Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any one can make sense of connStateInterface?

Tags:

go

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?

like image 280
user3698446 Avatar asked Jul 13 '18 06:07

user3698446


People also ask

Who said nobody can make you feel inferior without your consent?

consent.” Eleanor Roosevelt said that. It's one of my favorite.

What is Eleanor Roosevelt famous quote?

“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.”

Did Eleanor Roosevelt say no one can make you feel inferior?

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].

Do not let anyone make you feel inferior?

“No one can make you feel inferior without your consent.” ~ Eleanor Roosevelt.


1 Answers

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.

like image 193
Eddy R. Avatar answered Oct 10 '22 12:10

Eddy R.