aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/iface_test.go
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josharian@gmail.com>2014-12-23 18:28:02 -0800
committerJosh Bleecher Snyder <josharian@gmail.com>2015-02-12 22:23:38 +0000
commit77a2113925b516c0ead2ae258c4d41ac3fdc0836 (patch)
tree9dce58ccff89194921957f0023c9c35a784cea29 /src/runtime/iface_test.go
parent747c8498339b799eb613db1701a927a3549d389a (diff)
downloadgo-77a2113925b516c0ead2ae258c4d41ac3fdc0836.tar.gz
go-77a2113925b516c0ead2ae258c4d41ac3fdc0836.zip
cmd/gc: evaluate concrete == interface without allocating
Consider an interface value i of type I and concrete value c of type C. Prior to this CL, i==c was evaluated as I(c) == i Evaluating I(c) can allocate. This CL changes the evaluation of i==c to x, ok := i.(C); ok && x == c The new generated code is shorter and does not allocate directly. If C is small, as it is in every instance in the stdlib, the new code also uses less stack space and makes one runtime call instead of two. If C is very large, the original implementation is used. The cutoff for "very large" is 1<<16, following the stack vs heap cutoff used elsewhere. This kind of comparison occurs in 38 places in the stdlib, mostly in the net and os packages. benchmark old ns/op new ns/op delta BenchmarkEqEfaceConcrete 29.5 7.92 -73.15% BenchmarkEqIfaceConcrete 32.1 7.90 -75.39% BenchmarkNeEfaceConcrete 29.9 7.90 -73.58% BenchmarkNeIfaceConcrete 35.9 7.90 -77.99% Fixes #9370. Change-Id: I7c4555950bcd6406ee5c613be1f2128da2c9a2b7 Reviewed-on: https://go-review.googlesource.com/2096 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Diffstat (limited to 'src/runtime/iface_test.go')
-rw-r--r--src/runtime/iface_test.go42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/runtime/iface_test.go b/src/runtime/iface_test.go
index bca0ea0ee7..bfeb94b8aa 100644
--- a/src/runtime/iface_test.go
+++ b/src/runtime/iface_test.go
@@ -5,6 +5,7 @@
package runtime_test
import (
+ "runtime"
"testing"
)
@@ -38,6 +39,47 @@ var (
tl TL
)
+// Issue 9370
+func TestCmpIfaceConcreteAlloc(t *testing.T) {
+ if runtime.Compiler != "gc" {
+ t.Skip("skipping on non-gc compiler")
+ }
+
+ n := testing.AllocsPerRun(1, func() {
+ _ = e == ts
+ _ = i1 == ts
+ _ = e == 1
+ })
+
+ if n > 0 {
+ t.Fatalf("iface cmp allocs=%v; want 0", n)
+ }
+}
+
+func BenchmarkEqEfaceConcrete(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ _ = e == ts
+ }
+}
+
+func BenchmarkEqIfaceConcrete(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ _ = i1 == ts
+ }
+}
+
+func BenchmarkNeEfaceConcrete(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ _ = e != ts
+ }
+}
+
+func BenchmarkNeIfaceConcrete(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ _ = i1 != ts
+ }
+}
+
func BenchmarkConvT2ESmall(b *testing.B) {
for i := 0; i < b.N; i++ {
e = ts