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?
consent.” Eleanor Roosevelt said that. It's one of my favorite.
“Remember always that you have not only the right to be an individual; you have an obligation to be one. You cannot make any useful contribution in life unless you do this.”
Eleanor Roosevelt, First Lady: “No one can make you feel inferior without your consent.” In June of 1941 the aphorism appeared on a newspaper page dedicated to the topics of “Home, Church, Religion, Character” within a column titled “Sermonograms”. The words were credited to Eleanor Roosevelt [HNFI].
“No one can make you feel inferior without your consent.” ~ Eleanor Roosevelt.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With