Why creating a slice with variable length is slower?

4

Using make([]byte, tamanho) it behaves differently when tamanho is a variable or a constant.

Consider the two codes:

package Testes

import (
    "testing"
)

func BenchmarkConstante(b *testing.B) {
    const tamanho = 1024
    for n := 0; n < b.N; n++ {
        _ = make([]byte, tamanho)
    }
}
func BenchmarkVariavel(b *testing.B) {
    var tamanho = 1024
    for n := 0; n < b.N; n++ {
        _ = make([]byte, tamanho)
    }
}
  

The only difference between the two is const and var .

They return:

50000000            35.5 ns/op
10000000           181 ns/op

Both have the same% w / o of 1024. The only difference is that the first is constant (it also has the same effect if you use tamanho directly), but the second case is slower than the first.

Using the first form can be five times faster than using a variable. Now, why does this occur? Why use a variable value can have a difference so large ?

I think both are fast enough, but what's strange is that there's such a difference for something so simple.

My guess is that the compiler can reduce something when using a constant value. Meanwhile, using a variable would add some other checks, for example check if the value is less than zero, this does not need to use a constant value, since this is done at the time it compiles.

I think it might be something like this, but what exactly would it be?

    
asked by anonymous 07.06.2018 / 00:19

1 answer

2

In golang when you create a constant it is a literal, scalar value that may or may not be named. In other words, its value or expression gets directly set at compile time as if we had written directly into the code. Let's look at two cases:

In the first, we write a constant and then two variables and then its concatenation. In the second case, we only change v1 to be a constant. The result in both cases is Hello, Ari , however the compile behavior is different.

//primeiro caso
func main() {
    const v0 = "Hello, "
    var v1 = "Ari"
    var v2 = v0 + v1
    println(v2)
}

//segundo caso
func main() {
    const v0 = "Hello, "
    const v1 = "Ari"
    var v2 = v0 + v1
    println(v2)
}

In the first case there is an allocation of v1 to the heap and this causes the concatenation operation to fetch the value and then concatenate. See:

Inthesecondcaseitisthesameaswritingliterally'''v2="Hello, Ari", see:

Inthisway,thecostoffetchingthevalueandthenoperatingonitismorecostlythankeepingthevaluedirectlyinthecompiledcode.Thisisobvious!Technically,itcanbesaidthatconstworkatcompiletimeandvarworkatruntime.

Thatsaid,wecaneasilyunderstandthatifweconsumetheheapwiththisconstant,thecostofkeepingittheredoesnotcompensateanymorewhencomparedtoavariable.Thatis,ifyouliterallygraduallyincreasethesizeofyoursliceyouwillseethattherewillcomeatimewherebothconstantsandvariableshavethesamecost.So,ifyouuse[const|var]tamanho=64*1024,theresultwillbeasfollows(thefirstis16*1024andthesecondis64*1024):

P.S .: The difference in the second case is insignificant, given several executions.

    
11.06.2018 / 16:07