Val,

That's a lot of speculation!

The original benchmark applies to the original question:

   prefix := verylongstring[:3]

If we change the parameters of the benchmark then we expect to get 
different results. For example, read the Go gc compiler code. There's a 
stack/heap optimization for 32 bytes or less.

cmd/gc: allocate buffers for non-escaped strings on stack
commit    e6fac08146df323eb95f46508bef937cdfb802fd
https://go.googlesource.com/go/+/e6fac08146df323eb95f46508bef937cdfb802fd
https://go-review.googlesource.com/c/go/+/3120

3 byte prefix:

BenchmarkNil-4            10000000           173 ns/op          16 B/op    
       2 allocs/op
BenchmarkLiteral-4        10000000           171 ns/op          16 B/op    
       2 allocs/op
BenchmarkConvert-4        20000000            76.9 ns/op         3 B/op    
       1 allocs/op
BenchmarkCopy-4           20000000            67.1 ns/op         3 B/op    
       1 allocs/op
BenchmarkLoop-4           20000000            65.7 ns/op         3 B/op    
       1 allocs/op

32 byte prefix:

BenchmarkNil-4             5000000           235 ns/op          64 B/op    
       2 allocs/op
BenchmarkLiteral-4        10000000           232 ns/op          64 B/op    
       2 allocs/op
BenchmarkConvert-4        10000000           129 ns/op          32 B/op    
       1 allocs/op
BenchmarkCopy-4           10000000           118 ns/op          32 B/op    
       1 allocs/op
BenchmarkLoop-4           10000000           183 ns/op          32 B/op    
       1 allocs/op

33 byte prefix:

BenchmarkNil-4             5000000           295 ns/op          96 B/op    
       2 allocs/op
BenchmarkLiteral-4         5000000           285 ns/op          96 B/op    
       2 allocs/op
BenchmarkConvert-4         5000000           251 ns/op          96 B/op    
       2 allocs/op
BenchmarkCopy-4           10000000           143 ns/op          48 B/op    
       1 allocs/op
BenchmarkLoop-4           10000000           188 ns/op          48 B/op    
       1 allocs/op

256 byte prefix:

BenchmarkNil-4             2000000           661 ns/op         512 B/op    
       2 allocs/op
BenchmarkLiteral-4         2000000           665 ns/op         512 B/op    
       2 allocs/op
BenchmarkConvert-4         2000000           659 ns/op         512 B/op    
       2 allocs/op
BenchmarkCopy-4            5000000           369 ns/op         256 B/op    
       1 allocs/op
BenchmarkLoop-4            2000000           883 ns/op         256 B/op    
       1 allocs/op

$ go version
go version devel +33484a6 Tue Aug 22 08:09:42 2017 +0000 linux/amd64

$ go test -run=! -bench=. -benchmem strslice_test.go
goos: linux
goarch: amd64

https://play.golang.org/p/tAYyecoQXY

$ cat  strslice_test.go
package main

import (
    "strings"
    "testing"
)

const pfxLen = 3 // 3, 32, 33, 256

var (
    s      = strings.Repeat("a very, very long string", 4096)
    prefix string
)

func BenchmarkNil(b *testing.B) {
    for i := 0; i < b.N; i++ {
        prefix = string(append([]byte(nil), s[:pfxLen]...))
    }
}

func BenchmarkLiteral(b *testing.B) {
    for i := 0; i < b.N; i++ {
        prefix = string(append([]byte{}, s[:pfxLen]...))
    }
}

func BenchmarkConvert(b *testing.B) {
    for i := 0; i < b.N; i++ {
        prefix = string([]byte(s[:pfxLen]))
    }
}

func BenchmarkCopy(b *testing.B) {
    for i := 0; i < b.N; i++ {
        buffer := make([]byte, pfxLen)
        copy(buffer, s)
        prefix = string(buffer)
    }
}

func BenchmarkLoop(b *testing.B) {
    for i := 0; i < b.N; i++ {
        buffer := make([]byte, pfxLen)
        for i := 0; i < len(buffer); i++ {
            buffer[i] = s[i]
        }
        prefix = string(buffer)
    }
}
$

Peter


On Tuesday, August 22, 2017 at 8:07:01 AM UTC-4, Val wrote:
>
> FWIW, append is most often a small performance penalty when the number of 
> elements is known ahead.
> And for some reason, using built-in func copy, or an explicit loop, is 
> slightly faster on my workstation than BenchmarkConvert.
> Also, "small benchmarks are hard" so I suspect the small allocations in 
> tight benchmark loops may not be representative of their real cost in a 
> real program.
>
>
> func BenchmarkCopy(b *testing.B) {
>     for i := 0; i < b.N; i++ {
>         buffer := make([]byte, 3)
>         copy(buffer, s[:3])
>         prefix = string(buffer)
>     }
> }
>
> func BenchmarkLoop(b *testing.B) {
>     for i := 0; i < b.N; i++ {
>         buffer := make([]byte, 3)
>         for i := 0; i < 3; i++ {
>             buffer[i] = s[i]
>         }
>         prefix = string(buffer)
>     }
> }
>
>
> BenchmarkNil-4           30000000            61.9 ns/op          16 
> B/op           2 allocs/op
> BenchmarkLiteral-4       30000000            59.6 ns/op          16 
> B/op           2 allocs/op
> BenchmarkConvert-4       50000000            37.4 ns/op           3 
> B/op           1 allocs/op
> BenchmarkCopy-4          50000000            30.8 ns/op           3 
> B/op           1 allocs/op
> BenchmarkLoop-4          50000000            29.3 ns/op           3 
> B/op           1 allocs/op
>
> Cheers
> Val
>
> On Tuesday, August 22, 2017 at 1:01:36 PM UTC+2, peterGo wrote:
>>
>> A benchmark;
>>
>> https://play.golang.org/p/oUyeldDG5Q
>>
>> $ cat strslice_test.go
>> package main
>>
>> import (
>>     "strings"
>>     "testing"
>> )
>>
>> var (
>>     s      = strings.Repeat("a very, very long string", 4096)
>>     prefix string
>> )
>>
>> func BenchmarkNil(b *testing.B) {
>>     for i := 0; i < b.N; i++ {
>>         prefix = string(append([]byte(nil), s[:3]...))
>>     }
>> }
>>
>> func BenchmarkLiteral(b *testing.B) {
>>     for i := 0; i < b.N; i++ {
>>         prefix = string(append([]byte{}, s[:3]...))
>>     }
>> }
>>
>> func BenchmarkConvert(b *testing.B) {
>>     for i := 0; i < b.N; i++ {
>>         prefix = string([]byte(s[:3]))
>>     }
>> }
>>
>> $ go test -run=! -bench=. -benchmem strslice_test.go
>> goos: linux
>> goarch: amd64
>> BenchmarkNil-4           10000000           174 ns/op          16 B/op    
>>        2 allocs/op
>> BenchmarkLiteral-4       10000000           174 ns/op          16 B/op    
>>        2 allocs/op
>> BenchmarkConvert-4       20000000            77.0 ns/op         3 B/op    
>>        1 allocs/op
>> PASS
>> ok      command-line-arguments    5.512s
>> $
>>
>> Peter
>>
>> On Tuesday, August 22, 2017 at 12:15:44 AM UTC-4, Tamás Gulácsi wrote:
>>>
>>> prefix := string([]byte(verylongstring[:3]))
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to