unicode: performance improvements (API change)
*** There is an API change here: the introduction of the
LatinOffset int in the RangeTable struct. ***
* Avoid checking Latin range multiple times for non-Latin runes.
* Use linear search when it is faster than binary search.
go test -calibrate runs the calibration for where the linear/binary
crossover should be.
benchmark old MB/s new MB/s speedup
BenchmarkFields 36.27 41.43 1.14x
BenchmarkFieldsFunc 36.23 41.38 1.14x
The speedup here is evenly split between the linear scans
and the LatinOffset change. Both are about 1.07x.
R=r
CC=bradfitz, gobot, golang-dev
https://golang.org/cl/6526048
diff --git a/src/pkg/unicode/maketables.go b/src/pkg/unicode/maketables.go
index fcd14fc..2ed1915 100644
--- a/src/pkg/unicode/maketables.go
+++ b/src/pkg/unicode/maketables.go
@@ -503,6 +503,7 @@
func dumpRange(header string, inCategory Op) {
fmt.Print(header)
next := rune(0)
+ latinOffset := 0
fmt.Print("\tR16: []Range16{\n")
// one Range for each iteration
count := &range16Count
@@ -546,11 +547,17 @@
break
}
}
+ if uint32(hi) <= unicode.MaxLatin1 {
+ latinOffset++
+ }
size, count = printRange(uint32(lo), uint32(hi), uint32(stride), size, count)
// next range: start looking where this range ends
next = hi + 1
}
fmt.Print("\t},\n")
+ if latinOffset > 0 {
+ fmt.Printf("\tLatinOffset: %d,\n", latinOffset)
+ }
fmt.Print("}\n\n")
}
@@ -760,14 +767,17 @@
}
ndecl++
fmt.Printf("var _%s = &RangeTable {\n", name)
- fmt.Print("\tR16: []Range16{\n")
ranges := foldAdjacent(table[name])
+ fmt.Print("\tR16: []Range16{\n")
size := 16
count := &range16Count
for _, s := range ranges {
size, count = printRange(s.Lo, s.Hi, s.Stride, size, count)
}
fmt.Print("\t},\n")
+ if off := findLatinOffset(ranges); off > 0 {
+ fmt.Printf("\tLatinOffset: %d,\n", off)
+ }
fmt.Print("}\n\n")
}
decl.Sort()
@@ -779,6 +789,14 @@
fmt.Print(")\n\n")
}
+func findLatinOffset(ranges []unicode.Range32) int {
+ i := 0
+ for i < len(ranges) && ranges[i].Hi <= unicode.MaxLatin1 {
+ i++
+ }
+ return i
+}
+
const (
CaseUpper = 1 << iota
CaseLower