1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
// +build !appengine,!appenginevm
package jsonparser
import (
"reflect"
"strings"
"testing"
"unsafe"
)
var (
// short string/[]byte sequences, as the difference between these
// three methods is a constant overhead
benchmarkString = "0123456789x"
benchmarkBytes = []byte("0123456789y")
)
func bytesEqualStrSafe(abytes []byte, bstr string) bool {
return bstr == string(abytes)
}
func bytesEqualStrUnsafeSlower(abytes *[]byte, bstr string) bool {
aslicehdr := (*reflect.SliceHeader)(unsafe.Pointer(abytes))
astrhdr := reflect.StringHeader{Data: aslicehdr.Data, Len: aslicehdr.Len}
return *(*string)(unsafe.Pointer(&astrhdr)) == bstr
}
func TestEqual(t *testing.T) {
if !equalStr(&[]byte{}, "") {
t.Errorf(`equalStr("", ""): expected true, obtained false`)
return
}
longstr := strings.Repeat("a", 1000)
for i := 0; i < len(longstr); i++ {
s1, s2 := longstr[:i]+"1", longstr[:i]+"2"
b1 := []byte(s1)
if !equalStr(&b1, s1) {
t.Errorf(`equalStr("a"*%d + "1", "a"*%d + "1"): expected true, obtained false`, i, i)
break
}
if equalStr(&b1, s2) {
t.Errorf(`equalStr("a"*%d + "1", "a"*%d + "2"): expected false, obtained true`, i, i)
break
}
}
}
func BenchmarkEqualStr(b *testing.B) {
for i := 0; i < b.N; i++ {
equalStr(&benchmarkBytes, benchmarkString)
}
}
// Alternative implementation without using unsafe
func BenchmarkBytesEqualStrSafe(b *testing.B) {
for i := 0; i < b.N; i++ {
bytesEqualStrSafe(benchmarkBytes, benchmarkString)
}
}
// Alternative implementation using unsafe, but that is slower than the current implementation
func BenchmarkBytesEqualStrUnsafeSlower(b *testing.B) {
for i := 0; i < b.N; i++ {
bytesEqualStrUnsafeSlower(&benchmarkBytes, benchmarkString)
}
}
|