go/src/bytes/bytes_test.go

1451 lines
34 KiB
Go
Raw Normal View History

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bytes_test
import (
. "bytes"
"fmt"
"internal/testenv"
"math/rand"
"reflect"
"strings"
"testing"
"unicode"
"unicode/utf8"
)
func eq(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
func sliceOfString(s [][]byte) []string {
result := make([]string, len(s))
for i, v := range s {
result[i] = string(v)
}
return result
}
// For ease of reading, the test cases use strings that are converted to byte
// slices before invoking the functions.
var abcd = "abcd"
var faces = "☺☻☹"
var commas = "1,2,3,4"
var dots = "1....2....3....4"
type BinOpTest struct {
a string
b string
i int
}
func TestEqual(t *testing.T) {
for _, tt := range compareTests {
eql := Equal(tt.a, tt.b)
if eql != (tt.i == 0) {
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
}
eql = EqualPortable(tt.a, tt.b)
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
if eql != (tt.i == 0) {
t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql)
}
}
}
func TestEqualExhaustive(t *testing.T) {
var size = 128
if testing.Short() {
size = 32
}
a := make([]byte, size)
b := make([]byte, size)
b_init := make([]byte, size)
// randomish but deterministic data
for i := 0; i < size; i++ {
a[i] = byte(17 * i)
b_init[i] = byte(23*i + 100)
}
for len := 0; len <= size; len++ {
for x := 0; x <= size-len; x++ {
for y := 0; y <= size-len; y++ {
copy(b, b_init)
copy(b[y:y+len], a[x:x+len])
if !Equal(a[x:x+len], b[y:y+len]) || !Equal(b[y:y+len], a[x:x+len]) {
t.Errorf("Equal(%d, %d, %d) = false", len, x, y)
}
}
}
}
}
// make sure Equal returns false for minimally different strings. The data
// is all zeros except for a single one in one location.
func TestNotEqual(t *testing.T) {
var size = 128
if testing.Short() {
size = 32
}
a := make([]byte, size)
b := make([]byte, size)
for len := 0; len <= size; len++ {
for x := 0; x <= size-len; x++ {
for y := 0; y <= size-len; y++ {
for diffpos := x; diffpos < x+len; diffpos++ {
a[diffpos] = 1
if Equal(a[x:x+len], b[y:y+len]) || Equal(b[y:y+len], a[x:x+len]) {
t.Errorf("NotEqual(%d, %d, %d, %d) = true", len, x, y, diffpos)
}
a[diffpos] = 0
}
}
}
}
}
var indexTests = []BinOpTest{
{"", "", 0},
{"", "a", -1},
{"", "foo", -1},
{"fo", "foo", -1},
{"foo", "baz", -1},
{"foo", "foo", 0},
{"oofofoofooo", "f", 2},
{"oofofoofooo", "foo", 4},
{"barfoobarfoo", "foo", 3},
{"foo", "", 0},
{"foo", "o", 1},
{"abcABCabc", "A", 3},
// cases with one byte strings - test IndexByte and special case in Index()
{"", "a", -1},
{"x", "a", -1},
{"x", "x", 0},
{"abc", "a", 0},
{"abc", "b", 1},
{"abc", "c", 2},
{"abc", "x", -1},
{"barfoobarfooyyyzzzyyyzzzyyyzzzyyyxxxzzzyyy", "x", 33},
{"foofyfoobarfoobar", "y", 4},
{"oooooooooooooooooooooo", "r", -1},
}
var lastIndexTests = []BinOpTest{
{"", "", 0},
{"", "a", -1},
{"", "foo", -1},
{"fo", "foo", -1},
{"foo", "foo", 0},
{"foo", "f", 0},
{"oofofoofooo", "f", 7},
{"oofofoofooo", "foo", 7},
{"barfoobarfoo", "foo", 9},
{"foo", "", 3},
{"foo", "o", 2},
{"abcABCabc", "A", 3},
{"abcABCabc", "a", 6},
}
var indexAnyTests = []BinOpTest{
{"", "", -1},
{"", "a", -1},
{"", "abc", -1},
{"a", "", -1},
{"a", "a", 0},
{"aaa", "a", 0},
{"abc", "xyz", -1},
{"abc", "xcz", 2},
{"ab☺c", "x☺yz", 2},
{"aRegExp*", ".(|)*+?^$[]", 7},
{dots + dots + dots, " ", -1},
}
var lastIndexAnyTests = []BinOpTest{
{"", "", -1},
{"", "a", -1},
{"", "abc", -1},
{"a", "", -1},
{"a", "a", 0},
{"aaa", "a", 2},
{"abc", "xyz", -1},
{"abc", "ab", 1},
{"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
{"a.RegExp*", ".(|)*+?^$[]", 8},
{dots + dots + dots, " ", -1},
}
// Execute f on each test case. funcName should be the name of f; it's used
// in failure reports.
func runIndexTests(t *testing.T, f func(s, sep []byte) int, funcName string, testCases []BinOpTest) {
for _, test := range testCases {
a := []byte(test.a)
b := []byte(test.b)
actual := f(a, b)
if actual != test.i {
t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, b, actual, test.i)
}
}
}
func runIndexAnyTests(t *testing.T, f func(s []byte, chars string) int, funcName string, testCases []BinOpTest) {
for _, test := range testCases {
a := []byte(test.a)
actual := f(a, test.b)
if actual != test.i {
t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, test.b, actual, test.i)
}
}
}
func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }
func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
func TestIndexAny(t *testing.T) { runIndexAnyTests(t, IndexAny, "IndexAny", indexAnyTests) }
func TestLastIndexAny(t *testing.T) {
runIndexAnyTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests)
}
func TestIndexByte(t *testing.T) {
for _, tt := range indexTests {
if len(tt.b) != 1 {
continue
}
a := []byte(tt.a)
b := tt.b[0]
pos := IndexByte(a, b)
if pos != tt.i {
t.Errorf(`IndexByte(%q, '%c') = %v`, tt.a, b, pos)
}
posp := IndexBytePortable(a, b)
bytes: asm for bytes.IndexByte PERFORMANCE DIFFERENCE SUMMARY amd64 386 2.2 GHz AMD Opteron 8214 HE (Linux) 3.0x faster 8.2x faster 3.60 GHz Intel Xeon (Linux) 2.2x faster 6.2x faster 2.53 GHz Intel Core2 Duo E7200 (Linux) 1.5x faster 4.4x faster 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Xeon E5435 (Linux) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) 1.4x SLOWER 3.0x faster 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) none* 3.0x faster * but yesterday I consistently saw 1.4x SLOWER. DETAILS 2.2 GHz AMD Opteron 8214 HE (Linux) amd64 (3x faster) IndexByte4K 500000 3733 ns/op 1097.24 MB/s IndexByte4M 500 4328042 ns/op 969.10 MB/s IndexByte64M 50 67866160 ns/op 988.84 MB/s IndexBytePortable4K 200000 11161 ns/op 366.99 MB/s IndexBytePortable4M 100 11795880 ns/op 355.57 MB/s IndexBytePortable64M 10 188675000 ns/op 355.68 MB/s 386 (8.2x faster) IndexByte4K 500000 3734 ns/op 1096.95 MB/s IndexByte4M 500 4209954 ns/op 996.28 MB/s IndexByte64M 50 68031980 ns/op 986.43 MB/s IndexBytePortable4K 50000 30670 ns/op 133.55 MB/s IndexBytePortable4M 50 31868220 ns/op 131.61 MB/s IndexBytePortable64M 2 508851500 ns/op 131.88 MB/s 3.60 GHz Intel Xeon (Linux) amd64 (2.2x faster) IndexByte4K 500000 4612 ns/op 888.12 MB/s IndexByte4M 500 4835250 ns/op 867.44 MB/s IndexByte64M 20 77388450 ns/op 867.17 MB/s IndexBytePortable4K 200000 10306 ns/op 397.44 MB/s IndexBytePortable4M 100 11201460 ns/op 374.44 MB/s IndexBytePortable64M 10 179456800 ns/op 373.96 MB/s 386 (6.3x faster) IndexByte4K 500000 4631 ns/op 884.47 MB/s IndexByte4M 500 4846388 ns/op 865.45 MB/s IndexByte64M 20 78691200 ns/op 852.81 MB/s IndexBytePortable4K 100000 28989 ns/op 141.29 MB/s IndexBytePortable4M 50 31183180 ns/op 134.51 MB/s IndexBytePortable64M 5 498347200 ns/op 134.66 MB/s 2.53 GHz Intel Core2 Duo E7200 (Linux) amd64 (1.5x faster) IndexByte4K 500000 6502 ns/op 629.96 MB/s IndexByte4M 500 6692208 ns/op 626.74 MB/s IndexByte64M 10 107410400 ns/op 624.79 MB/s IndexBytePortable4K 200000 9721 ns/op 421.36 MB/s IndexBytePortable4M 100 10013680 ns/op 418.86 MB/s IndexBytePortable64M 10 160460800 ns/op 418.23 MB/s 386 (4.4x faster) IndexByte4K 500000 6505 ns/op 629.67 MB/s IndexByte4M 500 6694078 ns/op 626.57 MB/s IndexByte64M 10 107397600 ns/op 624.86 MB/s IndexBytePortable4K 100000 28835 ns/op 142.05 MB/s IndexBytePortable4M 50 29562680 ns/op 141.88 MB/s IndexBytePortable64M 5 473221400 ns/op 141.81 MB/s 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) amd64 (1.5x SLOWER) IndexByte4K 200000 9290 ns/op 440.90 MB/s IndexByte4M 200 9568925 ns/op 438.33 MB/s IndexByte64M 10 154473600 ns/op 434.44 MB/s IndexBytePortable4K 500000 6202 ns/op 660.43 MB/s IndexBytePortable4M 500 6583614 ns/op 637.08 MB/s IndexBytePortable64M 20 107166250 ns/op 626.21 MB/s 386 (3x faster) IndexByte4K 200000 9301 ns/op 440.38 MB/s IndexByte4M 200 9568025 ns/op 438.37 MB/s IndexByte64M 10 154391000 ns/op 434.67 MB/s IndexBytePortable4K 100000 27526 ns/op 148.80 MB/s IndexBytePortable4M 100 28302490 ns/op 148.20 MB/s IndexBytePortable64M 5 454170200 ns/op 147.76 MB/s 2.33 GHz Intel Xeon E5435 (Linux) amd64 (1.5x SLOWER) IndexByte4K 200000 10601 ns/op 386.38 MB/s IndexByte4M 100 10827240 ns/op 387.38 MB/s IndexByte64M 10 173175500 ns/op 387.52 MB/s IndexBytePortable4K 500000 7082 ns/op 578.37 MB/s IndexBytePortable4M 500 7391792 ns/op 567.43 MB/s IndexBytePortable64M 20 122618550 ns/op 547.30 MB/s 386 (3x faster) IndexByte4K 200000 11074 ns/op 369.88 MB/s IndexByte4M 100 10902620 ns/op 384.71 MB/s IndexByte64M 10 181292800 ns/op 370.17 MB/s IndexBytePortable4K 50000 31725 ns/op 129.11 MB/s IndexBytePortable4M 50 32564880 ns/op 128.80 MB/s IndexBytePortable64M 2 545926000 ns/op 122.93 MB/s 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) amd64 (1.4x SLOWER) IndexByte4K 200000 11120 ns/op 368.35 MB/s IndexByte4M 100 11531950 ns/op 363.71 MB/s IndexByte64M 10 184819000 ns/op 363.11 MB/s IndexBytePortable4K 500000 7419 ns/op 552.10 MB/s IndexBytePortable4M 200 8018710 ns/op 523.06 MB/s IndexBytePortable64M 10 127614900 ns/op 525.87 MB/s 386 (3x faster) IndexByte4K 200000 11114 ns/op 368.54 MB/s IndexByte4M 100 11443530 ns/op 366.52 MB/s IndexByte64M 10 185212000 ns/op 362.34 MB/s IndexBytePortable4K 50000 32891 ns/op 124.53 MB/s IndexBytePortable4M 50 33930580 ns/op 123.61 MB/s IndexBytePortable64M 2 545400500 ns/op 123.05 MB/s 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) amd64 (no difference) IndexByte4K 200000 13497 ns/op 303.47 MB/s IndexByte4M 100 13890650 ns/op 301.95 MB/s IndexByte64M 5 222358000 ns/op 301.81 MB/s IndexBytePortable4K 200000 13584 ns/op 301.53 MB/s IndexBytePortable4M 100 13913280 ns/op 301.46 MB/s IndexBytePortable64M 10 222572600 ns/op 301.51 MB/s 386 (3x faster) IndexByte4K 200000 13565 ns/op 301.95 MB/s IndexByte4M 100 13882640 ns/op 302.13 MB/s IndexByte64M 5 221411600 ns/op 303.10 MB/s IndexBytePortable4K 50000 39978 ns/op 102.46 MB/s IndexBytePortable4M 50 41038160 ns/op 102.20 MB/s IndexBytePortable64M 2 656362500 ns/op 102.24 MB/s R=r CC=golang-dev https://golang.org/cl/166055
2009-12-04 10:23:43 -08:00
if posp != tt.i {
t.Errorf(`indexBytePortable(%q, '%c') = %v`, tt.a, b, posp)
}
}
}
func TestLastIndexByte(t *testing.T) {
testCases := []BinOpTest{
{"", "q", -1},
{"abcdef", "q", -1},
{"abcdefabcdef", "a", len("abcdef")}, // something in the middle
{"abcdefabcdef", "f", len("abcdefabcde")}, // last byte
{"zabcdefabcdef", "z", 0}, // first byte
{"a☺b☻c☹d", "b", len("a☺")}, // non-ascii
}
for _, test := range testCases {
actual := LastIndexByte([]byte(test.a), test.b[0])
if actual != test.i {
t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.a, test.b[0], actual, test.i)
}
}
}
// test a larger buffer with different sizes and alignments
func TestIndexByteBig(t *testing.T) {
var n = 1024
if testing.Short() {
n = 128
}
b := make([]byte, n)
for i := 0; i < n; i++ {
// different start alignments
b1 := b[i:]
for j := 0; j < len(b1); j++ {
b1[j] = 'x'
pos := IndexByte(b1, 'x')
if pos != j {
t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
}
b1[j] = 0
pos = IndexByte(b1, 'x')
if pos != -1 {
t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
}
}
// different end alignments
b1 = b[:i]
for j := 0; j < len(b1); j++ {
b1[j] = 'x'
pos := IndexByte(b1, 'x')
if pos != j {
t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
}
b1[j] = 0
pos = IndexByte(b1, 'x')
if pos != -1 {
t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
}
}
// different start and end alignments
b1 = b[i/2 : n-(i+1)/2]
for j := 0; j < len(b1); j++ {
b1[j] = 'x'
pos := IndexByte(b1, 'x')
if pos != j {
t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
}
b1[j] = 0
pos = IndexByte(b1, 'x')
if pos != -1 {
t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)
}
}
}
}
// test a small index across all page offsets
func TestIndexByteSmall(t *testing.T) {
b := make([]byte, 5015) // bigger than a page
// Make sure we find the correct byte even when straddling a page.
for i := 0; i <= len(b)-15; i++ {
for j := 0; j < 15; j++ {
b[i+j] = byte(100 + j)
}
for j := 0; j < 15; j++ {
p := IndexByte(b[i:i+15], byte(100+j))
if p != j {
t.Errorf("IndexByte(%q, %d) = %d", b[i:i+15], 100+j, p)
}
}
for j := 0; j < 15; j++ {
b[i+j] = 0
}
}
// Make sure matches outside the slice never trigger.
for i := 0; i <= len(b)-15; i++ {
for j := 0; j < 15; j++ {
b[i+j] = 1
}
for j := 0; j < 15; j++ {
p := IndexByte(b[i:i+15], byte(0))
if p != -1 {
t.Errorf("IndexByte(%q, %d) = %d", b[i:i+15], 0, p)
}
}
for j := 0; j < 15; j++ {
b[i+j] = 0
}
}
}
func TestIndexRune(t *testing.T) {
tests := []struct {
in string
rune rune
want int
}{
{"", 'a', -1},
{"", '☺', -1},
{"foo", '☹', -1},
{"foo", 'o', 1},
{"foo☺bar", '☺', 3},
{"foo☺☻☹bar", '☹', 9},
{"a A x", 'A', 2},
{"some_text=some_value", '=', 9},
{"☺a", 'a', 3},
{"a☻☺b", '☺', 4},
// RuneError should match any invalid UTF-8 byte sequence.
{"<22>", '<27>', 0},
{"\xff", '<27>', 0},
{"☻x<E298BB>", '<27>', len("☻x")},
{"☻x\xe2\x98", '<27>', len("☻x")},
{"☻x\xe2\x98<39>", '<27>', len("☻x")},
{"☻x\xe2\x98x", '<27>', len("☻x")},
// Invalid rune values should never match.
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", -1, -1},
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", 0xD800, -1}, // Surrogate pair
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", utf8.MaxRune + 1, -1},
}
for _, tt := range tests {
if got := IndexRune([]byte(tt.in), tt.rune); got != tt.want {
t.Errorf("IndexRune(%q, %d) = %v; want %v", tt.in, tt.rune, got, tt.want)
}
}
bytes: make IndexRune faster re-implement IndexRune by IndexByte and Index which are well optimized to get performance gain. name old time/op new time/op delta IndexRune/10-4 53.2ns ± 1% 29.1ns ± 1% -45.32% (p=0.008 n=5+5) IndexRune/32-4 191ns ± 1% 27ns ± 1% -85.75% (p=0.008 n=5+5) IndexRune/4K-4 23.5µs ± 1% 1.0µs ± 1% -95.77% (p=0.008 n=5+5) IndexRune/4M-4 23.8ms ± 0% 1.0ms ± 2% -95.90% (p=0.008 n=5+5) IndexRune/64M-4 384ms ± 1% 15ms ± 1% -95.98% (p=0.008 n=5+5) IndexRuneASCII/10-4 61.5ns ± 0% 10.3ns ± 4% -83.17% (p=0.008 n=5+5) IndexRuneASCII/32-4 203ns ± 0% 11ns ± 5% -94.68% (p=0.008 n=5+5) IndexRuneASCII/4K-4 23.4µs ± 0% 0.3µs ± 2% -98.60% (p=0.008 n=5+5) IndexRuneASCII/4M-4 24.0ms ± 1% 0.3ms ± 1% -98.60% (p=0.008 n=5+5) IndexRuneASCII/64M-4 386ms ± 2% 6ms ± 1% -98.57% (p=0.008 n=5+5) name old speed new speed delta IndexRune/10-4 188MB/s ± 1% 344MB/s ± 1% +82.91% (p=0.008 n=5+5) IndexRune/32-4 167MB/s ± 0% 1175MB/s ± 1% +603.52% (p=0.008 n=5+5) IndexRune/4K-4 174MB/s ± 1% 4117MB/s ± 1% +2262.71% (p=0.008 n=5+5) IndexRune/4M-4 176MB/s ± 0% 4299MB/s ± 2% +2340.46% (p=0.008 n=5+5) IndexRune/64M-4 175MB/s ± 1% 4354MB/s ± 1% +2388.57% (p=0.008 n=5+5) IndexRuneASCII/10-4 163MB/s ± 0% 968MB/s ± 4% +494.66% (p=0.008 n=5+5) IndexRuneASCII/32-4 157MB/s ± 0% 2974MB/s ± 4% +1788.59% (p=0.008 n=5+5) IndexRuneASCII/4K-4 175MB/s ± 0% 12481MB/s ± 2% +7027.71% (p=0.008 n=5+5) IndexRuneASCII/4M-4 175MB/s ± 1% 12510MB/s ± 1% +7061.15% (p=0.008 n=5+5) IndexRuneASCII/64M-4 174MB/s ± 2% 12143MB/s ± 1% +6881.70% (p=0.008 n=5+5) Change-Id: I0632eadb83937c2a9daa7f0ce79df1dee64f992e Reviewed-on: https://go-review.googlesource.com/28537 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-06 08:09:27 +09:00
haystack := []byte("test世界")
allocs := testing.AllocsPerRun(1000, func() {
if i := IndexRune(haystack, 's'); i != 2 {
t.Fatalf("'s' at %d; want 2", i)
}
if i := IndexRune(haystack, '世'); i != 4 {
t.Fatalf("'世' at %d; want 4", i)
}
})
if allocs != 0 {
t.Errorf("expected no allocations, got %f", allocs)
bytes: make IndexRune faster re-implement IndexRune by IndexByte and Index which are well optimized to get performance gain. name old time/op new time/op delta IndexRune/10-4 53.2ns ± 1% 29.1ns ± 1% -45.32% (p=0.008 n=5+5) IndexRune/32-4 191ns ± 1% 27ns ± 1% -85.75% (p=0.008 n=5+5) IndexRune/4K-4 23.5µs ± 1% 1.0µs ± 1% -95.77% (p=0.008 n=5+5) IndexRune/4M-4 23.8ms ± 0% 1.0ms ± 2% -95.90% (p=0.008 n=5+5) IndexRune/64M-4 384ms ± 1% 15ms ± 1% -95.98% (p=0.008 n=5+5) IndexRuneASCII/10-4 61.5ns ± 0% 10.3ns ± 4% -83.17% (p=0.008 n=5+5) IndexRuneASCII/32-4 203ns ± 0% 11ns ± 5% -94.68% (p=0.008 n=5+5) IndexRuneASCII/4K-4 23.4µs ± 0% 0.3µs ± 2% -98.60% (p=0.008 n=5+5) IndexRuneASCII/4M-4 24.0ms ± 1% 0.3ms ± 1% -98.60% (p=0.008 n=5+5) IndexRuneASCII/64M-4 386ms ± 2% 6ms ± 1% -98.57% (p=0.008 n=5+5) name old speed new speed delta IndexRune/10-4 188MB/s ± 1% 344MB/s ± 1% +82.91% (p=0.008 n=5+5) IndexRune/32-4 167MB/s ± 0% 1175MB/s ± 1% +603.52% (p=0.008 n=5+5) IndexRune/4K-4 174MB/s ± 1% 4117MB/s ± 1% +2262.71% (p=0.008 n=5+5) IndexRune/4M-4 176MB/s ± 0% 4299MB/s ± 2% +2340.46% (p=0.008 n=5+5) IndexRune/64M-4 175MB/s ± 1% 4354MB/s ± 1% +2388.57% (p=0.008 n=5+5) IndexRuneASCII/10-4 163MB/s ± 0% 968MB/s ± 4% +494.66% (p=0.008 n=5+5) IndexRuneASCII/32-4 157MB/s ± 0% 2974MB/s ± 4% +1788.59% (p=0.008 n=5+5) IndexRuneASCII/4K-4 175MB/s ± 0% 12481MB/s ± 2% +7027.71% (p=0.008 n=5+5) IndexRuneASCII/4M-4 175MB/s ± 1% 12510MB/s ± 1% +7061.15% (p=0.008 n=5+5) IndexRuneASCII/64M-4 174MB/s ± 2% 12143MB/s ± 1% +6881.70% (p=0.008 n=5+5) Change-Id: I0632eadb83937c2a9daa7f0ce79df1dee64f992e Reviewed-on: https://go-review.googlesource.com/28537 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-06 08:09:27 +09:00
}
}
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
var bmbuf []byte
bytes: asm for bytes.IndexByte PERFORMANCE DIFFERENCE SUMMARY amd64 386 2.2 GHz AMD Opteron 8214 HE (Linux) 3.0x faster 8.2x faster 3.60 GHz Intel Xeon (Linux) 2.2x faster 6.2x faster 2.53 GHz Intel Core2 Duo E7200 (Linux) 1.5x faster 4.4x faster 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Xeon E5435 (Linux) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) 1.4x SLOWER 3.0x faster 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) none* 3.0x faster * but yesterday I consistently saw 1.4x SLOWER. DETAILS 2.2 GHz AMD Opteron 8214 HE (Linux) amd64 (3x faster) IndexByte4K 500000 3733 ns/op 1097.24 MB/s IndexByte4M 500 4328042 ns/op 969.10 MB/s IndexByte64M 50 67866160 ns/op 988.84 MB/s IndexBytePortable4K 200000 11161 ns/op 366.99 MB/s IndexBytePortable4M 100 11795880 ns/op 355.57 MB/s IndexBytePortable64M 10 188675000 ns/op 355.68 MB/s 386 (8.2x faster) IndexByte4K 500000 3734 ns/op 1096.95 MB/s IndexByte4M 500 4209954 ns/op 996.28 MB/s IndexByte64M 50 68031980 ns/op 986.43 MB/s IndexBytePortable4K 50000 30670 ns/op 133.55 MB/s IndexBytePortable4M 50 31868220 ns/op 131.61 MB/s IndexBytePortable64M 2 508851500 ns/op 131.88 MB/s 3.60 GHz Intel Xeon (Linux) amd64 (2.2x faster) IndexByte4K 500000 4612 ns/op 888.12 MB/s IndexByte4M 500 4835250 ns/op 867.44 MB/s IndexByte64M 20 77388450 ns/op 867.17 MB/s IndexBytePortable4K 200000 10306 ns/op 397.44 MB/s IndexBytePortable4M 100 11201460 ns/op 374.44 MB/s IndexBytePortable64M 10 179456800 ns/op 373.96 MB/s 386 (6.3x faster) IndexByte4K 500000 4631 ns/op 884.47 MB/s IndexByte4M 500 4846388 ns/op 865.45 MB/s IndexByte64M 20 78691200 ns/op 852.81 MB/s IndexBytePortable4K 100000 28989 ns/op 141.29 MB/s IndexBytePortable4M 50 31183180 ns/op 134.51 MB/s IndexBytePortable64M 5 498347200 ns/op 134.66 MB/s 2.53 GHz Intel Core2 Duo E7200 (Linux) amd64 (1.5x faster) IndexByte4K 500000 6502 ns/op 629.96 MB/s IndexByte4M 500 6692208 ns/op 626.74 MB/s IndexByte64M 10 107410400 ns/op 624.79 MB/s IndexBytePortable4K 200000 9721 ns/op 421.36 MB/s IndexBytePortable4M 100 10013680 ns/op 418.86 MB/s IndexBytePortable64M 10 160460800 ns/op 418.23 MB/s 386 (4.4x faster) IndexByte4K 500000 6505 ns/op 629.67 MB/s IndexByte4M 500 6694078 ns/op 626.57 MB/s IndexByte64M 10 107397600 ns/op 624.86 MB/s IndexBytePortable4K 100000 28835 ns/op 142.05 MB/s IndexBytePortable4M 50 29562680 ns/op 141.88 MB/s IndexBytePortable64M 5 473221400 ns/op 141.81 MB/s 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) amd64 (1.5x SLOWER) IndexByte4K 200000 9290 ns/op 440.90 MB/s IndexByte4M 200 9568925 ns/op 438.33 MB/s IndexByte64M 10 154473600 ns/op 434.44 MB/s IndexBytePortable4K 500000 6202 ns/op 660.43 MB/s IndexBytePortable4M 500 6583614 ns/op 637.08 MB/s IndexBytePortable64M 20 107166250 ns/op 626.21 MB/s 386 (3x faster) IndexByte4K 200000 9301 ns/op 440.38 MB/s IndexByte4M 200 9568025 ns/op 438.37 MB/s IndexByte64M 10 154391000 ns/op 434.67 MB/s IndexBytePortable4K 100000 27526 ns/op 148.80 MB/s IndexBytePortable4M 100 28302490 ns/op 148.20 MB/s IndexBytePortable64M 5 454170200 ns/op 147.76 MB/s 2.33 GHz Intel Xeon E5435 (Linux) amd64 (1.5x SLOWER) IndexByte4K 200000 10601 ns/op 386.38 MB/s IndexByte4M 100 10827240 ns/op 387.38 MB/s IndexByte64M 10 173175500 ns/op 387.52 MB/s IndexBytePortable4K 500000 7082 ns/op 578.37 MB/s IndexBytePortable4M 500 7391792 ns/op 567.43 MB/s IndexBytePortable64M 20 122618550 ns/op 547.30 MB/s 386 (3x faster) IndexByte4K 200000 11074 ns/op 369.88 MB/s IndexByte4M 100 10902620 ns/op 384.71 MB/s IndexByte64M 10 181292800 ns/op 370.17 MB/s IndexBytePortable4K 50000 31725 ns/op 129.11 MB/s IndexBytePortable4M 50 32564880 ns/op 128.80 MB/s IndexBytePortable64M 2 545926000 ns/op 122.93 MB/s 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) amd64 (1.4x SLOWER) IndexByte4K 200000 11120 ns/op 368.35 MB/s IndexByte4M 100 11531950 ns/op 363.71 MB/s IndexByte64M 10 184819000 ns/op 363.11 MB/s IndexBytePortable4K 500000 7419 ns/op 552.10 MB/s IndexBytePortable4M 200 8018710 ns/op 523.06 MB/s IndexBytePortable64M 10 127614900 ns/op 525.87 MB/s 386 (3x faster) IndexByte4K 200000 11114 ns/op 368.54 MB/s IndexByte4M 100 11443530 ns/op 366.52 MB/s IndexByte64M 10 185212000 ns/op 362.34 MB/s IndexBytePortable4K 50000 32891 ns/op 124.53 MB/s IndexBytePortable4M 50 33930580 ns/op 123.61 MB/s IndexBytePortable64M 2 545400500 ns/op 123.05 MB/s 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) amd64 (no difference) IndexByte4K 200000 13497 ns/op 303.47 MB/s IndexByte4M 100 13890650 ns/op 301.95 MB/s IndexByte64M 5 222358000 ns/op 301.81 MB/s IndexBytePortable4K 200000 13584 ns/op 301.53 MB/s IndexBytePortable4M 100 13913280 ns/op 301.46 MB/s IndexBytePortable64M 10 222572600 ns/op 301.51 MB/s 386 (3x faster) IndexByte4K 200000 13565 ns/op 301.95 MB/s IndexByte4M 100 13882640 ns/op 302.13 MB/s IndexByte64M 5 221411600 ns/op 303.10 MB/s IndexBytePortable4K 50000 39978 ns/op 102.46 MB/s IndexBytePortable4M 50 41038160 ns/op 102.20 MB/s IndexBytePortable64M 2 656362500 ns/op 102.24 MB/s R=r CC=golang-dev https://golang.org/cl/166055
2009-12-04 10:23:43 -08:00
func valName(x int) string {
if s := x >> 20; s<<20 == x {
return fmt.Sprintf("%dM", s)
}
if s := x >> 10; s<<10 == x {
return fmt.Sprintf("%dK", s)
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
}
return fmt.Sprint(x)
bytes: asm for bytes.IndexByte PERFORMANCE DIFFERENCE SUMMARY amd64 386 2.2 GHz AMD Opteron 8214 HE (Linux) 3.0x faster 8.2x faster 3.60 GHz Intel Xeon (Linux) 2.2x faster 6.2x faster 2.53 GHz Intel Core2 Duo E7200 (Linux) 1.5x faster 4.4x faster 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Xeon E5435 (Linux) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) 1.4x SLOWER 3.0x faster 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) none* 3.0x faster * but yesterday I consistently saw 1.4x SLOWER. DETAILS 2.2 GHz AMD Opteron 8214 HE (Linux) amd64 (3x faster) IndexByte4K 500000 3733 ns/op 1097.24 MB/s IndexByte4M 500 4328042 ns/op 969.10 MB/s IndexByte64M 50 67866160 ns/op 988.84 MB/s IndexBytePortable4K 200000 11161 ns/op 366.99 MB/s IndexBytePortable4M 100 11795880 ns/op 355.57 MB/s IndexBytePortable64M 10 188675000 ns/op 355.68 MB/s 386 (8.2x faster) IndexByte4K 500000 3734 ns/op 1096.95 MB/s IndexByte4M 500 4209954 ns/op 996.28 MB/s IndexByte64M 50 68031980 ns/op 986.43 MB/s IndexBytePortable4K 50000 30670 ns/op 133.55 MB/s IndexBytePortable4M 50 31868220 ns/op 131.61 MB/s IndexBytePortable64M 2 508851500 ns/op 131.88 MB/s 3.60 GHz Intel Xeon (Linux) amd64 (2.2x faster) IndexByte4K 500000 4612 ns/op 888.12 MB/s IndexByte4M 500 4835250 ns/op 867.44 MB/s IndexByte64M 20 77388450 ns/op 867.17 MB/s IndexBytePortable4K 200000 10306 ns/op 397.44 MB/s IndexBytePortable4M 100 11201460 ns/op 374.44 MB/s IndexBytePortable64M 10 179456800 ns/op 373.96 MB/s 386 (6.3x faster) IndexByte4K 500000 4631 ns/op 884.47 MB/s IndexByte4M 500 4846388 ns/op 865.45 MB/s IndexByte64M 20 78691200 ns/op 852.81 MB/s IndexBytePortable4K 100000 28989 ns/op 141.29 MB/s IndexBytePortable4M 50 31183180 ns/op 134.51 MB/s IndexBytePortable64M 5 498347200 ns/op 134.66 MB/s 2.53 GHz Intel Core2 Duo E7200 (Linux) amd64 (1.5x faster) IndexByte4K 500000 6502 ns/op 629.96 MB/s IndexByte4M 500 6692208 ns/op 626.74 MB/s IndexByte64M 10 107410400 ns/op 624.79 MB/s IndexBytePortable4K 200000 9721 ns/op 421.36 MB/s IndexBytePortable4M 100 10013680 ns/op 418.86 MB/s IndexBytePortable64M 10 160460800 ns/op 418.23 MB/s 386 (4.4x faster) IndexByte4K 500000 6505 ns/op 629.67 MB/s IndexByte4M 500 6694078 ns/op 626.57 MB/s IndexByte64M 10 107397600 ns/op 624.86 MB/s IndexBytePortable4K 100000 28835 ns/op 142.05 MB/s IndexBytePortable4M 50 29562680 ns/op 141.88 MB/s IndexBytePortable64M 5 473221400 ns/op 141.81 MB/s 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) amd64 (1.5x SLOWER) IndexByte4K 200000 9290 ns/op 440.90 MB/s IndexByte4M 200 9568925 ns/op 438.33 MB/s IndexByte64M 10 154473600 ns/op 434.44 MB/s IndexBytePortable4K 500000 6202 ns/op 660.43 MB/s IndexBytePortable4M 500 6583614 ns/op 637.08 MB/s IndexBytePortable64M 20 107166250 ns/op 626.21 MB/s 386 (3x faster) IndexByte4K 200000 9301 ns/op 440.38 MB/s IndexByte4M 200 9568025 ns/op 438.37 MB/s IndexByte64M 10 154391000 ns/op 434.67 MB/s IndexBytePortable4K 100000 27526 ns/op 148.80 MB/s IndexBytePortable4M 100 28302490 ns/op 148.20 MB/s IndexBytePortable64M 5 454170200 ns/op 147.76 MB/s 2.33 GHz Intel Xeon E5435 (Linux) amd64 (1.5x SLOWER) IndexByte4K 200000 10601 ns/op 386.38 MB/s IndexByte4M 100 10827240 ns/op 387.38 MB/s IndexByte64M 10 173175500 ns/op 387.52 MB/s IndexBytePortable4K 500000 7082 ns/op 578.37 MB/s IndexBytePortable4M 500 7391792 ns/op 567.43 MB/s IndexBytePortable64M 20 122618550 ns/op 547.30 MB/s 386 (3x faster) IndexByte4K 200000 11074 ns/op 369.88 MB/s IndexByte4M 100 10902620 ns/op 384.71 MB/s IndexByte64M 10 181292800 ns/op 370.17 MB/s IndexBytePortable4K 50000 31725 ns/op 129.11 MB/s IndexBytePortable4M 50 32564880 ns/op 128.80 MB/s IndexBytePortable64M 2 545926000 ns/op 122.93 MB/s 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) amd64 (1.4x SLOWER) IndexByte4K 200000 11120 ns/op 368.35 MB/s IndexByte4M 100 11531950 ns/op 363.71 MB/s IndexByte64M 10 184819000 ns/op 363.11 MB/s IndexBytePortable4K 500000 7419 ns/op 552.10 MB/s IndexBytePortable4M 200 8018710 ns/op 523.06 MB/s IndexBytePortable64M 10 127614900 ns/op 525.87 MB/s 386 (3x faster) IndexByte4K 200000 11114 ns/op 368.54 MB/s IndexByte4M 100 11443530 ns/op 366.52 MB/s IndexByte64M 10 185212000 ns/op 362.34 MB/s IndexBytePortable4K 50000 32891 ns/op 124.53 MB/s IndexBytePortable4M 50 33930580 ns/op 123.61 MB/s IndexBytePortable64M 2 545400500 ns/op 123.05 MB/s 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) amd64 (no difference) IndexByte4K 200000 13497 ns/op 303.47 MB/s IndexByte4M 100 13890650 ns/op 301.95 MB/s IndexByte64M 5 222358000 ns/op 301.81 MB/s IndexBytePortable4K 200000 13584 ns/op 301.53 MB/s IndexBytePortable4M 100 13913280 ns/op 301.46 MB/s IndexBytePortable64M 10 222572600 ns/op 301.51 MB/s 386 (3x faster) IndexByte4K 200000 13565 ns/op 301.95 MB/s IndexByte4M 100 13882640 ns/op 302.13 MB/s IndexByte64M 5 221411600 ns/op 303.10 MB/s IndexBytePortable4K 50000 39978 ns/op 102.46 MB/s IndexBytePortable4M 50 41038160 ns/op 102.20 MB/s IndexBytePortable64M 2 656362500 ns/op 102.24 MB/s R=r CC=golang-dev https://golang.org/cl/166055
2009-12-04 10:23:43 -08:00
}
func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
for _, n := range sizes {
if isRaceBuilder && n > 4<<10 {
continue
}
b.Run(valName(n), func(b *testing.B) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
f(b, n)
})
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
}
bytes: asm for bytes.IndexByte PERFORMANCE DIFFERENCE SUMMARY amd64 386 2.2 GHz AMD Opteron 8214 HE (Linux) 3.0x faster 8.2x faster 3.60 GHz Intel Xeon (Linux) 2.2x faster 6.2x faster 2.53 GHz Intel Core2 Duo E7200 (Linux) 1.5x faster 4.4x faster 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Xeon E5435 (Linux) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) 1.4x SLOWER 3.0x faster 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) none* 3.0x faster * but yesterday I consistently saw 1.4x SLOWER. DETAILS 2.2 GHz AMD Opteron 8214 HE (Linux) amd64 (3x faster) IndexByte4K 500000 3733 ns/op 1097.24 MB/s IndexByte4M 500 4328042 ns/op 969.10 MB/s IndexByte64M 50 67866160 ns/op 988.84 MB/s IndexBytePortable4K 200000 11161 ns/op 366.99 MB/s IndexBytePortable4M 100 11795880 ns/op 355.57 MB/s IndexBytePortable64M 10 188675000 ns/op 355.68 MB/s 386 (8.2x faster) IndexByte4K 500000 3734 ns/op 1096.95 MB/s IndexByte4M 500 4209954 ns/op 996.28 MB/s IndexByte64M 50 68031980 ns/op 986.43 MB/s IndexBytePortable4K 50000 30670 ns/op 133.55 MB/s IndexBytePortable4M 50 31868220 ns/op 131.61 MB/s IndexBytePortable64M 2 508851500 ns/op 131.88 MB/s 3.60 GHz Intel Xeon (Linux) amd64 (2.2x faster) IndexByte4K 500000 4612 ns/op 888.12 MB/s IndexByte4M 500 4835250 ns/op 867.44 MB/s IndexByte64M 20 77388450 ns/op 867.17 MB/s IndexBytePortable4K 200000 10306 ns/op 397.44 MB/s IndexBytePortable4M 100 11201460 ns/op 374.44 MB/s IndexBytePortable64M 10 179456800 ns/op 373.96 MB/s 386 (6.3x faster) IndexByte4K 500000 4631 ns/op 884.47 MB/s IndexByte4M 500 4846388 ns/op 865.45 MB/s IndexByte64M 20 78691200 ns/op 852.81 MB/s IndexBytePortable4K 100000 28989 ns/op 141.29 MB/s IndexBytePortable4M 50 31183180 ns/op 134.51 MB/s IndexBytePortable64M 5 498347200 ns/op 134.66 MB/s 2.53 GHz Intel Core2 Duo E7200 (Linux) amd64 (1.5x faster) IndexByte4K 500000 6502 ns/op 629.96 MB/s IndexByte4M 500 6692208 ns/op 626.74 MB/s IndexByte64M 10 107410400 ns/op 624.79 MB/s IndexBytePortable4K 200000 9721 ns/op 421.36 MB/s IndexBytePortable4M 100 10013680 ns/op 418.86 MB/s IndexBytePortable64M 10 160460800 ns/op 418.23 MB/s 386 (4.4x faster) IndexByte4K 500000 6505 ns/op 629.67 MB/s IndexByte4M 500 6694078 ns/op 626.57 MB/s IndexByte64M 10 107397600 ns/op 624.86 MB/s IndexBytePortable4K 100000 28835 ns/op 142.05 MB/s IndexBytePortable4M 50 29562680 ns/op 141.88 MB/s IndexBytePortable64M 5 473221400 ns/op 141.81 MB/s 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) amd64 (1.5x SLOWER) IndexByte4K 200000 9290 ns/op 440.90 MB/s IndexByte4M 200 9568925 ns/op 438.33 MB/s IndexByte64M 10 154473600 ns/op 434.44 MB/s IndexBytePortable4K 500000 6202 ns/op 660.43 MB/s IndexBytePortable4M 500 6583614 ns/op 637.08 MB/s IndexBytePortable64M 20 107166250 ns/op 626.21 MB/s 386 (3x faster) IndexByte4K 200000 9301 ns/op 440.38 MB/s IndexByte4M 200 9568025 ns/op 438.37 MB/s IndexByte64M 10 154391000 ns/op 434.67 MB/s IndexBytePortable4K 100000 27526 ns/op 148.80 MB/s IndexBytePortable4M 100 28302490 ns/op 148.20 MB/s IndexBytePortable64M 5 454170200 ns/op 147.76 MB/s 2.33 GHz Intel Xeon E5435 (Linux) amd64 (1.5x SLOWER) IndexByte4K 200000 10601 ns/op 386.38 MB/s IndexByte4M 100 10827240 ns/op 387.38 MB/s IndexByte64M 10 173175500 ns/op 387.52 MB/s IndexBytePortable4K 500000 7082 ns/op 578.37 MB/s IndexBytePortable4M 500 7391792 ns/op 567.43 MB/s IndexBytePortable64M 20 122618550 ns/op 547.30 MB/s 386 (3x faster) IndexByte4K 200000 11074 ns/op 369.88 MB/s IndexByte4M 100 10902620 ns/op 384.71 MB/s IndexByte64M 10 181292800 ns/op 370.17 MB/s IndexBytePortable4K 50000 31725 ns/op 129.11 MB/s IndexBytePortable4M 50 32564880 ns/op 128.80 MB/s IndexBytePortable64M 2 545926000 ns/op 122.93 MB/s 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) amd64 (1.4x SLOWER) IndexByte4K 200000 11120 ns/op 368.35 MB/s IndexByte4M 100 11531950 ns/op 363.71 MB/s IndexByte64M 10 184819000 ns/op 363.11 MB/s IndexBytePortable4K 500000 7419 ns/op 552.10 MB/s IndexBytePortable4M 200 8018710 ns/op 523.06 MB/s IndexBytePortable64M 10 127614900 ns/op 525.87 MB/s 386 (3x faster) IndexByte4K 200000 11114 ns/op 368.54 MB/s IndexByte4M 100 11443530 ns/op 366.52 MB/s IndexByte64M 10 185212000 ns/op 362.34 MB/s IndexBytePortable4K 50000 32891 ns/op 124.53 MB/s IndexBytePortable4M 50 33930580 ns/op 123.61 MB/s IndexBytePortable64M 2 545400500 ns/op 123.05 MB/s 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) amd64 (no difference) IndexByte4K 200000 13497 ns/op 303.47 MB/s IndexByte4M 100 13890650 ns/op 301.95 MB/s IndexByte64M 5 222358000 ns/op 301.81 MB/s IndexBytePortable4K 200000 13584 ns/op 301.53 MB/s IndexBytePortable4M 100 13913280 ns/op 301.46 MB/s IndexBytePortable64M 10 222572600 ns/op 301.51 MB/s 386 (3x faster) IndexByte4K 200000 13565 ns/op 301.95 MB/s IndexByte4M 100 13882640 ns/op 302.13 MB/s IndexByte64M 5 221411600 ns/op 303.10 MB/s IndexBytePortable4K 50000 39978 ns/op 102.46 MB/s IndexBytePortable4M 50 41038160 ns/op 102.20 MB/s IndexBytePortable64M 2 656362500 ns/op 102.24 MB/s R=r CC=golang-dev https://golang.org/cl/166055
2009-12-04 10:23:43 -08:00
}
var indexSizes = []int{10, 32, 4 << 10, 4 << 20, 64 << 20}
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
var isRaceBuilder = strings.HasSuffix(testenv.Builder(), "-race")
func BenchmarkIndexByte(b *testing.B) {
benchBytes(b, indexSizes, bmIndexByte(IndexByte))
}
func BenchmarkIndexBytePortable(b *testing.B) {
benchBytes(b, indexSizes, bmIndexByte(IndexBytePortable))
}
func bmIndexByte(index func([]byte, byte) int) func(b *testing.B, n int) {
return func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := index(buf, 'x')
if j != n-1 {
b.Fatal("bad index", j)
}
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
}
buf[n-1] = '\x00'
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
}
bytes: asm for bytes.IndexByte PERFORMANCE DIFFERENCE SUMMARY amd64 386 2.2 GHz AMD Opteron 8214 HE (Linux) 3.0x faster 8.2x faster 3.60 GHz Intel Xeon (Linux) 2.2x faster 6.2x faster 2.53 GHz Intel Core2 Duo E7200 (Linux) 1.5x faster 4.4x faster 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Xeon E5435 (Linux) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) 1.4x SLOWER 3.0x faster 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) none* 3.0x faster * but yesterday I consistently saw 1.4x SLOWER. DETAILS 2.2 GHz AMD Opteron 8214 HE (Linux) amd64 (3x faster) IndexByte4K 500000 3733 ns/op 1097.24 MB/s IndexByte4M 500 4328042 ns/op 969.10 MB/s IndexByte64M 50 67866160 ns/op 988.84 MB/s IndexBytePortable4K 200000 11161 ns/op 366.99 MB/s IndexBytePortable4M 100 11795880 ns/op 355.57 MB/s IndexBytePortable64M 10 188675000 ns/op 355.68 MB/s 386 (8.2x faster) IndexByte4K 500000 3734 ns/op 1096.95 MB/s IndexByte4M 500 4209954 ns/op 996.28 MB/s IndexByte64M 50 68031980 ns/op 986.43 MB/s IndexBytePortable4K 50000 30670 ns/op 133.55 MB/s IndexBytePortable4M 50 31868220 ns/op 131.61 MB/s IndexBytePortable64M 2 508851500 ns/op 131.88 MB/s 3.60 GHz Intel Xeon (Linux) amd64 (2.2x faster) IndexByte4K 500000 4612 ns/op 888.12 MB/s IndexByte4M 500 4835250 ns/op 867.44 MB/s IndexByte64M 20 77388450 ns/op 867.17 MB/s IndexBytePortable4K 200000 10306 ns/op 397.44 MB/s IndexBytePortable4M 100 11201460 ns/op 374.44 MB/s IndexBytePortable64M 10 179456800 ns/op 373.96 MB/s 386 (6.3x faster) IndexByte4K 500000 4631 ns/op 884.47 MB/s IndexByte4M 500 4846388 ns/op 865.45 MB/s IndexByte64M 20 78691200 ns/op 852.81 MB/s IndexBytePortable4K 100000 28989 ns/op 141.29 MB/s IndexBytePortable4M 50 31183180 ns/op 134.51 MB/s IndexBytePortable64M 5 498347200 ns/op 134.66 MB/s 2.53 GHz Intel Core2 Duo E7200 (Linux) amd64 (1.5x faster) IndexByte4K 500000 6502 ns/op 629.96 MB/s IndexByte4M 500 6692208 ns/op 626.74 MB/s IndexByte64M 10 107410400 ns/op 624.79 MB/s IndexBytePortable4K 200000 9721 ns/op 421.36 MB/s IndexBytePortable4M 100 10013680 ns/op 418.86 MB/s IndexBytePortable64M 10 160460800 ns/op 418.23 MB/s 386 (4.4x faster) IndexByte4K 500000 6505 ns/op 629.67 MB/s IndexByte4M 500 6694078 ns/op 626.57 MB/s IndexByte64M 10 107397600 ns/op 624.86 MB/s IndexBytePortable4K 100000 28835 ns/op 142.05 MB/s IndexBytePortable4M 50 29562680 ns/op 141.88 MB/s IndexBytePortable64M 5 473221400 ns/op 141.81 MB/s 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) amd64 (1.5x SLOWER) IndexByte4K 200000 9290 ns/op 440.90 MB/s IndexByte4M 200 9568925 ns/op 438.33 MB/s IndexByte64M 10 154473600 ns/op 434.44 MB/s IndexBytePortable4K 500000 6202 ns/op 660.43 MB/s IndexBytePortable4M 500 6583614 ns/op 637.08 MB/s IndexBytePortable64M 20 107166250 ns/op 626.21 MB/s 386 (3x faster) IndexByte4K 200000 9301 ns/op 440.38 MB/s IndexByte4M 200 9568025 ns/op 438.37 MB/s IndexByte64M 10 154391000 ns/op 434.67 MB/s IndexBytePortable4K 100000 27526 ns/op 148.80 MB/s IndexBytePortable4M 100 28302490 ns/op 148.20 MB/s IndexBytePortable64M 5 454170200 ns/op 147.76 MB/s 2.33 GHz Intel Xeon E5435 (Linux) amd64 (1.5x SLOWER) IndexByte4K 200000 10601 ns/op 386.38 MB/s IndexByte4M 100 10827240 ns/op 387.38 MB/s IndexByte64M 10 173175500 ns/op 387.52 MB/s IndexBytePortable4K 500000 7082 ns/op 578.37 MB/s IndexBytePortable4M 500 7391792 ns/op 567.43 MB/s IndexBytePortable64M 20 122618550 ns/op 547.30 MB/s 386 (3x faster) IndexByte4K 200000 11074 ns/op 369.88 MB/s IndexByte4M 100 10902620 ns/op 384.71 MB/s IndexByte64M 10 181292800 ns/op 370.17 MB/s IndexBytePortable4K 50000 31725 ns/op 129.11 MB/s IndexBytePortable4M 50 32564880 ns/op 128.80 MB/s IndexBytePortable64M 2 545926000 ns/op 122.93 MB/s 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) amd64 (1.4x SLOWER) IndexByte4K 200000 11120 ns/op 368.35 MB/s IndexByte4M 100 11531950 ns/op 363.71 MB/s IndexByte64M 10 184819000 ns/op 363.11 MB/s IndexBytePortable4K 500000 7419 ns/op 552.10 MB/s IndexBytePortable4M 200 8018710 ns/op 523.06 MB/s IndexBytePortable64M 10 127614900 ns/op 525.87 MB/s 386 (3x faster) IndexByte4K 200000 11114 ns/op 368.54 MB/s IndexByte4M 100 11443530 ns/op 366.52 MB/s IndexByte64M 10 185212000 ns/op 362.34 MB/s IndexBytePortable4K 50000 32891 ns/op 124.53 MB/s IndexBytePortable4M 50 33930580 ns/op 123.61 MB/s IndexBytePortable64M 2 545400500 ns/op 123.05 MB/s 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) amd64 (no difference) IndexByte4K 200000 13497 ns/op 303.47 MB/s IndexByte4M 100 13890650 ns/op 301.95 MB/s IndexByte64M 5 222358000 ns/op 301.81 MB/s IndexBytePortable4K 200000 13584 ns/op 301.53 MB/s IndexBytePortable4M 100 13913280 ns/op 301.46 MB/s IndexBytePortable64M 10 222572600 ns/op 301.51 MB/s 386 (3x faster) IndexByte4K 200000 13565 ns/op 301.95 MB/s IndexByte4M 100 13882640 ns/op 302.13 MB/s IndexByte64M 5 221411600 ns/op 303.10 MB/s IndexBytePortable4K 50000 39978 ns/op 102.46 MB/s IndexBytePortable4M 50 41038160 ns/op 102.20 MB/s IndexBytePortable64M 2 656362500 ns/op 102.24 MB/s R=r CC=golang-dev https://golang.org/cl/166055
2009-12-04 10:23:43 -08:00
}
bytes: make IndexRune faster re-implement IndexRune by IndexByte and Index which are well optimized to get performance gain. name old time/op new time/op delta IndexRune/10-4 53.2ns ± 1% 29.1ns ± 1% -45.32% (p=0.008 n=5+5) IndexRune/32-4 191ns ± 1% 27ns ± 1% -85.75% (p=0.008 n=5+5) IndexRune/4K-4 23.5µs ± 1% 1.0µs ± 1% -95.77% (p=0.008 n=5+5) IndexRune/4M-4 23.8ms ± 0% 1.0ms ± 2% -95.90% (p=0.008 n=5+5) IndexRune/64M-4 384ms ± 1% 15ms ± 1% -95.98% (p=0.008 n=5+5) IndexRuneASCII/10-4 61.5ns ± 0% 10.3ns ± 4% -83.17% (p=0.008 n=5+5) IndexRuneASCII/32-4 203ns ± 0% 11ns ± 5% -94.68% (p=0.008 n=5+5) IndexRuneASCII/4K-4 23.4µs ± 0% 0.3µs ± 2% -98.60% (p=0.008 n=5+5) IndexRuneASCII/4M-4 24.0ms ± 1% 0.3ms ± 1% -98.60% (p=0.008 n=5+5) IndexRuneASCII/64M-4 386ms ± 2% 6ms ± 1% -98.57% (p=0.008 n=5+5) name old speed new speed delta IndexRune/10-4 188MB/s ± 1% 344MB/s ± 1% +82.91% (p=0.008 n=5+5) IndexRune/32-4 167MB/s ± 0% 1175MB/s ± 1% +603.52% (p=0.008 n=5+5) IndexRune/4K-4 174MB/s ± 1% 4117MB/s ± 1% +2262.71% (p=0.008 n=5+5) IndexRune/4M-4 176MB/s ± 0% 4299MB/s ± 2% +2340.46% (p=0.008 n=5+5) IndexRune/64M-4 175MB/s ± 1% 4354MB/s ± 1% +2388.57% (p=0.008 n=5+5) IndexRuneASCII/10-4 163MB/s ± 0% 968MB/s ± 4% +494.66% (p=0.008 n=5+5) IndexRuneASCII/32-4 157MB/s ± 0% 2974MB/s ± 4% +1788.59% (p=0.008 n=5+5) IndexRuneASCII/4K-4 175MB/s ± 0% 12481MB/s ± 2% +7027.71% (p=0.008 n=5+5) IndexRuneASCII/4M-4 175MB/s ± 1% 12510MB/s ± 1% +7061.15% (p=0.008 n=5+5) IndexRuneASCII/64M-4 174MB/s ± 2% 12143MB/s ± 1% +6881.70% (p=0.008 n=5+5) Change-Id: I0632eadb83937c2a9daa7f0ce79df1dee64f992e Reviewed-on: https://go-review.googlesource.com/28537 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-09-06 08:09:27 +09:00
func BenchmarkIndexRune(b *testing.B) {
benchBytes(b, indexSizes, bmIndexRune(IndexRune))
}
func BenchmarkIndexRuneASCII(b *testing.B) {
benchBytes(b, indexSizes, bmIndexRuneASCII(IndexRune))
}
func bmIndexRuneASCII(index func([]byte, rune) int) func(b *testing.B, n int) {
return func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := index(buf, 'x')
if j != n-1 {
b.Fatal("bad index", j)
}
}
buf[n-1] = '\x00'
}
}
func bmIndexRune(index func([]byte, rune) int) func(b *testing.B, n int) {
return func(b *testing.B, n int) {
buf := bmbuf[0:n]
utf8.EncodeRune(buf[n-3:], '世')
for i := 0; i < b.N; i++ {
j := index(buf, '世')
if j != n-3 {
b.Fatal("bad index", j)
}
}
buf[n-3] = '\x00'
buf[n-2] = '\x00'
buf[n-1] = '\x00'
}
}
func BenchmarkEqual(b *testing.B) {
b.Run("0", func(b *testing.B) {
var buf [4]byte
buf1 := buf[0:0]
buf2 := buf[1:1]
for i := 0; i < b.N; i++ {
eq := Equal(buf1, buf2)
if !eq {
b.Fatal("bad equal")
}
}
})
bytes: asm for bytes.IndexByte PERFORMANCE DIFFERENCE SUMMARY amd64 386 2.2 GHz AMD Opteron 8214 HE (Linux) 3.0x faster 8.2x faster 3.60 GHz Intel Xeon (Linux) 2.2x faster 6.2x faster 2.53 GHz Intel Core2 Duo E7200 (Linux) 1.5x faster 4.4x faster 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Xeon E5435 (Linux) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) 1.4x SLOWER 3.0x faster 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) none* 3.0x faster * but yesterday I consistently saw 1.4x SLOWER. DETAILS 2.2 GHz AMD Opteron 8214 HE (Linux) amd64 (3x faster) IndexByte4K 500000 3733 ns/op 1097.24 MB/s IndexByte4M 500 4328042 ns/op 969.10 MB/s IndexByte64M 50 67866160 ns/op 988.84 MB/s IndexBytePortable4K 200000 11161 ns/op 366.99 MB/s IndexBytePortable4M 100 11795880 ns/op 355.57 MB/s IndexBytePortable64M 10 188675000 ns/op 355.68 MB/s 386 (8.2x faster) IndexByte4K 500000 3734 ns/op 1096.95 MB/s IndexByte4M 500 4209954 ns/op 996.28 MB/s IndexByte64M 50 68031980 ns/op 986.43 MB/s IndexBytePortable4K 50000 30670 ns/op 133.55 MB/s IndexBytePortable4M 50 31868220 ns/op 131.61 MB/s IndexBytePortable64M 2 508851500 ns/op 131.88 MB/s 3.60 GHz Intel Xeon (Linux) amd64 (2.2x faster) IndexByte4K 500000 4612 ns/op 888.12 MB/s IndexByte4M 500 4835250 ns/op 867.44 MB/s IndexByte64M 20 77388450 ns/op 867.17 MB/s IndexBytePortable4K 200000 10306 ns/op 397.44 MB/s IndexBytePortable4M 100 11201460 ns/op 374.44 MB/s IndexBytePortable64M 10 179456800 ns/op 373.96 MB/s 386 (6.3x faster) IndexByte4K 500000 4631 ns/op 884.47 MB/s IndexByte4M 500 4846388 ns/op 865.45 MB/s IndexByte64M 20 78691200 ns/op 852.81 MB/s IndexBytePortable4K 100000 28989 ns/op 141.29 MB/s IndexBytePortable4M 50 31183180 ns/op 134.51 MB/s IndexBytePortable64M 5 498347200 ns/op 134.66 MB/s 2.53 GHz Intel Core2 Duo E7200 (Linux) amd64 (1.5x faster) IndexByte4K 500000 6502 ns/op 629.96 MB/s IndexByte4M 500 6692208 ns/op 626.74 MB/s IndexByte64M 10 107410400 ns/op 624.79 MB/s IndexBytePortable4K 200000 9721 ns/op 421.36 MB/s IndexBytePortable4M 100 10013680 ns/op 418.86 MB/s IndexBytePortable64M 10 160460800 ns/op 418.23 MB/s 386 (4.4x faster) IndexByte4K 500000 6505 ns/op 629.67 MB/s IndexByte4M 500 6694078 ns/op 626.57 MB/s IndexByte64M 10 107397600 ns/op 624.86 MB/s IndexBytePortable4K 100000 28835 ns/op 142.05 MB/s IndexBytePortable4M 50 29562680 ns/op 141.88 MB/s IndexBytePortable64M 5 473221400 ns/op 141.81 MB/s 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) amd64 (1.5x SLOWER) IndexByte4K 200000 9290 ns/op 440.90 MB/s IndexByte4M 200 9568925 ns/op 438.33 MB/s IndexByte64M 10 154473600 ns/op 434.44 MB/s IndexBytePortable4K 500000 6202 ns/op 660.43 MB/s IndexBytePortable4M 500 6583614 ns/op 637.08 MB/s IndexBytePortable64M 20 107166250 ns/op 626.21 MB/s 386 (3x faster) IndexByte4K 200000 9301 ns/op 440.38 MB/s IndexByte4M 200 9568025 ns/op 438.37 MB/s IndexByte64M 10 154391000 ns/op 434.67 MB/s IndexBytePortable4K 100000 27526 ns/op 148.80 MB/s IndexBytePortable4M 100 28302490 ns/op 148.20 MB/s IndexBytePortable64M 5 454170200 ns/op 147.76 MB/s 2.33 GHz Intel Xeon E5435 (Linux) amd64 (1.5x SLOWER) IndexByte4K 200000 10601 ns/op 386.38 MB/s IndexByte4M 100 10827240 ns/op 387.38 MB/s IndexByte64M 10 173175500 ns/op 387.52 MB/s IndexBytePortable4K 500000 7082 ns/op 578.37 MB/s IndexBytePortable4M 500 7391792 ns/op 567.43 MB/s IndexBytePortable64M 20 122618550 ns/op 547.30 MB/s 386 (3x faster) IndexByte4K 200000 11074 ns/op 369.88 MB/s IndexByte4M 100 10902620 ns/op 384.71 MB/s IndexByte64M 10 181292800 ns/op 370.17 MB/s IndexBytePortable4K 50000 31725 ns/op 129.11 MB/s IndexBytePortable4M 50 32564880 ns/op 128.80 MB/s IndexBytePortable64M 2 545926000 ns/op 122.93 MB/s 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) amd64 (1.4x SLOWER) IndexByte4K 200000 11120 ns/op 368.35 MB/s IndexByte4M 100 11531950 ns/op 363.71 MB/s IndexByte64M 10 184819000 ns/op 363.11 MB/s IndexBytePortable4K 500000 7419 ns/op 552.10 MB/s IndexBytePortable4M 200 8018710 ns/op 523.06 MB/s IndexBytePortable64M 10 127614900 ns/op 525.87 MB/s 386 (3x faster) IndexByte4K 200000 11114 ns/op 368.54 MB/s IndexByte4M 100 11443530 ns/op 366.52 MB/s IndexByte64M 10 185212000 ns/op 362.34 MB/s IndexBytePortable4K 50000 32891 ns/op 124.53 MB/s IndexBytePortable4M 50 33930580 ns/op 123.61 MB/s IndexBytePortable64M 2 545400500 ns/op 123.05 MB/s 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) amd64 (no difference) IndexByte4K 200000 13497 ns/op 303.47 MB/s IndexByte4M 100 13890650 ns/op 301.95 MB/s IndexByte64M 5 222358000 ns/op 301.81 MB/s IndexBytePortable4K 200000 13584 ns/op 301.53 MB/s IndexBytePortable4M 100 13913280 ns/op 301.46 MB/s IndexBytePortable64M 10 222572600 ns/op 301.51 MB/s 386 (3x faster) IndexByte4K 200000 13565 ns/op 301.95 MB/s IndexByte4M 100 13882640 ns/op 302.13 MB/s IndexByte64M 5 221411600 ns/op 303.10 MB/s IndexBytePortable4K 50000 39978 ns/op 102.46 MB/s IndexBytePortable4M 50 41038160 ns/op 102.20 MB/s IndexBytePortable64M 2 656362500 ns/op 102.24 MB/s R=r CC=golang-dev https://golang.org/cl/166055
2009-12-04 10:23:43 -08:00
sizes := []int{1, 6, 9, 15, 16, 20, 32, 4 << 10, 4 << 20, 64 << 20}
benchBytes(b, sizes, bmEqual(Equal))
}
func BenchmarkEqualPort(b *testing.B) {
sizes := []int{1, 6, 32, 4 << 10, 4 << 20, 64 << 20}
benchBytes(b, sizes, bmEqual(EqualPortable))
}
func bmEqual(equal func([]byte, []byte) bool) func(b *testing.B, n int) {
return func(b *testing.B, n int) {
if len(bmbuf) < 2*n {
bmbuf = make([]byte, 2*n)
}
buf1 := bmbuf[0:n]
buf2 := bmbuf[n : 2*n]
buf1[n-1] = 'x'
buf2[n-1] = 'x'
for i := 0; i < b.N; i++ {
eq := equal(buf1, buf2)
if !eq {
b.Fatal("bad equal")
}
bytes: asm for bytes.IndexByte PERFORMANCE DIFFERENCE SUMMARY amd64 386 2.2 GHz AMD Opteron 8214 HE (Linux) 3.0x faster 8.2x faster 3.60 GHz Intel Xeon (Linux) 2.2x faster 6.2x faster 2.53 GHz Intel Core2 Duo E7200 (Linux) 1.5x faster 4.4x faster 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Xeon E5435 (Linux) 1.5x SLOWER 3.0x faster 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) 1.4x SLOWER 3.0x faster 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) none* 3.0x faster * but yesterday I consistently saw 1.4x SLOWER. DETAILS 2.2 GHz AMD Opteron 8214 HE (Linux) amd64 (3x faster) IndexByte4K 500000 3733 ns/op 1097.24 MB/s IndexByte4M 500 4328042 ns/op 969.10 MB/s IndexByte64M 50 67866160 ns/op 988.84 MB/s IndexBytePortable4K 200000 11161 ns/op 366.99 MB/s IndexBytePortable4M 100 11795880 ns/op 355.57 MB/s IndexBytePortable64M 10 188675000 ns/op 355.68 MB/s 386 (8.2x faster) IndexByte4K 500000 3734 ns/op 1096.95 MB/s IndexByte4M 500 4209954 ns/op 996.28 MB/s IndexByte64M 50 68031980 ns/op 986.43 MB/s IndexBytePortable4K 50000 30670 ns/op 133.55 MB/s IndexBytePortable4M 50 31868220 ns/op 131.61 MB/s IndexBytePortable64M 2 508851500 ns/op 131.88 MB/s 3.60 GHz Intel Xeon (Linux) amd64 (2.2x faster) IndexByte4K 500000 4612 ns/op 888.12 MB/s IndexByte4M 500 4835250 ns/op 867.44 MB/s IndexByte64M 20 77388450 ns/op 867.17 MB/s IndexBytePortable4K 200000 10306 ns/op 397.44 MB/s IndexBytePortable4M 100 11201460 ns/op 374.44 MB/s IndexBytePortable64M 10 179456800 ns/op 373.96 MB/s 386 (6.3x faster) IndexByte4K 500000 4631 ns/op 884.47 MB/s IndexByte4M 500 4846388 ns/op 865.45 MB/s IndexByte64M 20 78691200 ns/op 852.81 MB/s IndexBytePortable4K 100000 28989 ns/op 141.29 MB/s IndexBytePortable4M 50 31183180 ns/op 134.51 MB/s IndexBytePortable64M 5 498347200 ns/op 134.66 MB/s 2.53 GHz Intel Core2 Duo E7200 (Linux) amd64 (1.5x faster) IndexByte4K 500000 6502 ns/op 629.96 MB/s IndexByte4M 500 6692208 ns/op 626.74 MB/s IndexByte64M 10 107410400 ns/op 624.79 MB/s IndexBytePortable4K 200000 9721 ns/op 421.36 MB/s IndexBytePortable4M 100 10013680 ns/op 418.86 MB/s IndexBytePortable64M 10 160460800 ns/op 418.23 MB/s 386 (4.4x faster) IndexByte4K 500000 6505 ns/op 629.67 MB/s IndexByte4M 500 6694078 ns/op 626.57 MB/s IndexByte64M 10 107397600 ns/op 624.86 MB/s IndexBytePortable4K 100000 28835 ns/op 142.05 MB/s IndexBytePortable4M 50 29562680 ns/op 141.88 MB/s IndexBytePortable64M 5 473221400 ns/op 141.81 MB/s 2.66 Ghz Intel Xeon 5150 (Mac Pro, OS X) amd64 (1.5x SLOWER) IndexByte4K 200000 9290 ns/op 440.90 MB/s IndexByte4M 200 9568925 ns/op 438.33 MB/s IndexByte64M 10 154473600 ns/op 434.44 MB/s IndexBytePortable4K 500000 6202 ns/op 660.43 MB/s IndexBytePortable4M 500 6583614 ns/op 637.08 MB/s IndexBytePortable64M 20 107166250 ns/op 626.21 MB/s 386 (3x faster) IndexByte4K 200000 9301 ns/op 440.38 MB/s IndexByte4M 200 9568025 ns/op 438.37 MB/s IndexByte64M 10 154391000 ns/op 434.67 MB/s IndexBytePortable4K 100000 27526 ns/op 148.80 MB/s IndexBytePortable4M 100 28302490 ns/op 148.20 MB/s IndexBytePortable64M 5 454170200 ns/op 147.76 MB/s 2.33 GHz Intel Xeon E5435 (Linux) amd64 (1.5x SLOWER) IndexByte4K 200000 10601 ns/op 386.38 MB/s IndexByte4M 100 10827240 ns/op 387.38 MB/s IndexByte64M 10 173175500 ns/op 387.52 MB/s IndexBytePortable4K 500000 7082 ns/op 578.37 MB/s IndexBytePortable4M 500 7391792 ns/op 567.43 MB/s IndexBytePortable64M 20 122618550 ns/op 547.30 MB/s 386 (3x faster) IndexByte4K 200000 11074 ns/op 369.88 MB/s IndexByte4M 100 10902620 ns/op 384.71 MB/s IndexByte64M 10 181292800 ns/op 370.17 MB/s IndexBytePortable4K 50000 31725 ns/op 129.11 MB/s IndexBytePortable4M 50 32564880 ns/op 128.80 MB/s IndexBytePortable64M 2 545926000 ns/op 122.93 MB/s 2.33 GHz Intel Core2 T7600 (MacBook Pro, OS X) amd64 (1.4x SLOWER) IndexByte4K 200000 11120 ns/op 368.35 MB/s IndexByte4M 100 11531950 ns/op 363.71 MB/s IndexByte64M 10 184819000 ns/op 363.11 MB/s IndexBytePortable4K 500000 7419 ns/op 552.10 MB/s IndexBytePortable4M 200 8018710 ns/op 523.06 MB/s IndexBytePortable64M 10 127614900 ns/op 525.87 MB/s 386 (3x faster) IndexByte4K 200000 11114 ns/op 368.54 MB/s IndexByte4M 100 11443530 ns/op 366.52 MB/s IndexByte64M 10 185212000 ns/op 362.34 MB/s IndexBytePortable4K 50000 32891 ns/op 124.53 MB/s IndexBytePortable4M 50 33930580 ns/op 123.61 MB/s IndexBytePortable64M 2 545400500 ns/op 123.05 MB/s 1.83 GHz Intel Core2 T5600 (Mac Mini, OS X) amd64 (no difference) IndexByte4K 200000 13497 ns/op 303.47 MB/s IndexByte4M 100 13890650 ns/op 301.95 MB/s IndexByte64M 5 222358000 ns/op 301.81 MB/s IndexBytePortable4K 200000 13584 ns/op 301.53 MB/s IndexBytePortable4M 100 13913280 ns/op 301.46 MB/s IndexBytePortable64M 10 222572600 ns/op 301.51 MB/s 386 (3x faster) IndexByte4K 200000 13565 ns/op 301.95 MB/s IndexByte4M 100 13882640 ns/op 302.13 MB/s IndexByte64M 5 221411600 ns/op 303.10 MB/s IndexBytePortable4K 50000 39978 ns/op 102.46 MB/s IndexBytePortable4M 50 41038160 ns/op 102.20 MB/s IndexBytePortable64M 2 656362500 ns/op 102.24 MB/s R=r CC=golang-dev https://golang.org/cl/166055
2009-12-04 10:23:43 -08:00
}
buf1[n-1] = '\x00'
buf2[n-1] = '\x00'
}
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
}
func BenchmarkIndex(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := Index(buf, buf[n-7:])
if j != n-7 {
b.Fatal("bad index", j)
}
}
buf[n-1] = '\x00'
})
}
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
func BenchmarkIndexEasy(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
j := Index(buf, buf[n-7:])
if j != n-7 {
b.Fatal("bad index", j)
}
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
}
buf[n-1] = '\x00'
buf[n-7] = '\x00'
})
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
}
func BenchmarkCount(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := Count(buf, buf[n-7:])
if j != 1 {
b.Fatal("bad count", j)
}
}
buf[n-1] = '\x00'
})
}
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
func BenchmarkCountEasy(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
j := Count(buf, buf[n-7:])
if j != 1 {
b.Fatal("bad count", j)
}
bytes: faster Count, Index, Equal Benchmarks are from GOARCH=amd64 on a MacPro5,1. benchmark old MB/s new MB/s speedup bytes_test.BenchmarkEqual32 452.89 891.07 1.97x bytes_test.BenchmarkEqual4K 852.71 1700.44 1.99x bytes_test.BenchmarkEqual4M 841.53 1587.93 1.89x bytes_test.BenchmarkEqual64M 838.22 1578.14 1.88x bytes_test.BenchmarkIndex32 58.02 48.99 0.84x bytes_test.BenchmarkIndex4K 48.26 41.32 0.86x bytes_test.BenchmarkIndex4M 48.20 41.24 0.86x bytes_test.BenchmarkIndex64M 48.08 41.21 0.86x bytes_test.BenchmarkIndexEasy32 410.04 546.82 1.33x bytes_test.BenchmarkIndexEasy4K 849.26 14257.37 16.79x bytes_test.BenchmarkIndexEasy4M 854.54 17222.15 20.15x bytes_test.BenchmarkIndexEasy64M 843.57 11060.40 13.11x bytes_test.BenchmarkCount32 57.24 50.68 0.89x bytes_test.BenchmarkCount4K 48.19 41.82 0.87x bytes_test.BenchmarkCount4M 48.18 41.74 0.87x bytes_test.BenchmarkCount64M 48.17 41.71 0.87x bytes_test.BenchmarkCountEasy32 433.11 547.44 1.26x bytes_test.BenchmarkCountEasy4K 1130.59 14194.06 12.55x bytes_test.BenchmarkCountEasy4M 1131.23 17231.18 15.23x bytes_test.BenchmarkCountEasy64M 1111.40 11068.88 9.96x The non-easy Count/Index benchmarks are a worst case input. regexp.BenchmarkMatchEasy0_32 237.46 221.47 0.93x regexp.BenchmarkMatchEasy0_1K 553.53 1019.72 1.84x regexp.BenchmarkMatchEasy0_32K 693.99 1672.06 2.41x regexp.BenchmarkMatchEasy0_1M 688.72 1611.68 2.34x regexp.BenchmarkMatchEasy0_32M 680.70 1565.05 2.30x regexp.BenchmarkMatchEasy1_32 165.56 243.08 1.47x regexp.BenchmarkMatchEasy1_1K 336.45 496.32 1.48x regexp.BenchmarkMatchEasy1_32K 302.80 425.63 1.41x regexp.BenchmarkMatchEasy1_1M 300.42 414.20 1.38x regexp.BenchmarkMatchEasy1_32M 299.64 413.47 1.38x R=golang-dev, r, iant CC=golang-dev https://golang.org/cl/5451116
2011-12-07 15:09:56 -05:00
}
buf[n-1] = '\x00'
buf[n-7] = '\x00'
})
}
type ExplodeTest struct {
s string
n int
a []string
}
var explodetests = []ExplodeTest{
{"", -1, []string{}},
{abcd, -1, []string{"a", "b", "c", "d"}},
{faces, -1, []string{"☺", "☻", "☹"}},
{abcd, 2, []string{"a", "bcd"}},
}
func TestExplode(t *testing.T) {
for _, tt := range explodetests {
a := SplitN([]byte(tt.s), nil, tt.n)
result := sliceOfString(a)
if !eq(result, tt.a) {
t.Errorf(`Explode("%s", %d) = %v; want %v`, tt.s, tt.n, result, tt.a)
continue
}
s := Join(a, []byte{})
if string(s) != tt.s {
t.Errorf(`Join(Explode("%s", %d), "") = "%s"`, tt.s, tt.n, s)
}
}
}
type SplitTest struct {
s string
sep string
n int
a []string
}
var splittests = []SplitTest{
{abcd, "a", 0, nil},
{abcd, "a", -1, []string{"", "bcd"}},
{abcd, "z", -1, []string{"abcd"}},
{abcd, "", -1, []string{"a", "b", "c", "d"}},
{commas, ",", -1, []string{"1", "2", "3", "4"}},
{dots, "...", -1, []string{"1", ".2", ".3", ".4"}},
{faces, "☹", -1, []string{"☺☻", ""}},
{faces, "~", -1, []string{faces}},
{faces, "", -1, []string{"☺", "☻", "☹"}},
{"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
{"1 2", " ", 3, []string{"1", "2"}},
{"123", "", 2, []string{"1", "23"}},
{"123", "", 17, []string{"1", "2", "3"}},
}
func TestSplit(t *testing.T) {
for _, tt := range splittests {
a := SplitN([]byte(tt.s), []byte(tt.sep), tt.n)
result := sliceOfString(a)
if !eq(result, tt.a) {
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
continue
}
if tt.n == 0 {
continue
}
s := Join(a, []byte(tt.sep))
if string(s) != tt.s {
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
}
if tt.n < 0 {
b := Split([]byte(tt.s), []byte(tt.sep))
if !reflect.DeepEqual(a, b) {
t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
}
}
if len(a) > 0 {
in, out := a[0], s
if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
t.Errorf("Join(%#v, %q) didn't copy", a, tt.sep)
}
}
}
}
var splitaftertests = []SplitTest{
{abcd, "a", -1, []string{"a", "bcd"}},
{abcd, "z", -1, []string{"abcd"}},
{abcd, "", -1, []string{"a", "b", "c", "d"}},
{commas, ",", -1, []string{"1,", "2,", "3,", "4"}},
{dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}},
{faces, "☹", -1, []string{"☺☻☹", ""}},
{faces, "~", -1, []string{faces}},
{faces, "", -1, []string{"☺", "☻", "☹"}},
{"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}},
{"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}},
{"1 2", " ", 3, []string{"1 ", "2"}},
{"123", "", 2, []string{"1", "23"}},
{"123", "", 17, []string{"1", "2", "3"}},
}
func TestSplitAfter(t *testing.T) {
for _, tt := range splitaftertests {
a := SplitAfterN([]byte(tt.s), []byte(tt.sep), tt.n)
result := sliceOfString(a)
if !eq(result, tt.a) {
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
continue
}
s := Join(a, nil)
if string(s) != tt.s {
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
}
if tt.n < 0 {
b := SplitAfter([]byte(tt.s), []byte(tt.sep))
if !reflect.DeepEqual(a, b) {
t.Errorf("SplitAfter disagrees withSplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
}
}
}
}
type FieldsTest struct {
s string
a []string
}
var fieldstests = []FieldsTest{
{"", []string{}},
{" ", []string{}},
{" \t ", []string{}},
{" abc ", []string{"abc"}},
{"1 2 3 4", []string{"1", "2", "3", "4"}},
{"1 2 3 4", []string{"1", "2", "3", "4"}},
{"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}},
{"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}},
{"\u2000\u2001\u2002", []string{}},
{"\n™\t™\n", []string{"™", "™"}},
{faces, []string{faces}},
}
func TestFields(t *testing.T) {
for _, tt := range fieldstests {
a := Fields([]byte(tt.s))
result := sliceOfString(a)
if !eq(result, tt.a) {
t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a)
continue
}
}
}
func TestFieldsFunc(t *testing.T) {
for _, tt := range fieldstests {
a := FieldsFunc([]byte(tt.s), unicode.IsSpace)
result := sliceOfString(a)
if !eq(result, tt.a) {
t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a)
continue
}
}
pred := func(c rune) bool { return c == 'X' }
var fieldsFuncTests = []FieldsTest{
{"", []string{}},
{"XX", []string{}},
{"XXhiXXX", []string{"hi"}},
{"aXXbXXXcX", []string{"a", "b", "c"}},
}
for _, tt := range fieldsFuncTests {
a := FieldsFunc([]byte(tt.s), pred)
result := sliceOfString(a)
if !eq(result, tt.a) {
t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
}
}
}
// Test case for any function which accepts and returns a byte slice.
// For ease of creation, we write the byte slices as strings.
type StringTest struct {
in, out string
}
var upperTests = []StringTest{
{"", ""},
{"abc", "ABC"},
{"AbC123", "ABC123"},
{"azAZ09_", "AZAZ09_"},
{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
}
var lowerTests = []StringTest{
{"", ""},
{"abc", "abc"},
{"AbC123", "abc123"},
{"azAZ09_", "azaz09_"},
{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
}
const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
var trimSpaceTests = []StringTest{
{"", ""},
{"abc", "abc"},
{space + "abc" + space, "abc"},
{" ", ""},
{" \t\r\n \t\t\r\r\n\n ", ""},
{" \t\r\n x\t\t\r\r\n\n ", "x"},
{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
{"1 \t\r\n2", "1 \t\r\n2"},
{" x\x80", "x\x80"},
{" x\xc0", "x\xc0"},
{"x \xc0\xc0 ", "x \xc0\xc0"},
{"x \xc0", "x \xc0"},
{"x \xc0 ", "x \xc0"},
{"x \xc0\xc0 ", "x \xc0\xc0"},
{"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"},
{"x ☺ ", "x ☺"},
}
// Execute f on each test case. funcName should be the name of f; it's used
// in failure reports.
func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCases []StringTest) {
for _, tc := range testCases {
actual := string(f([]byte(tc.in)))
if actual != tc.out {
t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
}
}
}
func tenRunes(r rune) string {
runes := make([]rune, 10)
for i := range runes {
runes[i] = r
}
return string(runes)
}
// User-defined self-inverse mapping function
func rot13(r rune) rune {
const step = 13
if r >= 'a' && r <= 'z' {
return ((r - 'a' + step) % 26) + 'a'
}
if r >= 'A' && r <= 'Z' {
return ((r - 'A' + step) % 26) + 'A'
}
return r
}
func TestMap(t *testing.T) {
// Run a couple of awful growth/shrinkage tests
a := tenRunes('a')
// 1. Grow. This triggers two reallocations in Map.
maxRune := func(r rune) rune { return unicode.MaxRune }
m := Map(maxRune, []byte(a))
expect := tenRunes(unicode.MaxRune)
if string(m) != expect {
t.Errorf("growing: expected %q got %q", expect, m)
}
// 2. Shrink
minRune := func(r rune) rune { return 'a' }
m = Map(minRune, []byte(tenRunes(unicode.MaxRune)))
expect = a
if string(m) != expect {
t.Errorf("shrinking: expected %q got %q", expect, m)
}
// 3. Rot13
m = Map(rot13, []byte("a to zed"))
expect = "n gb mrq"
if string(m) != expect {
t.Errorf("rot13: expected %q got %q", expect, m)
}
// 4. Rot13^2
m = Map(rot13, Map(rot13, []byte("a to zed")))
expect = "a to zed"
if string(m) != expect {
t.Errorf("rot13: expected %q got %q", expect, m)
}
// 5. Drop
dropNotLatin := func(r rune) rune {
if unicode.Is(unicode.Latin, r) {
return r
}
return -1
}
m = Map(dropNotLatin, []byte("Hello, 세계"))
expect = "Hello"
if string(m) != expect {
t.Errorf("drop: expected %q got %q", expect, m)
}
// 6. Invalid rune
invalidRune := func(r rune) rune {
return utf8.MaxRune + 1
}
m = Map(invalidRune, []byte("x"))
expect = "\uFFFD"
if string(m) != expect {
t.Errorf("invalidRune: expected %q got %q", expect, m)
}
}
func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
type RepeatTest struct {
in, out string
count int
}
var RepeatTests = []RepeatTest{
{"", "", 0},
{"", "", 1},
{"", "", 2},
{"-", "", 0},
{"-", "-", 1},
{"-", "----------", 10},
{"abc ", "abc abc abc ", 3},
}
func TestRepeat(t *testing.T) {
for _, tt := range RepeatTests {
tin := []byte(tt.in)
tout := []byte(tt.out)
a := Repeat(tin, tt.count)
if !Equal(a, tout) {
t.Errorf("Repeat(%q, %d) = %q; want %q", tin, tt.count, a, tout)
continue
}
}
}
func repeat(b []byte, count int) (err error) {
defer func() {
if r := recover(); r != nil {
switch v := r.(type) {
case error:
err = v
default:
err = fmt.Errorf("%s", v)
}
}
}()
Repeat(b, count)
return
}
// See Issue golang.org/issue/16237
func TestRepeatCatchesOverflow(t *testing.T) {
tests := [...]struct {
s string
count int
errStr string
}{
0: {"--", -2147483647, "negative"},
1: {"", int(^uint(0) >> 1), ""},
2: {"-", 10, ""},
3: {"gopher", 0, ""},
4: {"-", -1, "negative"},
5: {"--", -102, "negative"},
6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
}
for i, tt := range tests {
err := repeat([]byte(tt.s), tt.count)
if tt.errStr == "" {
if err != nil {
t.Errorf("#%d panicked %v", i, err)
}
continue
}
if err == nil || !strings.Contains(err.Error(), tt.errStr) {
t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
}
}
}
func runesEqual(a, b []rune) bool {
if len(a) != len(b) {
return false
}
for i, r := range a {
if r != b[i] {
return false
}
}
return true
}
type RunesTest struct {
in string
out []rune
lossy bool
}
var RunesTests = []RunesTest{
{"", []rune{}, false},
{" ", []rune{32}, false},
{"ABC", []rune{65, 66, 67}, false},
{"abc", []rune{97, 98, 99}, false},
{"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false},
{"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true},
{"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true},
}
func TestRunes(t *testing.T) {
for _, tt := range RunesTests {
tin := []byte(tt.in)
a := Runes(tin)
if !runesEqual(a, tt.out) {
t.Errorf("Runes(%q) = %v; want %v", tin, a, tt.out)
continue
}
if !tt.lossy {
// can only test reassembly if we didn't lose information
s := string(a)
if s != tt.in {
t.Errorf("string(Runes(%q)) = %x; want %x", tin, s, tin)
}
}
}
}
type TrimTest struct {
f string
in, arg, out string
}
var trimTests = []TrimTest{
{"Trim", "abba", "a", "bb"},
{"Trim", "abba", "ab", ""},
{"TrimLeft", "abba", "ab", ""},
{"TrimRight", "abba", "ab", ""},
{"TrimLeft", "abba", "a", "bba"},
{"TrimRight", "abba", "a", "abb"},
{"Trim", "<tag>", "<>", "tag"},
{"Trim", "* listitem", " *", "listitem"},
{"Trim", `"quote"`, `"`, "quote"},
{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
//empty string tests
{"Trim", "abba", "", "abba"},
{"Trim", "", "123", ""},
{"Trim", "", "", ""},
{"TrimLeft", "abba", "", "abba"},
{"TrimLeft", "", "123", ""},
{"TrimLeft", "", "", ""},
{"TrimRight", "abba", "", "abba"},
{"TrimRight", "", "123", ""},
{"TrimRight", "", "", ""},
{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
{"TrimPrefix", "aabb", "a", "abb"},
{"TrimPrefix", "aabb", "b", "aabb"},
{"TrimSuffix", "aabb", "a", "aabb"},
{"TrimSuffix", "aabb", "b", "aab"},
}
func TestTrim(t *testing.T) {
for _, tc := range trimTests {
name := tc.f
var f func([]byte, string) []byte
var fb func([]byte, []byte) []byte
switch name {
case "Trim":
f = Trim
case "TrimLeft":
f = TrimLeft
case "TrimRight":
f = TrimRight
case "TrimPrefix":
fb = TrimPrefix
case "TrimSuffix":
fb = TrimSuffix
default:
t.Errorf("Undefined trim function %s", name)
}
var actual string
if f != nil {
actual = string(f([]byte(tc.in), tc.arg))
} else {
actual = string(fb([]byte(tc.in), []byte(tc.arg)))
}
if actual != tc.out {
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
}
}
}
type predicate struct {
f func(r rune) bool
name string
}
var isSpace = predicate{unicode.IsSpace, "IsSpace"}
var isDigit = predicate{unicode.IsDigit, "IsDigit"}
var isUpper = predicate{unicode.IsUpper, "IsUpper"}
var isValidRune = predicate{
func(r rune) bool {
return r != utf8.RuneError
},
"IsValidRune",
}
type TrimFuncTest struct {
f predicate
in, out string
}
func not(p predicate) predicate {
return predicate{
func(r rune) bool {
return !p.f(r)
},
"not " + p.name,
}
}
var trimFuncTests = []TrimFuncTest{
{isSpace, space + " hello " + space, "hello"},
{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
{not(isSpace), "hello" + space + "hello", space},
{not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"},
{isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"},
{not(isValidRune), "\xc0a\xc0", "a"},
}
func TestTrimFunc(t *testing.T) {
for _, tc := range trimFuncTests {
actual := string(TrimFunc([]byte(tc.in), tc.f.f))
if actual != tc.out {
t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out)
}
}
}
type IndexFuncTest struct {
in string
f predicate
first, last int
}
var indexFuncTests = []IndexFuncTest{
{"", isValidRune, -1, -1},
{"abc", isDigit, -1, -1},
{"0123", isDigit, 0, 3},
{"a1b", isDigit, 1, 1},
{space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes
{"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18},
{"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34},
{"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12},
// tests of invalid UTF-8
{"\x801", isDigit, 1, 1},
{"\x80abc", isDigit, -1, -1},
{"\xc0a\xc0", isValidRune, 1, 1},
{"\xc0a\xc0", not(isValidRune), 0, 2},
{"\xc0☺\xc0", not(isValidRune), 0, 4},
{"\xc0☺\xc0\xc0", not(isValidRune), 0, 5},
{"ab\xc0a\xc0cd", not(isValidRune), 2, 4},
{"a\xe0\x80cd", not(isValidRune), 1, 2},
}
func TestIndexFunc(t *testing.T) {
for _, tc := range indexFuncTests {
first := IndexFunc([]byte(tc.in), tc.f.f)
if first != tc.first {
t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first)
}
last := LastIndexFunc([]byte(tc.in), tc.f.f)
if last != tc.last {
t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last)
}
}
}
type ReplaceTest struct {
in string
old, new string
n int
out string
}
var ReplaceTests = []ReplaceTest{
{"hello", "l", "L", 0, "hello"},
{"hello", "l", "L", -1, "heLLo"},
{"hello", "x", "X", -1, "hello"},
{"", "x", "X", -1, ""},
{"radar", "r", "<r>", -1, "<r>ada<r>"},
{"", "", "<>", -1, "<>"},
{"banana", "a", "<>", -1, "b<>n<>n<>"},
{"banana", "a", "<>", 1, "b<>nana"},
{"banana", "a", "<>", 1000, "b<>n<>n<>"},
{"banana", "an", "<>", -1, "b<><>a"},
{"banana", "ana", "<>", -1, "b<>na"},
{"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"},
{"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"},
{"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"},
{"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"},
{"banana", "", "<>", 1, "<>banana"},
{"banana", "a", "a", -1, "banana"},
{"banana", "a", "a", 1, "banana"},
{"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"},
}
func TestReplace(t *testing.T) {
for _, tt := range ReplaceTests {
in := append([]byte(tt.in), "<spare>"...)
in = in[:len(tt.in)]
out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n)
if s := string(out); s != tt.out {
t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out)
}
if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n)
}
}
}
type TitleTest struct {
in, out string
}
var TitleTests = []TitleTest{
{"", ""},
{"a", "A"},
{" aaa aaa aaa ", " Aaa Aaa Aaa "},
{" Aaa Aaa Aaa ", " Aaa Aaa Aaa "},
{"123a456", "123a456"},
{"double-blind", "Double-Blind"},
{"ÿøû", "Ÿøû"},
{"with_underscore", "With_underscore"},
{"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"},
}
func TestTitle(t *testing.T) {
for _, tt := range TitleTests {
if s := string(Title([]byte(tt.in))); s != tt.out {
t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out)
}
}
}
var ToTitleTests = []TitleTest{
{"", ""},
{"a", "A"},
{" aaa aaa aaa ", " AAA AAA AAA "},
{" Aaa Aaa Aaa ", " AAA AAA AAA "},
{"123a456", "123A456"},
{"double-blind", "DOUBLE-BLIND"},
{"ÿøû", "ŸØÛ"},
}
func TestToTitle(t *testing.T) {
for _, tt := range ToTitleTests {
if s := string(ToTitle([]byte(tt.in))); s != tt.out {
t.Errorf("ToTitle(%q) = %q, want %q", tt.in, s, tt.out)
}
}
}
var EqualFoldTests = []struct {
s, t string
out bool
}{
{"abc", "abc", true},
{"ABcd", "ABcd", true},
{"123abc", "123ABC", true},
{"αβδ", "ΑΒΔ", true},
{"abc", "xyz", false},
{"abc", "XYZ", false},
{"abcdefghijk", "abcdefghijX", false},
{"abcdefghijk", "abcdefghij\u212A", true},
{"abcdefghijK", "abcdefghij\u212A", true},
{"abcdefghijkz", "abcdefghij\u212Ay", false},
{"abcdefghijKz", "abcdefghij\u212Ay", false},
}
func TestEqualFold(t *testing.T) {
for _, tt := range EqualFoldTests {
if out := EqualFold([]byte(tt.s), []byte(tt.t)); out != tt.out {
t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out)
}
if out := EqualFold([]byte(tt.t), []byte(tt.s)); out != tt.out {
t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out)
}
}
}
func TestBufferGrowNegative(t *testing.T) {
defer func() {
if err := recover(); err == nil {
t.Fatal("Grow(-1) should have panicked")
}
}()
var b Buffer
b.Grow(-1)
}
func TestBufferTruncateNegative(t *testing.T) {
defer func() {
if err := recover(); err == nil {
t.Fatal("Truncate(-1) should have panicked")
}
}()
var b Buffer
b.Truncate(-1)
}
func TestBufferTruncateOutOfRange(t *testing.T) {
defer func() {
if err := recover(); err == nil {
t.Fatal("Truncate(20) should have panicked")
}
}()
var b Buffer
b.Write(make([]byte, 10))
b.Truncate(20)
}
var containsTests = []struct {
b, subslice []byte
want bool
}{
{[]byte("hello"), []byte("hel"), true},
{[]byte("日本語"), []byte("日本"), true},
{[]byte("hello"), []byte("Hello, world"), false},
{[]byte("東京"), []byte("京東"), false},
}
func TestContains(t *testing.T) {
for _, tt := range containsTests {
if got := Contains(tt.b, tt.subslice); got != tt.want {
t.Errorf("Contains(%q, %q) = %v, want %v", tt.b, tt.subslice, got, tt.want)
}
}
}
var ContainsAnyTests = []struct {
b []byte
substr string
expected bool
}{
{[]byte(""), "", false},
{[]byte(""), "a", false},
{[]byte(""), "abc", false},
{[]byte("a"), "", false},
{[]byte("a"), "a", true},
{[]byte("aaa"), "a", true},
{[]byte("abc"), "xyz", false},
{[]byte("abc"), "xcz", true},
{[]byte("a☺b☻c☹d"), "uvw☻xyz", true},
{[]byte("aRegExp*"), ".(|)*+?^$[]", true},
{[]byte(dots + dots + dots), " ", false},
}
func TestContainsAny(t *testing.T) {
for _, ct := range ContainsAnyTests {
if ContainsAny(ct.b, ct.substr) != ct.expected {
t.Errorf("ContainsAny(%s, %s) = %v, want %v",
ct.b, ct.substr, !ct.expected, ct.expected)
}
}
}
var ContainsRuneTests = []struct {
b []byte
r rune
expected bool
}{
{[]byte(""), 'a', false},
{[]byte("a"), 'a', true},
{[]byte("aaa"), 'a', true},
{[]byte("abc"), 'y', false},
{[]byte("abc"), 'c', true},
{[]byte("a☺b☻c☹d"), 'x', false},
{[]byte("a☺b☻c☹d"), '☻', true},
{[]byte("aRegExp*"), '*', true},
}
func TestContainsRune(t *testing.T) {
for _, ct := range ContainsRuneTests {
if ContainsRune(ct.b, ct.r) != ct.expected {
t.Errorf("ContainsRune(%q, %q) = %v, want %v",
ct.b, ct.r, !ct.expected, ct.expected)
}
}
}
var makeFieldsInput = func() []byte {
x := make([]byte, 1<<20)
// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
for i := range x {
switch rand.Intn(10) {
case 0:
x[i] = ' '
case 1:
if i > 0 && x[i-1] == 'x' {
copy(x[i-1:], "χ")
break
}
fallthrough
default:
x[i] = 'x'
}
}
return x
}
var fieldsInput = makeFieldsInput()
func BenchmarkFields(b *testing.B) {
b.SetBytes(int64(len(fieldsInput)))
for i := 0; i < b.N; i++ {
Fields(fieldsInput)
}
}
func BenchmarkFieldsFunc(b *testing.B) {
b.SetBytes(int64(len(fieldsInput)))
for i := 0; i < b.N; i++ {
FieldsFunc(fieldsInput, unicode.IsSpace)
}
}
func BenchmarkTrimSpace(b *testing.B) {
s := []byte(" Some text. \n")
for i := 0; i < b.N; i++ {
TrimSpace(s)
}
}
func BenchmarkRepeat(b *testing.B) {
for i := 0; i < b.N; i++ {
Repeat([]byte("-"), 80)
}
}
func BenchmarkBytesCompare(b *testing.B) {
for n := 1; n <= 2048; n <<= 1 {
b.Run(fmt.Sprint(n), func(b *testing.B) {
var x = make([]byte, n)
var y = make([]byte, n)
for i := 0; i < n; i++ {
x[i] = 'a'
}
for i := 0; i < n; i++ {
y[i] = 'a'
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
Compare(x, y)
}
})
}
}