reflect: cache IsVariadic calls in Call

These calls are cachable, so do that in order to avoid doing extra work.

This opportunity was discovered while taking a look at a CPU profile while
investigating #7818.

I added a BenchmarkCallMethod which is similar to BechmarkCall but for a
method receiver.

Benchmark results, including the new BenchmarkCallMethod:

name                       old time/op    new time/op    delta
Call-16                      22.0ns ±19%    20.2ns ±17%  -8.08%  (p=0.000 n=40+40)
CallMethod-16                 100ns ± 3%      91ns ± 2%  -9.13%  (p=0.000 n=40+39)
CallArgCopy/size=128-16      15.7ns ± 1%    14.3ns ± 4%  -8.98%  (p=0.000 n=38+37)
CallArgCopy/size=256-16      15.9ns ± 3%    15.0ns ± 5%  -6.12%  (p=0.000 n=39+39)
CallArgCopy/size=1024-16     18.8ns ± 6%    17.1ns ± 6%  -9.03%  (p=0.000 n=38+38)
CallArgCopy/size=4096-16     26.6ns ± 3%    25.2ns ± 4%  -5.19%  (p=0.000 n=39+40)
CallArgCopy/size=65536-16     379ns ± 3%     371ns ± 5%  -2.11%  (p=0.000 n=39+40)

name                       old alloc/op   new alloc/op   delta
Call-16                       0.00B          0.00B         ~     (all equal)
CallMethod-16                 0.00B          0.00B         ~     (all equal)

name                       old allocs/op  new allocs/op  delta
Call-16                        0.00           0.00         ~     (all equal)
CallMethod-16                  0.00           0.00         ~     (all equal)

name                       old speed      new speed      delta
CallArgCopy/size=128-16    8.13GB/s ± 1%  8.92GB/s ± 4%  +9.77%  (p=0.000 n=38+38)
CallArgCopy/size=256-16    16.1GB/s ± 3%  17.1GB/s ± 5%  +6.56%  (p=0.000 n=39+39)
CallArgCopy/size=1024-16   54.6GB/s ± 6%  60.1GB/s ± 5%  +9.93%  (p=0.000 n=38+38)
CallArgCopy/size=4096-16    154GB/s ± 5%   163GB/s ± 4%  +5.63%  (p=0.000 n=40+40)
CallArgCopy/size=65536-16   173GB/s ± 3%   177GB/s ± 5%  +2.18%  (p=0.000 n=39+40)

Updates #7818.

Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
This commit is contained in:
Ignacio Hagopian 2021-01-03 11:50:01 -03:00 committed by Daniel Martí
parent 6d8084c57d
commit 6e7a43135b
1 changed files with 5 additions and 4 deletions

View File

@ -378,8 +378,9 @@ func (v Value) call(op string, in []Value) []Value {
isSlice := op == "CallSlice"
n := t.NumIn()
isVariadic := t.IsVariadic()
if isSlice {
if !t.IsVariadic() {
if !isVariadic {
panic("reflect: CallSlice of non-variadic function")
}
if len(in) < n {
@ -389,13 +390,13 @@ func (v Value) call(op string, in []Value) []Value {
panic("reflect: CallSlice with too many input arguments")
}
} else {
if t.IsVariadic() {
if isVariadic {
n--
}
if len(in) < n {
panic("reflect: Call with too few input arguments")
}
if !t.IsVariadic() && len(in) > n {
if !isVariadic && len(in) > n {
panic("reflect: Call with too many input arguments")
}
}
@ -409,7 +410,7 @@ func (v Value) call(op string, in []Value) []Value {
panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
}
}
if !isSlice && t.IsVariadic() {
if !isSlice && isVariadic {
// prepare slice for remaining values
m := len(in) - n
slice := MakeSlice(t.In(n), m, m)