Commit 7365fac2 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

runtime: use bytes.IndexByte in findnull

bytes.IndexByte is heavily optimized.
Use it in findnull.

name        old time/op  new time/op  delta
GoString-8  65.5ns ± 1%  40.2ns ± 1%  -38.62%  (p=0.000 n=19+19)

findnull is also used in gostringnocopy,
which is used in many hot spots in the runtime.

Fixes #23830

Change-Id: I2e6cb279c7d8078f8844065de684cc3567fe89d7
Reviewed-on: https://go-review.googlesource.com/97523
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 39fefa07
...@@ -31,6 +31,8 @@ struct S { ...@@ -31,6 +31,8 @@ struct S {
int x; int x;
}; };
const char *cstr = "abcefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ1234567890";
extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter); extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter);
enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; } enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; }
...@@ -149,6 +151,18 @@ func benchCgoCall(b *testing.B) { ...@@ -149,6 +151,18 @@ func benchCgoCall(b *testing.B) {
} }
} }
var sinkString string
func benchGoString(b *testing.B) {
for i := 0; i < b.N; i++ {
sinkString = C.GoString(C.cstr)
}
const want = "abcefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ1234567890"
if sinkString != want {
b.Fatalf("%q != %q", sinkString, want)
}
}
// Issue 2470. // Issue 2470.
func testUnsignedInt(t *testing.T) { func testUnsignedInt(t *testing.T) {
a := (int64)(C.UINT32VAL) a := (int64)(C.UINT32VAL)
......
...@@ -89,3 +89,4 @@ func Test21897(t *testing.T) { test21897(t) } ...@@ -89,3 +89,4 @@ func Test21897(t *testing.T) { test21897(t) }
func Test22906(t *testing.T) { test22906(t) } func Test22906(t *testing.T) { test22906(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
...@@ -121,6 +121,7 @@ func printany(i interface{}) { ...@@ -121,6 +121,7 @@ func printany(i interface{}) {
// strings.IndexByte is implemented in runtime/asm_$goarch.s // strings.IndexByte is implemented in runtime/asm_$goarch.s
// but amusingly we need go:linkname to get access to it here in the runtime. // but amusingly we need go:linkname to get access to it here in the runtime.
//go:linkname stringsIndexByte strings.IndexByte //go:linkname stringsIndexByte strings.IndexByte
//go:noescape
func stringsIndexByte(s string, c byte) int func stringsIndexByte(s string, c byte) int
// panicwrap generates a panic for a call to a wrapped value method // panicwrap generates a panic for a call to a wrapped value method
......
...@@ -407,12 +407,9 @@ func findnull(s *byte) int { ...@@ -407,12 +407,9 @@ func findnull(s *byte) int {
if s == nil { if s == nil {
return 0 return 0
} }
p := (*[maxAlloc/2 - 1]byte)(unsafe.Pointer(s)) ss := stringStruct{unsafe.Pointer(s), maxAlloc/2 - 1}
l := 0 t := *(*string)(unsafe.Pointer(&ss))
for p[l] != 0 { return stringsIndexByte(t, 0)
l++
}
return l
} }
func findnullw(s *uint16) int { func findnullw(s *uint16) int {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment