dsepcxw181184853 2018-07-13 06:45
浏览 33
已采纳

任何人都可以理解connStateInterface吗?

func (c *conn) setState(nc net.Conn, state ConnState) {
    ...
    c.curState.Store(connStateInterface[state])
    ...
}

// connStateInterface is an array of the interface{} versions of
// ConnState values, so we can use them in atomic.Values later without
// paying the cost of shoving their integers in an interface{}.
var connStateInterface = [...]interface{}{
    StateNew:      StateNew,
    StateActive:   StateActive,
    StateIdle:     StateIdle,
    StateHijacked: StateHijacked,
    StateClosed:   StateClosed,
}

I can't figure out the trick with connStateInterface, how exactly does it work?

  • 写回答

1条回答 默认 最新

  • dpfw3607 2018-07-13 07:21
    关注

    There's a few things going on here...

    The [...] declaration creates an actual array instead of a slice, so that indirection is removed. What's being declared here is an array of interface{} types... so you might wonder why the weird map-looking notation?

    The StateXXX variables are simply constants declared further above, so they are ints... so the declaration is actually of the form index: value.

    Here's a less obfuscated example of that using an array of ints:

    var i = [...]int{4: 2, 2: 7}
    

    This will allocate an array containing:

    [0, 0, 7, 0, 2]
    

    ... note that index 2 has 7, index 4 has 2. Not a common way of declaring an array, but it's valid Go.

    So going back to the original declaration, just take the example I gave above, and instead of int, make the array of type interface{}:

    var i = [...]interface{}{4: 2, 2: 7}
    

    And you'll get a similar array, but with nil interface values in place of zeroes.

    Getting even closer to the original code, the StateXXX constants are just ints, only not literals like in my example.

    So, what's the point of all this? Why all the obfuscation?

    It's a performance hack. The function c.curState.Store() takes an argument of type interface{}. If you were to pass it an int, the compiled code would have to fumble about with converting the type on each call. A more clear (though obviously impractical) illustration of this might be:

    var val interface{}
    
    for i := 0; i < 1000000; i++ {
        // the types are different, compiler has to fumble int vs. interface{}
        val = i
        // do something with val
    }
    

    Every time you do val = i a conversion between int and interface{} needs to happen. The code you posted avoids this by creating a static lookup table where all the values are already of type interface.

    Therefore, this:

    c.curState.Store(connStateInterface[state])
    

    is more efficient than this:

    c.curState.Store(state)
    

    Since state would, in this case, need to undergo the int -> interface{} conversion. In the optimized code, state is merely an index looking up a value into an array, the result of which gets you an interface{}... so the int -> interface{} type conversion is avoided.

    I'm not familiar with that code, but I'd imagine it's in a critical path and the nanoseconds or whatever savings shaved off likely makes a difference.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度