Permalink
Browse files

runtime: use zeroVal for small zero values in interfaces

Fixes golang#17725

name                old time/op    new time/op    delta
ConvT2EInt/const-8    0.90ns ± 4%    0.90ns ± 2%      ~     (p=0.623 n=20+15)
ConvT2EInt/zero-8     21.5ns ± 2%     7.4ns ± 6%   -65.33%  (p=0.000 n=19+18)
ConvT2EInt/one-8      21.6ns ± 2%    22.8ns ± 2%    +5.21%  (p=0.000 n=20+19)

name                old alloc/op   new alloc/op   delta
ConvT2EInt/const-8     0.00B          0.00B           ~     (all equal)
ConvT2EInt/zero-8      8.00B ± 0%     0.00B       -100.00%  (p=0.000 n=20+20)
ConvT2EInt/one-8       8.00B ± 0%     8.00B ± 0%      ~     (all equal)

name                old allocs/op  new allocs/op  delta
ConvT2EInt/const-8      0.00           0.00           ~     (all equal)
ConvT2EInt/zero-8       1.00 ± 0%      0.00       -100.00%  (p=0.000 n=20+20)
ConvT2EInt/one-8        1.00 ± 0%      1.00 ± 0%      ~     (all equal)

Change-Id: I5b71f9e44e3de8b8f2284a3821c5176c13ab2c61
  • Loading branch information...
josharian committed Jan 22, 2017
1 parent 766fc9a commit a9d47ff773cc584ff64777c14231922ed8e2964d
Showing with 36 additions and 6 deletions.
  1. +36 −6 src/runtime/iface.go
View
@@ -199,10 +199,25 @@ func convT2E(t *_type, elem unsafe.Pointer) (e eface) {
// This case is implemented directly by the compiler.
throw("direct convT2E")
}
x := newobject(t)
// TODO: We allocate a zeroed object only to overwrite it with
// actual data. Figure out how to avoid zeroing. Also below in convT2I.
typedmemmove(t, x, elem)
var x unsafe.Pointer
if t.size <= unsafe.Sizeof(zeroVal) {
iszero := true
for i := uintptr(0); i < t.size; i++ {
if *(*byte)(unsafe.Pointer(uintptr(elem) + i)) != 0 {
iszero = false
break
}
}
if iszero {
x = unsafe.Pointer(&zeroVal)
}
}
if x == nil {
// TODO: We allocate a zeroed object only to overwrite it with
// actual data. Figure out how to avoid zeroing. Also below in convT2I.
x = newobject(t)
typedmemmove(t, x, elem)
}
e._type = t
e.data = x
return
@@ -220,8 +235,23 @@ func convT2I(tab *itab, elem unsafe.Pointer) (i iface) {
// This case is implemented directly by the compiler.
throw("direct convT2I")
}
x := newobject(t)
typedmemmove(t, x, elem)
var x unsafe.Pointer
if t.size <= unsafe.Sizeof(zeroVal) {
iszero := true
for i := uintptr(0); i < t.size; i++ {
if *(*byte)(unsafe.Pointer(uintptr(elem) + i)) != 0 {
iszero = false
break
}
}
if iszero {
x = unsafe.Pointer(&zeroVal[0])
}
}
if x == nil {
x = newobject(t)
typedmemmove(t, x, elem)
}
i.tab = tab
i.data = x
return

0 comments on commit a9d47ff

Please sign in to comment.