Pregunta Cualquiera puede dar sentido a 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,
}

No puedo entender el truco con connStateInterface, ¿cómo funciona exactamente?


5
2017-07-13 06:45


origen


Respuestas:


Hay algunas cosas pasando aquí ...

los [...] La declaración crea una matriz real en lugar de una división, de modo que se elimina la indirección. Lo que se declara aquí es una serie de interface{} tipos ... así que podrías preguntarte por qué la extraña notación de mapa?

los StateXXX las variables son simplemente constantes declaradas más arriba, así que son ints ... así que la declaración es en realidad de la forma index: value.

Aquí hay un ejemplo menos confuso de eso usando una matriz de entradas:

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

Esto asignará una matriz que contiene:

[0, 0, 7, 0, 2]

... tenga en cuenta que el índice 2 tiene 7, el índice 4 tiene 2. No es una forma común de declarar una matriz, pero es válido Ir.

Así que volviendo a la declaración original, simplemente tome el ejemplo que di anteriormente, y en lugar de int, haga la matriz de tipo interface{}:

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

Y obtendrás una matriz similar, pero con nil Interfaz de valores en lugar de ceros.

Acercándose aún más al código original, el StateXXX las constantes son solo ints, pero no los literales como en mi ejemplo.

Entonces, ¿cuál es el punto de todo esto? ¿Por qué toda la ofuscación?

Es un hack de rendimiento. La función c.curState.Store() toma un argumento de tipo interface{}. Si tuviera que pasarlo un int, el código compilado tendría que buscar la conversión del tipo en cada llamada. Una ilustración más clara (aunque obviamente impráctica) de esto podría ser:

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
}

Cada vez que hagas val = i una conversión entre int y interface{} tiene que pasar El código que publicaste evita esto al crear una tabla de búsqueda estática donde todos los valores son ya de tipo interfaz.

Por lo tanto, esto:

c.curState.Store(connStateInterface[state])

Es más eficiente que esto:

c.curState.Store(state)

Ya que state sería, en este caso, necesario someterse a la int -> interface{} conversión. En el código optimizado, state es simplemente un índice que busca un valor en una matriz, cuyo resultado le da una interface{}... entonces el int -> interface{} Se evita la conversión de tipo.

No estoy familiarizado con ese código, pero me imagino que se encuentra en una ruta crítica y que los nanosegundos o cualquier ahorro que se haya recortado probablemente hagan una diferencia.


7
2017-07-13 07:21