reflect: make Value an opaque struct
Making Value opaque means we can drop the interface kludges
in favor of a significantly simpler and faster representation.
v.Kind() will be a prime candidate for inlining too.
On a Thinkpad X201s using -benchtime 10:
benchmark old ns/op new ns/op delta
json.BenchmarkCodeEncoder 284391780 157415960 -44.65%
json.BenchmarkCodeMarshal 286979140 158992020 -44.60%
json.BenchmarkCodeDecoder 717175800 388288220 -45.86%
json.BenchmarkCodeUnmarshal 734470500 404548520 -44.92%
json.BenchmarkCodeUnmarshalReuse 707172280 385258720 -45.52%
json.BenchmarkSkipValue 24630036 18557062 -24.66%
benchmark old MB/s new MB/s speedup
json.BenchmarkCodeEncoder 6.82 12.33 1.81x
json.BenchmarkCodeMarshal 6.76 12.20 1.80x
json.BenchmarkCodeDecoder 2.71 5.00 1.85x
json.BenchmarkCodeUnmarshal 2.64 4.80 1.82x
json.BenchmarkCodeUnmarshalReuse 2.74 5.04 1.84x
json.BenchmarkSkipValue 77.92 103.42 1.33x
I cannot explain why BenchmarkSkipValue gets faster.
Maybe it is one of those code alignment things.
R=iant, r, gri, r
CC=golang-dev
https://golang.org/cl/5373101
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index 2f6917d..b35373c 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -16,6 +16,13 @@
"unsafe"
)
+func TestBool(t *testing.T) {
+ v := ValueOf(true)
+ if v.Bool() != true {
+ t.Fatal("ValueOf(true).Bool() = false")
+ }
+}
+
type integer int
type T struct {
a int
@@ -215,7 +222,8 @@
func TestSet(t *testing.T) {
for i, tt := range valueTests {
- v := ValueOf(tt.i).Elem()
+ v := ValueOf(tt.i)
+ v = v.Elem()
switch v.Kind() {
case Int:
v.SetInt(132)
@@ -1100,21 +1108,38 @@
}
// Curried method of value.
- i = ValueOf(p).Method(1).Call([]Value{ValueOf(10)})[0].Int()
+ tfunc := TypeOf(func(int) int(nil))
+ v := ValueOf(p).Method(1)
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(10)})[0].Int()
if i != 250 {
t.Errorf("Value Method returned %d; want 250", i)
}
- i = ValueOf(p).MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int()
+ v = ValueOf(p).MethodByName("Dist")
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(10)})[0].Int()
if i != 250 {
t.Errorf("Value MethodByName returned %d; want 250", i)
}
// Curried method of pointer.
- i = ValueOf(&p).Method(1).Call([]Value{ValueOf(10)})[0].Int()
+ v = ValueOf(&p).Method(1)
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(10)})[0].Int()
if i != 250 {
t.Errorf("Pointer Value Method returned %d; want 250", i)
}
- i = ValueOf(&p).MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int()
+ v = ValueOf(&p).MethodByName("Dist")
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(10)})[0].Int()
if i != 250 {
t.Errorf("Pointer Value MethodByName returned %d; want 250", i)
}
@@ -1129,11 +1154,19 @@
}
}{p}
pv := ValueOf(s).Field(0)
- i = pv.Method(0).Call([]Value{ValueOf(10)})[0].Int()
+ v = pv.Method(0)
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(10)})[0].Int()
if i != 250 {
t.Errorf("Interface Method returned %d; want 250", i)
}
- i = pv.MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int()
+ v = pv.MethodByName("Dist")
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(10)})[0].Int()
if i != 250 {
t.Errorf("Interface MethodByName returned %d; want 250", i)
}