[
https://issues.apache.org/jira/browse/BEAM-3388?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16321484#comment-16321484
]
ASF GitHub Bot commented on BEAM-3388:
--------------------------------------
aaltay closed pull request #4373: [BEAM-3388] Add general-purpose
reflection-free function calls in Go runtime
URL: https://github.com/apache/beam/pull/4373
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/sdks/go/cmd/specialize/main.go b/sdks/go/cmd/specialize/main.go
index 67863041975..6ee82b589a3 100644
--- a/sdks/go/cmd/specialize/main.go
+++ b/sdks/go/cmd/specialize/main.go
@@ -32,7 +32,11 @@ import (
)
var (
- x = flag.String("x", "", "Comma-separated list of X types")
+ noheader = flag.Bool("noheader", false, "Omit auto-generated header")
+ pack = flag.String("package", "", "Package name (optional)")
+ imports = flag.String("imports", "", "Comma-separated list of extra
imports (optional)")
+
+ x = flag.String("x", "", "Comma-separated list of X types (optional)")
y = flag.String("y", "", "Comma-separated list of Y types (optional)")
z = flag.String("z", "", "Comma-separated list of Z types (optional)")
@@ -42,8 +46,12 @@ var (
// Top is the top-level struct to be passed to the template.
type Top struct {
- // Name is the base form of the filename: "foo/bar.go.templ" -> "bar".
+ // Name is the base form of the filename: "foo/bar.tmpl" -> "bar".
Name string
+ // Package is the package name.
+ Package string
+ // Imports is a list of custom imports, if provided.
+ Imports []string
// X is the list of X type values.
X []*X
}
@@ -88,7 +96,11 @@ var (
"floats": floats,
"primitives": primitives,
"data": append([]string{"[]byte"}, primitives...),
- "universals": []string{"typex.T", "typex.U", "typex.V",
"typex.W", "typex.X", "typex.Y", "typex.Z"},
+ "universals": {"typex.T", "typex.U", "typex.V", "typex.W",
"typex.X", "typex.Y", "typex.Z"},
+ }
+
+ packageMacros = map[string][]string{
+ "typex": {"github.com/apache/beam/sdks/go/pkg/beam/core/typex"},
}
)
@@ -108,10 +120,6 @@ func main() {
flag.Usage()
log.Fatalf("no template file")
}
- if *x == "" {
- flag.Usage()
- log.Fatalf("no specialization types")
- }
name := filepath.Base(*input)
if index := strings.Index(name, "."); index > 0 {
@@ -121,30 +129,32 @@ func main() {
*output = filepath.Join(filepath.Dir(*input), name+".go")
}
- top := Top{name, nil}
+ top := Top{Name: name, Package: *pack, Imports: expand(packageMacros,
*imports)}
var ys []*Y
if *y != "" {
var zs []*Z
if *z != "" {
- for _, zt := range expand(*z) {
+ for _, zt := range expand(macros, *z) {
zs = append(zs, &Z{Name: makeName(zt), Type:
zt})
}
}
- for _, yt := range expand(*y) {
+ for _, yt := range expand(macros, *y) {
ys = append(ys, &Y{Name: makeName(yt), Type: yt, Z: zs})
}
}
- for _, xt := range expand(*x) {
+ for _, xt := range expand(macros, *x) {
top.X = append(top.X, &X{Name: makeName(xt), Type: xt, Y: ys})
}
- tmpl, err := template.ParseFiles(*input)
+ tmpl, err := template.New(*input).Funcs(funcMap).ParseFiles(*input)
if err != nil {
log.Fatalf("template parse failed: %v", err)
}
var buf bytes.Buffer
- buf.WriteString("// File generated by specialize. Do not edit.\n\n")
- if err := tmpl.Execute(&buf, top); err != nil {
+ if !*noheader {
+ buf.WriteString("// File generated by specialize. Do not
edit.\n\n")
+ }
+ if err := tmpl.Funcs(funcMap).Execute(&buf, top); err != nil {
log.Fatalf("specialization failed: %v", err)
}
if err := ioutil.WriteFile(*output, buf.Bytes(), 0644); err != nil {
@@ -153,14 +163,14 @@ func main() {
}
// expand parses, cleans up and expands macros for a comma-separated list.
-func expand(list string) []string {
+func expand(subst map[string][]string, list string) []string {
var ret []string
for _, xt := range strings.Split(list, ",") {
xt = strings.TrimSpace(xt)
if xt == "" {
continue
}
- if exp, ok := macros[strings.ToLower(xt)]; ok {
+ if exp, ok := subst[strings.ToLower(xt)]; ok {
for _, t := range exp {
ret = append(ret, t)
}
@@ -182,3 +192,49 @@ func makeName(t string) string {
t = strings.Replace(t, "]", "_", -1)
return strings.Title(t)
}
+
+// Useful template functions
+
+var funcMap template.FuncMap = map[string]interface{}{
+ "join": strings.Join,
+ "upto": upto,
+ "mkargs": mkargs,
+ "mktuple": mktuple,
+ "mktuplef": mktuplef,
+}
+
+// mkargs(n, type) returns "<fmt.Sprintf(format, 0)>, .., <fmt.Sprintf(format,
n-1)> type".
+// If n is 0, it returns the empty string.
+func mkargs(n int, format, typ string) string {
+ if n == 0 {
+ return ""
+ }
+ return fmt.Sprintf("%v %v", mktuplef(n, format), typ)
+}
+
+// mktuple(n, v) returns "v, v, ..., v".
+func mktuple(n int, v string) string {
+ var ret []string
+ for i := 0; i < n; i++ {
+ ret = append(ret, v)
+ }
+ return strings.Join(ret, ", ")
+}
+
+// mktuplef(n, format) returns "<fmt.Sprintf(format, 0)>, ..,
<fmt.Sprintf(format, n-1)>"
+func mktuplef(n int, format string) string {
+ var ret []string
+ for i := 0; i < n; i++ {
+ ret = append(ret, fmt.Sprintf(format, i))
+ }
+ return strings.Join(ret, ", ")
+}
+
+// upto(n) returns []int{0, 1, .., n-1}.
+func upto(i int) []int {
+ var ret []int
+ for k := 0; k < i; k++ {
+ ret = append(ret, k)
+ }
+ return ret
+}
diff --git a/sdks/go/pkg/beam/core/runtime/exec/callers.go
b/sdks/go/pkg/beam/core/runtime/exec/callers.go
new file mode 100644
index 00000000000..8c374bf9624
--- /dev/null
+++ b/sdks/go/pkg/beam/core/runtime/exec/callers.go
@@ -0,0 +1,544 @@
+// File generated by specialize. Do not edit.
+
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exec
+
+import (
+ "reflect"
+
+ "github.com/apache/beam/sdks/go/pkg/beam/core/typex"
+ "github.com/apache/beam/sdks/go/pkg/beam/core/util/reflectx"
+)
+
+// TODO(herohde) 1/4/2018: Potential targets for type-specialization include
simple predicate,
+// dofn and combiner forms.
+//
+// (1) func(X) bool // unary predicate
+// (2) func(X, X) X // binary combiner merge
+// (3) func(ctx?, X) (X, error?) // simple DoFn with direct output
+// (4) func(ctx?, X, func(X)) (error?) // simple DoFn with emitter
+//
+// For now, we just do #2.
+
+func init() {
+ reflectx.RegisterCaller(reflect.TypeOf((*func([]byte, []byte)
[]byte)(nil)).Elem(), callMakerByteSliceM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(bool, bool)
bool)(nil)).Elem(), callMakerBoolM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(string, string)
string)(nil)).Elem(), callMakerStringM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(int, int)
int)(nil)).Elem(), callMakerIntM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(int8, int8)
int8)(nil)).Elem(), callMakerInt8M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(int16, int16)
int16)(nil)).Elem(), callMakerInt16M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(int32, int32)
int32)(nil)).Elem(), callMakerInt32M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(int64, int64)
int64)(nil)).Elem(), callMakerInt64M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(uint, uint)
uint)(nil)).Elem(), callMakerUintM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(uint8, uint8)
uint8)(nil)).Elem(), callMakerUint8M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(uint16, uint16)
uint16)(nil)).Elem(), callMakerUint16M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(uint32, uint32)
uint32)(nil)).Elem(), callMakerUint32M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(uint64, uint64)
uint64)(nil)).Elem(), callMakerUint64M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(float32, float32)
float32)(nil)).Elem(), callMakerFloat32M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(float64, float64)
float64)(nil)).Elem(), callMakerFloat64M)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(typex.T, typex.T)
typex.T)(nil)).Elem(), callMakerTypex_TM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(typex.U, typex.U)
typex.U)(nil)).Elem(), callMakerTypex_UM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(typex.V, typex.V)
typex.V)(nil)).Elem(), callMakerTypex_VM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(typex.W, typex.W)
typex.W)(nil)).Elem(), callMakerTypex_WM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(typex.X, typex.X)
typex.X)(nil)).Elem(), callMakerTypex_XM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(typex.Y, typex.Y)
typex.Y)(nil)).Elem(), callMakerTypex_YM)
+ reflectx.RegisterCaller(reflect.TypeOf((*func(typex.Z, typex.Z)
typex.Z)(nil)).Elem(), callMakerTypex_ZM)
+}
+
+type nativeByteSliceMCaller struct {
+ fn func([]byte, []byte) []byte
+}
+
+func callMakerByteSliceM(fn interface{}) reflectx.Caller {
+ f := fn.(func([]byte, []byte) []byte)
+ return &nativeByteSliceMCaller{fn: f}
+}
+
+func (c *nativeByteSliceMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeByteSliceMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].([]byte), args[1].([]byte))
+ return []interface{}{out}
+}
+
+func (c *nativeByteSliceMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.([]byte), b.([]byte))
+}
+
+type nativeBoolMCaller struct {
+ fn func(bool, bool) bool
+}
+
+func callMakerBoolM(fn interface{}) reflectx.Caller {
+ f := fn.(func(bool, bool) bool)
+ return &nativeBoolMCaller{fn: f}
+}
+
+func (c *nativeBoolMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeBoolMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(bool), args[1].(bool))
+ return []interface{}{out}
+}
+
+func (c *nativeBoolMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(bool), b.(bool))
+}
+
+type nativeStringMCaller struct {
+ fn func(string, string) string
+}
+
+func callMakerStringM(fn interface{}) reflectx.Caller {
+ f := fn.(func(string, string) string)
+ return &nativeStringMCaller{fn: f}
+}
+
+func (c *nativeStringMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeStringMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(string), args[1].(string))
+ return []interface{}{out}
+}
+
+func (c *nativeStringMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(string), b.(string))
+}
+
+type nativeIntMCaller struct {
+ fn func(int, int) int
+}
+
+func callMakerIntM(fn interface{}) reflectx.Caller {
+ f := fn.(func(int, int) int)
+ return &nativeIntMCaller{fn: f}
+}
+
+func (c *nativeIntMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeIntMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(int), args[1].(int))
+ return []interface{}{out}
+}
+
+func (c *nativeIntMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(int), b.(int))
+}
+
+type nativeInt8MCaller struct {
+ fn func(int8, int8) int8
+}
+
+func callMakerInt8M(fn interface{}) reflectx.Caller {
+ f := fn.(func(int8, int8) int8)
+ return &nativeInt8MCaller{fn: f}
+}
+
+func (c *nativeInt8MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeInt8MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(int8), args[1].(int8))
+ return []interface{}{out}
+}
+
+func (c *nativeInt8MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(int8), b.(int8))
+}
+
+type nativeInt16MCaller struct {
+ fn func(int16, int16) int16
+}
+
+func callMakerInt16M(fn interface{}) reflectx.Caller {
+ f := fn.(func(int16, int16) int16)
+ return &nativeInt16MCaller{fn: f}
+}
+
+func (c *nativeInt16MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeInt16MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(int16), args[1].(int16))
+ return []interface{}{out}
+}
+
+func (c *nativeInt16MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(int16), b.(int16))
+}
+
+type nativeInt32MCaller struct {
+ fn func(int32, int32) int32
+}
+
+func callMakerInt32M(fn interface{}) reflectx.Caller {
+ f := fn.(func(int32, int32) int32)
+ return &nativeInt32MCaller{fn: f}
+}
+
+func (c *nativeInt32MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeInt32MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(int32), args[1].(int32))
+ return []interface{}{out}
+}
+
+func (c *nativeInt32MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(int32), b.(int32))
+}
+
+type nativeInt64MCaller struct {
+ fn func(int64, int64) int64
+}
+
+func callMakerInt64M(fn interface{}) reflectx.Caller {
+ f := fn.(func(int64, int64) int64)
+ return &nativeInt64MCaller{fn: f}
+}
+
+func (c *nativeInt64MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeInt64MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(int64), args[1].(int64))
+ return []interface{}{out}
+}
+
+func (c *nativeInt64MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(int64), b.(int64))
+}
+
+type nativeUintMCaller struct {
+ fn func(uint, uint) uint
+}
+
+func callMakerUintM(fn interface{}) reflectx.Caller {
+ f := fn.(func(uint, uint) uint)
+ return &nativeUintMCaller{fn: f}
+}
+
+func (c *nativeUintMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeUintMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(uint), args[1].(uint))
+ return []interface{}{out}
+}
+
+func (c *nativeUintMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(uint), b.(uint))
+}
+
+type nativeUint8MCaller struct {
+ fn func(uint8, uint8) uint8
+}
+
+func callMakerUint8M(fn interface{}) reflectx.Caller {
+ f := fn.(func(uint8, uint8) uint8)
+ return &nativeUint8MCaller{fn: f}
+}
+
+func (c *nativeUint8MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeUint8MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(uint8), args[1].(uint8))
+ return []interface{}{out}
+}
+
+func (c *nativeUint8MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(uint8), b.(uint8))
+}
+
+type nativeUint16MCaller struct {
+ fn func(uint16, uint16) uint16
+}
+
+func callMakerUint16M(fn interface{}) reflectx.Caller {
+ f := fn.(func(uint16, uint16) uint16)
+ return &nativeUint16MCaller{fn: f}
+}
+
+func (c *nativeUint16MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeUint16MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(uint16), args[1].(uint16))
+ return []interface{}{out}
+}
+
+func (c *nativeUint16MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(uint16), b.(uint16))
+}
+
+type nativeUint32MCaller struct {
+ fn func(uint32, uint32) uint32
+}
+
+func callMakerUint32M(fn interface{}) reflectx.Caller {
+ f := fn.(func(uint32, uint32) uint32)
+ return &nativeUint32MCaller{fn: f}
+}
+
+func (c *nativeUint32MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeUint32MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(uint32), args[1].(uint32))
+ return []interface{}{out}
+}
+
+func (c *nativeUint32MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(uint32), b.(uint32))
+}
+
+type nativeUint64MCaller struct {
+ fn func(uint64, uint64) uint64
+}
+
+func callMakerUint64M(fn interface{}) reflectx.Caller {
+ f := fn.(func(uint64, uint64) uint64)
+ return &nativeUint64MCaller{fn: f}
+}
+
+func (c *nativeUint64MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeUint64MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(uint64), args[1].(uint64))
+ return []interface{}{out}
+}
+
+func (c *nativeUint64MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(uint64), b.(uint64))
+}
+
+type nativeFloat32MCaller struct {
+ fn func(float32, float32) float32
+}
+
+func callMakerFloat32M(fn interface{}) reflectx.Caller {
+ f := fn.(func(float32, float32) float32)
+ return &nativeFloat32MCaller{fn: f}
+}
+
+func (c *nativeFloat32MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeFloat32MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(float32), args[1].(float32))
+ return []interface{}{out}
+}
+
+func (c *nativeFloat32MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(float32), b.(float32))
+}
+
+type nativeFloat64MCaller struct {
+ fn func(float64, float64) float64
+}
+
+func callMakerFloat64M(fn interface{}) reflectx.Caller {
+ f := fn.(func(float64, float64) float64)
+ return &nativeFloat64MCaller{fn: f}
+}
+
+func (c *nativeFloat64MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeFloat64MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(float64), args[1].(float64))
+ return []interface{}{out}
+}
+
+func (c *nativeFloat64MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(float64), b.(float64))
+}
+
+type nativeTypex_TMCaller struct {
+ fn func(typex.T, typex.T) typex.T
+}
+
+func callMakerTypex_TM(fn interface{}) reflectx.Caller {
+ f := fn.(func(typex.T, typex.T) typex.T)
+ return &nativeTypex_TMCaller{fn: f}
+}
+
+func (c *nativeTypex_TMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeTypex_TMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(typex.T), args[1].(typex.T))
+ return []interface{}{out}
+}
+
+func (c *nativeTypex_TMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(typex.T), b.(typex.T))
+}
+
+type nativeTypex_UMCaller struct {
+ fn func(typex.U, typex.U) typex.U
+}
+
+func callMakerTypex_UM(fn interface{}) reflectx.Caller {
+ f := fn.(func(typex.U, typex.U) typex.U)
+ return &nativeTypex_UMCaller{fn: f}
+}
+
+func (c *nativeTypex_UMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeTypex_UMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(typex.U), args[1].(typex.U))
+ return []interface{}{out}
+}
+
+func (c *nativeTypex_UMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(typex.U), b.(typex.U))
+}
+
+type nativeTypex_VMCaller struct {
+ fn func(typex.V, typex.V) typex.V
+}
+
+func callMakerTypex_VM(fn interface{}) reflectx.Caller {
+ f := fn.(func(typex.V, typex.V) typex.V)
+ return &nativeTypex_VMCaller{fn: f}
+}
+
+func (c *nativeTypex_VMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeTypex_VMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(typex.V), args[1].(typex.V))
+ return []interface{}{out}
+}
+
+func (c *nativeTypex_VMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(typex.V), b.(typex.V))
+}
+
+type nativeTypex_WMCaller struct {
+ fn func(typex.W, typex.W) typex.W
+}
+
+func callMakerTypex_WM(fn interface{}) reflectx.Caller {
+ f := fn.(func(typex.W, typex.W) typex.W)
+ return &nativeTypex_WMCaller{fn: f}
+}
+
+func (c *nativeTypex_WMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeTypex_WMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(typex.W), args[1].(typex.W))
+ return []interface{}{out}
+}
+
+func (c *nativeTypex_WMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(typex.W), b.(typex.W))
+}
+
+type nativeTypex_XMCaller struct {
+ fn func(typex.X, typex.X) typex.X
+}
+
+func callMakerTypex_XM(fn interface{}) reflectx.Caller {
+ f := fn.(func(typex.X, typex.X) typex.X)
+ return &nativeTypex_XMCaller{fn: f}
+}
+
+func (c *nativeTypex_XMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeTypex_XMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(typex.X), args[1].(typex.X))
+ return []interface{}{out}
+}
+
+func (c *nativeTypex_XMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(typex.X), b.(typex.X))
+}
+
+type nativeTypex_YMCaller struct {
+ fn func(typex.Y, typex.Y) typex.Y
+}
+
+func callMakerTypex_YM(fn interface{}) reflectx.Caller {
+ f := fn.(func(typex.Y, typex.Y) typex.Y)
+ return &nativeTypex_YMCaller{fn: f}
+}
+
+func (c *nativeTypex_YMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeTypex_YMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(typex.Y), args[1].(typex.Y))
+ return []interface{}{out}
+}
+
+func (c *nativeTypex_YMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(typex.Y), b.(typex.Y))
+}
+
+type nativeTypex_ZMCaller struct {
+ fn func(typex.Z, typex.Z) typex.Z
+}
+
+func callMakerTypex_ZM(fn interface{}) reflectx.Caller {
+ f := fn.(func(typex.Z, typex.Z) typex.Z)
+ return &nativeTypex_ZMCaller{fn: f}
+}
+
+func (c *nativeTypex_ZMCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *nativeTypex_ZMCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].(typex.Z), args[1].(typex.Z))
+ return []interface{}{out}
+}
+
+func (c *nativeTypex_ZMCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.(typex.Z), b.(typex.Z))
+}
diff --git a/sdks/go/pkg/beam/core/runtime/exec/callers.tmpl
b/sdks/go/pkg/beam/core/runtime/exec/callers.tmpl
new file mode 100644
index 00000000000..36d427b16f7
--- /dev/null
+++ b/sdks/go/pkg/beam/core/runtime/exec/callers.tmpl
@@ -0,0 +1,63 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exec
+
+import (
+ "reflect"
+
+ "github.com/apache/beam/sdks/go/pkg/beam/core/typex"
+ "github.com/apache/beam/sdks/go/pkg/beam/core/util/reflectx"
+)
+
+// TODO(herohde) 1/4/2018: Potential targets for type-specialization include
simple predicate,
+// dofn and combiner forms.
+//
+// (1) func(X) bool // unary predicate
+// (2) func(X, X) X // binary combiner merge
+// (3) func(ctx?, X) (X, error?) // simple DoFn with direct output
+// (4) func(ctx?, X, func(X)) (error?) // simple DoFn with emitter
+//
+// For now, we just do #2.
+
+func init() {
+{{- range $x := .X}}
+ reflectx.RegisterCaller(reflect.TypeOf((*func ({{$x.Type}},
{{$x.Type}}){{$x.Type}})(nil)).Elem(), callMaker{{$x.Name}}M)
+{{- end}}
+}
+
+{{range $x := .X}}
+type native{{$x.Name}}MCaller struct {
+ fn func ({{$x.Type}}, {{$x.Type}}){{$x.Type}}
+}
+
+func callMaker{{$x.Name}}M(fn interface{}) reflectx.Caller {
+ f := fn.(func ({{$x.Type}}, {{$x.Type}}){{$x.Type}})
+ return &native{{$x.Name}}MCaller{fn: f}
+}
+
+func (c *native{{$x.Name}}MCaller) Type() reflect.Type {
+ return reflect.TypeOf(c.fn)
+}
+
+func (c *native{{$x.Name}}MCaller) Call(args []interface{}) []interface{} {
+ out := c.fn(args[0].({{$x.Type}}), args[1].({{$x.Type}}))
+ return []interface{}{out}
+}
+
+func (c *native{{$x.Name}}MCaller) Call2x1(a, b interface{}) interface{} {
+ return c.fn(a.({{$x.Type}}), b.({{$x.Type}}))
+}
+{{end}}
diff --git a/sdks/go/pkg/beam/core/runtime/exec/combine.go
b/sdks/go/pkg/beam/core/runtime/exec/combine.go
index 6c040423b91..84c064aaefd 100644
--- a/sdks/go/pkg/beam/core/runtime/exec/combine.go
+++ b/sdks/go/pkg/beam/core/runtime/exec/combine.go
@@ -39,6 +39,8 @@ type Combine struct {
first bool
isPerKey, usesKey bool
+ mergeFn reflectx.Caller2x1 // optimized caller in the case of binary
merge accumulators
+
status Status
err errorx.GuardedError
}
@@ -57,6 +59,10 @@ func (n *Combine) Up(ctx context.Context) error {
return n.fail(err)
}
+ if n.Edge.CombineFn.AddInputFn() == nil {
+ n.mergeFn =
reflectx.MakeCaller2x1(n.Edge.CombineFn.MergeAccumulatorsFn().Fn.Interface())
+ }
+
// TODO(herohde) 6/28/2017: maybe record the per-key mode in the Edge
// instead of inferring it here?
@@ -209,12 +215,7 @@ func (n *Combine) addInput(ctx context.Context, accum,
key, value reflect.Value,
a := reflectx.UnderlyingType(accum)
b := reflectx.UnderlyingType(value)
-
- val, err := Invoke(ctx, n.Edge.CombineFn.MergeAccumulatorsFn(),
nil, a, b)
- if err != nil {
- return reflect.Value{},
n.fail(fmt.Errorf("MergeAccumulators failed: %v", err))
- }
- return val.Elm, err
+ return reflect.ValueOf(n.mergeFn.Call2x1(a.Interface(),
b.Interface())), nil
}
opt := &MainInput{
diff --git a/sdks/go/pkg/beam/core/runtime/exec/fn.go
b/sdks/go/pkg/beam/core/runtime/exec/fn.go
index 15c0e287707..d23ec329d81 100644
--- a/sdks/go/pkg/beam/core/runtime/exec/fn.go
+++ b/sdks/go/pkg/beam/core/runtime/exec/fn.go
@@ -25,6 +25,8 @@ import (
"github.com/apache/beam/sdks/go/pkg/beam/core/typex"
)
+//go:generate specialize --input=callers.tmpl --x=data,universals
+
// NOTE(herohde) 12/11/2017: the below helpers are ripe for
type-specialization,
// if the reflection overhead here turns out to be significant. It would
// be nice to be able to quantify any potential improvements first, however.
diff --git a/sdks/go/pkg/beam/core/util/reflectx/call.go
b/sdks/go/pkg/beam/core/util/reflectx/call.go
new file mode 100644
index 00000000000..ebac4da813d
--- /dev/null
+++ b/sdks/go/pkg/beam/core/util/reflectx/call.go
@@ -0,0 +1,100 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package reflectx
+
+import (
+ "context"
+ "reflect"
+ "sync"
+
+ "github.com/apache/beam/sdks/go/pkg/beam/log"
+)
+
+//go:generate specialize --input=calls.tmpl
+
+// Caller is an untyped function call interface. This indirection allows
+// us to avoid reflection call overhead for certain types.
+type Caller interface {
+ // Type returns the type.
+ Type() reflect.Type
+ // Call invokes the implicit fn with arguments.
+ Call(args []interface{}) []interface{}
+}
+
+var (
+ callers = make(map[string]func(interface{}) Caller)
+ callersMu sync.Mutex
+)
+
+// RegisterCaller registers an custom caller factory for the given type, such
as
+// "func(int)bool". If multiple caller factories are registered for the same
type,
+// the last registration wins.
+func RegisterCaller(t reflect.Type, maker func(interface{}) Caller) {
+ callersMu.Lock()
+ defer callersMu.Unlock()
+
+ key := t.String()
+ if _, exists := callers[key]; exists {
+ log.Warnf(context.Background(), "Caller for %v already
registered. Overwriting.", key)
+ }
+ callers[key] = maker
+}
+
+// MakeCaller returns a caller for given function.
+func MakeCaller(fn interface{}) Caller {
+ callersMu.Lock()
+ maker, exists := callers[reflect.TypeOf(fn).String()]
+ callersMu.Unlock()
+
+ if exists {
+ return maker(fn)
+ }
+
+ // If no specialized implementation is available, we use the standard
+ // reflection-based call.
+
+ return &caller{fn: reflect.ValueOf(fn)}
+}
+
+type caller struct {
+ fn reflect.Value
+}
+
+func (c *caller) Type() reflect.Type {
+ return c.fn.Type()
+}
+
+func (c *caller) Call(args []interface{}) []interface{} {
+ return Interface(c.fn.Call(ValueOf(args)))
+}
+
+// ValueOf performs a per-element reflect.ValueOf.
+func ValueOf(list []interface{}) []reflect.Value {
+ ret := make([]reflect.Value, len(list), len(list))
+ for i := 0; i < len(list); i++ {
+ ret[i] = reflect.ValueOf(list[i])
+ }
+ return ret
+}
+
+// Interface performs a per-element Interface call.
+func Interface(list []reflect.Value) []interface{} {
+ ret := make([]interface{}, len(list), len(list))
+ for i := 0; i < len(list); i++ {
+ ret[i] = list[i].Interface()
+ }
+ return ret
+}
diff --git a/sdks/go/pkg/beam/core/util/reflectx/calls.go
b/sdks/go/pkg/beam/core/util/reflectx/calls.go
new file mode 100644
index 00000000000..2799b8a8260
--- /dev/null
+++ b/sdks/go/pkg/beam/core/util/reflectx/calls.go
@@ -0,0 +1,1213 @@
+// File generated by specialize. Do not edit.
+
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package reflectx
+
+import "reflect"
+
+// Generated arity-specialized Caller implementations to avoid runtime
temporary
+// slices. Code that knows the arity can potentially avoid that overhead in
+// addition to avoiding the reflection call overhead.
+//
+// We force CallerZxY to implement Caller as well to have a single registry.
Concrete
+// caller implementations should implement the most specific supported
variant. This
+// also allows more specific intermediate interfaces, such as Caller2bool, to
be added
+// later.
+
+type Caller0x0 interface {
+ Caller
+ Call0x0()
+}
+
+type shimCaller0x0 struct {
+ inner Caller
+}
+
+func (c *shimCaller0x0) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller0x0) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller0x0) Call0x0() {
+ ret := c.inner.Call([]interface{}{})
+ _ = ret
+ return
+}
+
+func ToCaller0x0(c Caller) Caller0x0 {
+ if c.Type().NumIn() != 0 || c.Type().NumOut() != 0 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller0x0); ok {
+ return sc
+ }
+ return &shimCaller0x0{inner: c}
+}
+
+func MakeCaller0x0(fn interface{}) Caller0x0 {
+ return ToCaller0x0(MakeCaller(fn))
+}
+
+type Caller0x1 interface {
+ Caller
+ Call0x1() interface{}
+}
+
+type shimCaller0x1 struct {
+ inner Caller
+}
+
+func (c *shimCaller0x1) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller0x1) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller0x1) Call0x1() interface{} {
+ ret := c.inner.Call([]interface{}{})
+ _ = ret
+ return ret[0]
+}
+
+func ToCaller0x1(c Caller) Caller0x1 {
+ if c.Type().NumIn() != 0 || c.Type().NumOut() != 1 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller0x1); ok {
+ return sc
+ }
+ return &shimCaller0x1{inner: c}
+}
+
+func MakeCaller0x1(fn interface{}) Caller0x1 {
+ return ToCaller0x1(MakeCaller(fn))
+}
+
+type Caller0x2 interface {
+ Caller
+ Call0x2() (interface{}, interface{})
+}
+
+type shimCaller0x2 struct {
+ inner Caller
+}
+
+func (c *shimCaller0x2) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller0x2) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller0x2) Call0x2() (interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{})
+ _ = ret
+ return ret[0], ret[1]
+}
+
+func ToCaller0x2(c Caller) Caller0x2 {
+ if c.Type().NumIn() != 0 || c.Type().NumOut() != 2 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller0x2); ok {
+ return sc
+ }
+ return &shimCaller0x2{inner: c}
+}
+
+func MakeCaller0x2(fn interface{}) Caller0x2 {
+ return ToCaller0x2(MakeCaller(fn))
+}
+
+type Caller0x3 interface {
+ Caller
+ Call0x3() (interface{}, interface{}, interface{})
+}
+
+type shimCaller0x3 struct {
+ inner Caller
+}
+
+func (c *shimCaller0x3) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller0x3) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller0x3) Call0x3() (interface{}, interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{})
+ _ = ret
+ return ret[0], ret[1], ret[2]
+}
+
+func ToCaller0x3(c Caller) Caller0x3 {
+ if c.Type().NumIn() != 0 || c.Type().NumOut() != 3 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller0x3); ok {
+ return sc
+ }
+ return &shimCaller0x3{inner: c}
+}
+
+func MakeCaller0x3(fn interface{}) Caller0x3 {
+ return ToCaller0x3(MakeCaller(fn))
+}
+
+type Caller1x0 interface {
+ Caller
+ Call1x0(interface{})
+}
+
+type shimCaller1x0 struct {
+ inner Caller
+}
+
+func (c *shimCaller1x0) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller1x0) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller1x0) Call1x0(arg0 interface{}) {
+ ret := c.inner.Call([]interface{}{arg0})
+ _ = ret
+ return
+}
+
+func ToCaller1x0(c Caller) Caller1x0 {
+ if c.Type().NumIn() != 1 || c.Type().NumOut() != 0 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller1x0); ok {
+ return sc
+ }
+ return &shimCaller1x0{inner: c}
+}
+
+func MakeCaller1x0(fn interface{}) Caller1x0 {
+ return ToCaller1x0(MakeCaller(fn))
+}
+
+type Caller1x1 interface {
+ Caller
+ Call1x1(interface{}) interface{}
+}
+
+type shimCaller1x1 struct {
+ inner Caller
+}
+
+func (c *shimCaller1x1) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller1x1) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller1x1) Call1x1(arg0 interface{}) interface{} {
+ ret := c.inner.Call([]interface{}{arg0})
+ _ = ret
+ return ret[0]
+}
+
+func ToCaller1x1(c Caller) Caller1x1 {
+ if c.Type().NumIn() != 1 || c.Type().NumOut() != 1 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller1x1); ok {
+ return sc
+ }
+ return &shimCaller1x1{inner: c}
+}
+
+func MakeCaller1x1(fn interface{}) Caller1x1 {
+ return ToCaller1x1(MakeCaller(fn))
+}
+
+type Caller1x2 interface {
+ Caller
+ Call1x2(interface{}) (interface{}, interface{})
+}
+
+type shimCaller1x2 struct {
+ inner Caller
+}
+
+func (c *shimCaller1x2) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller1x2) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller1x2) Call1x2(arg0 interface{}) (interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0})
+ _ = ret
+ return ret[0], ret[1]
+}
+
+func ToCaller1x2(c Caller) Caller1x2 {
+ if c.Type().NumIn() != 1 || c.Type().NumOut() != 2 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller1x2); ok {
+ return sc
+ }
+ return &shimCaller1x2{inner: c}
+}
+
+func MakeCaller1x2(fn interface{}) Caller1x2 {
+ return ToCaller1x2(MakeCaller(fn))
+}
+
+type Caller1x3 interface {
+ Caller
+ Call1x3(interface{}) (interface{}, interface{}, interface{})
+}
+
+type shimCaller1x3 struct {
+ inner Caller
+}
+
+func (c *shimCaller1x3) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller1x3) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller1x3) Call1x3(arg0 interface{}) (interface{}, interface{},
interface{}) {
+ ret := c.inner.Call([]interface{}{arg0})
+ _ = ret
+ return ret[0], ret[1], ret[2]
+}
+
+func ToCaller1x3(c Caller) Caller1x3 {
+ if c.Type().NumIn() != 1 || c.Type().NumOut() != 3 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller1x3); ok {
+ return sc
+ }
+ return &shimCaller1x3{inner: c}
+}
+
+func MakeCaller1x3(fn interface{}) Caller1x3 {
+ return ToCaller1x3(MakeCaller(fn))
+}
+
+type Caller2x0 interface {
+ Caller
+ Call2x0(interface{}, interface{})
+}
+
+type shimCaller2x0 struct {
+ inner Caller
+}
+
+func (c *shimCaller2x0) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller2x0) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller2x0) Call2x0(arg0, arg1 interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1})
+ _ = ret
+ return
+}
+
+func ToCaller2x0(c Caller) Caller2x0 {
+ if c.Type().NumIn() != 2 || c.Type().NumOut() != 0 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller2x0); ok {
+ return sc
+ }
+ return &shimCaller2x0{inner: c}
+}
+
+func MakeCaller2x0(fn interface{}) Caller2x0 {
+ return ToCaller2x0(MakeCaller(fn))
+}
+
+type Caller2x1 interface {
+ Caller
+ Call2x1(interface{}, interface{}) interface{}
+}
+
+type shimCaller2x1 struct {
+ inner Caller
+}
+
+func (c *shimCaller2x1) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller2x1) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller2x1) Call2x1(arg0, arg1 interface{}) interface{} {
+ ret := c.inner.Call([]interface{}{arg0, arg1})
+ _ = ret
+ return ret[0]
+}
+
+func ToCaller2x1(c Caller) Caller2x1 {
+ if c.Type().NumIn() != 2 || c.Type().NumOut() != 1 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller2x1); ok {
+ return sc
+ }
+ return &shimCaller2x1{inner: c}
+}
+
+func MakeCaller2x1(fn interface{}) Caller2x1 {
+ return ToCaller2x1(MakeCaller(fn))
+}
+
+type Caller2x2 interface {
+ Caller
+ Call2x2(interface{}, interface{}) (interface{}, interface{})
+}
+
+type shimCaller2x2 struct {
+ inner Caller
+}
+
+func (c *shimCaller2x2) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller2x2) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller2x2) Call2x2(arg0, arg1 interface{}) (interface{},
interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1})
+ _ = ret
+ return ret[0], ret[1]
+}
+
+func ToCaller2x2(c Caller) Caller2x2 {
+ if c.Type().NumIn() != 2 || c.Type().NumOut() != 2 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller2x2); ok {
+ return sc
+ }
+ return &shimCaller2x2{inner: c}
+}
+
+func MakeCaller2x2(fn interface{}) Caller2x2 {
+ return ToCaller2x2(MakeCaller(fn))
+}
+
+type Caller2x3 interface {
+ Caller
+ Call2x3(interface{}, interface{}) (interface{}, interface{},
interface{})
+}
+
+type shimCaller2x3 struct {
+ inner Caller
+}
+
+func (c *shimCaller2x3) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller2x3) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller2x3) Call2x3(arg0, arg1 interface{}) (interface{},
interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1})
+ _ = ret
+ return ret[0], ret[1], ret[2]
+}
+
+func ToCaller2x3(c Caller) Caller2x3 {
+ if c.Type().NumIn() != 2 || c.Type().NumOut() != 3 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller2x3); ok {
+ return sc
+ }
+ return &shimCaller2x3{inner: c}
+}
+
+func MakeCaller2x3(fn interface{}) Caller2x3 {
+ return ToCaller2x3(MakeCaller(fn))
+}
+
+type Caller3x0 interface {
+ Caller
+ Call3x0(interface{}, interface{}, interface{})
+}
+
+type shimCaller3x0 struct {
+ inner Caller
+}
+
+func (c *shimCaller3x0) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller3x0) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller3x0) Call3x0(arg0, arg1, arg2 interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2})
+ _ = ret
+ return
+}
+
+func ToCaller3x0(c Caller) Caller3x0 {
+ if c.Type().NumIn() != 3 || c.Type().NumOut() != 0 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller3x0); ok {
+ return sc
+ }
+ return &shimCaller3x0{inner: c}
+}
+
+func MakeCaller3x0(fn interface{}) Caller3x0 {
+ return ToCaller3x0(MakeCaller(fn))
+}
+
+type Caller3x1 interface {
+ Caller
+ Call3x1(interface{}, interface{}, interface{}) interface{}
+}
+
+type shimCaller3x1 struct {
+ inner Caller
+}
+
+func (c *shimCaller3x1) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller3x1) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller3x1) Call3x1(arg0, arg1, arg2 interface{}) interface{} {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2})
+ _ = ret
+ return ret[0]
+}
+
+func ToCaller3x1(c Caller) Caller3x1 {
+ if c.Type().NumIn() != 3 || c.Type().NumOut() != 1 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller3x1); ok {
+ return sc
+ }
+ return &shimCaller3x1{inner: c}
+}
+
+func MakeCaller3x1(fn interface{}) Caller3x1 {
+ return ToCaller3x1(MakeCaller(fn))
+}
+
+type Caller3x2 interface {
+ Caller
+ Call3x2(interface{}, interface{}, interface{}) (interface{},
interface{})
+}
+
+type shimCaller3x2 struct {
+ inner Caller
+}
+
+func (c *shimCaller3x2) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller3x2) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller3x2) Call3x2(arg0, arg1, arg2 interface{}) (interface{},
interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2})
+ _ = ret
+ return ret[0], ret[1]
+}
+
+func ToCaller3x2(c Caller) Caller3x2 {
+ if c.Type().NumIn() != 3 || c.Type().NumOut() != 2 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller3x2); ok {
+ return sc
+ }
+ return &shimCaller3x2{inner: c}
+}
+
+func MakeCaller3x2(fn interface{}) Caller3x2 {
+ return ToCaller3x2(MakeCaller(fn))
+}
+
+type Caller3x3 interface {
+ Caller
+ Call3x3(interface{}, interface{}, interface{}) (interface{},
interface{}, interface{})
+}
+
+type shimCaller3x3 struct {
+ inner Caller
+}
+
+func (c *shimCaller3x3) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller3x3) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller3x3) Call3x3(arg0, arg1, arg2 interface{}) (interface{},
interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2})
+ _ = ret
+ return ret[0], ret[1], ret[2]
+}
+
+func ToCaller3x3(c Caller) Caller3x3 {
+ if c.Type().NumIn() != 3 || c.Type().NumOut() != 3 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller3x3); ok {
+ return sc
+ }
+ return &shimCaller3x3{inner: c}
+}
+
+func MakeCaller3x3(fn interface{}) Caller3x3 {
+ return ToCaller3x3(MakeCaller(fn))
+}
+
+type Caller4x0 interface {
+ Caller
+ Call4x0(interface{}, interface{}, interface{}, interface{})
+}
+
+type shimCaller4x0 struct {
+ inner Caller
+}
+
+func (c *shimCaller4x0) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller4x0) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller4x0) Call4x0(arg0, arg1, arg2, arg3 interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3})
+ _ = ret
+ return
+}
+
+func ToCaller4x0(c Caller) Caller4x0 {
+ if c.Type().NumIn() != 4 || c.Type().NumOut() != 0 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller4x0); ok {
+ return sc
+ }
+ return &shimCaller4x0{inner: c}
+}
+
+func MakeCaller4x0(fn interface{}) Caller4x0 {
+ return ToCaller4x0(MakeCaller(fn))
+}
+
+type Caller4x1 interface {
+ Caller
+ Call4x1(interface{}, interface{}, interface{}, interface{}) interface{}
+}
+
+type shimCaller4x1 struct {
+ inner Caller
+}
+
+func (c *shimCaller4x1) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller4x1) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller4x1) Call4x1(arg0, arg1, arg2, arg3 interface{})
interface{} {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3})
+ _ = ret
+ return ret[0]
+}
+
+func ToCaller4x1(c Caller) Caller4x1 {
+ if c.Type().NumIn() != 4 || c.Type().NumOut() != 1 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller4x1); ok {
+ return sc
+ }
+ return &shimCaller4x1{inner: c}
+}
+
+func MakeCaller4x1(fn interface{}) Caller4x1 {
+ return ToCaller4x1(MakeCaller(fn))
+}
+
+type Caller4x2 interface {
+ Caller
+ Call4x2(interface{}, interface{}, interface{}, interface{})
(interface{}, interface{})
+}
+
+type shimCaller4x2 struct {
+ inner Caller
+}
+
+func (c *shimCaller4x2) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller4x2) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller4x2) Call4x2(arg0, arg1, arg2, arg3 interface{})
(interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3})
+ _ = ret
+ return ret[0], ret[1]
+}
+
+func ToCaller4x2(c Caller) Caller4x2 {
+ if c.Type().NumIn() != 4 || c.Type().NumOut() != 2 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller4x2); ok {
+ return sc
+ }
+ return &shimCaller4x2{inner: c}
+}
+
+func MakeCaller4x2(fn interface{}) Caller4x2 {
+ return ToCaller4x2(MakeCaller(fn))
+}
+
+type Caller4x3 interface {
+ Caller
+ Call4x3(interface{}, interface{}, interface{}, interface{})
(interface{}, interface{}, interface{})
+}
+
+type shimCaller4x3 struct {
+ inner Caller
+}
+
+func (c *shimCaller4x3) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller4x3) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller4x3) Call4x3(arg0, arg1, arg2, arg3 interface{})
(interface{}, interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3})
+ _ = ret
+ return ret[0], ret[1], ret[2]
+}
+
+func ToCaller4x3(c Caller) Caller4x3 {
+ if c.Type().NumIn() != 4 || c.Type().NumOut() != 3 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller4x3); ok {
+ return sc
+ }
+ return &shimCaller4x3{inner: c}
+}
+
+func MakeCaller4x3(fn interface{}) Caller4x3 {
+ return ToCaller4x3(MakeCaller(fn))
+}
+
+type Caller5x0 interface {
+ Caller
+ Call5x0(interface{}, interface{}, interface{}, interface{}, interface{})
+}
+
+type shimCaller5x0 struct {
+ inner Caller
+}
+
+func (c *shimCaller5x0) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller5x0) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller5x0) Call5x0(arg0, arg1, arg2, arg3, arg4 interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4})
+ _ = ret
+ return
+}
+
+func ToCaller5x0(c Caller) Caller5x0 {
+ if c.Type().NumIn() != 5 || c.Type().NumOut() != 0 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller5x0); ok {
+ return sc
+ }
+ return &shimCaller5x0{inner: c}
+}
+
+func MakeCaller5x0(fn interface{}) Caller5x0 {
+ return ToCaller5x0(MakeCaller(fn))
+}
+
+type Caller5x1 interface {
+ Caller
+ Call5x1(interface{}, interface{}, interface{}, interface{},
interface{}) interface{}
+}
+
+type shimCaller5x1 struct {
+ inner Caller
+}
+
+func (c *shimCaller5x1) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller5x1) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller5x1) Call5x1(arg0, arg1, arg2, arg3, arg4 interface{})
interface{} {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4})
+ _ = ret
+ return ret[0]
+}
+
+func ToCaller5x1(c Caller) Caller5x1 {
+ if c.Type().NumIn() != 5 || c.Type().NumOut() != 1 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller5x1); ok {
+ return sc
+ }
+ return &shimCaller5x1{inner: c}
+}
+
+func MakeCaller5x1(fn interface{}) Caller5x1 {
+ return ToCaller5x1(MakeCaller(fn))
+}
+
+type Caller5x2 interface {
+ Caller
+ Call5x2(interface{}, interface{}, interface{}, interface{},
interface{}) (interface{}, interface{})
+}
+
+type shimCaller5x2 struct {
+ inner Caller
+}
+
+func (c *shimCaller5x2) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller5x2) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller5x2) Call5x2(arg0, arg1, arg2, arg3, arg4 interface{})
(interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4})
+ _ = ret
+ return ret[0], ret[1]
+}
+
+func ToCaller5x2(c Caller) Caller5x2 {
+ if c.Type().NumIn() != 5 || c.Type().NumOut() != 2 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller5x2); ok {
+ return sc
+ }
+ return &shimCaller5x2{inner: c}
+}
+
+func MakeCaller5x2(fn interface{}) Caller5x2 {
+ return ToCaller5x2(MakeCaller(fn))
+}
+
+type Caller5x3 interface {
+ Caller
+ Call5x3(interface{}, interface{}, interface{}, interface{},
interface{}) (interface{}, interface{}, interface{})
+}
+
+type shimCaller5x3 struct {
+ inner Caller
+}
+
+func (c *shimCaller5x3) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller5x3) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller5x3) Call5x3(arg0, arg1, arg2, arg3, arg4 interface{})
(interface{}, interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4})
+ _ = ret
+ return ret[0], ret[1], ret[2]
+}
+
+func ToCaller5x3(c Caller) Caller5x3 {
+ if c.Type().NumIn() != 5 || c.Type().NumOut() != 3 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller5x3); ok {
+ return sc
+ }
+ return &shimCaller5x3{inner: c}
+}
+
+func MakeCaller5x3(fn interface{}) Caller5x3 {
+ return ToCaller5x3(MakeCaller(fn))
+}
+
+type Caller6x0 interface {
+ Caller
+ Call6x0(interface{}, interface{}, interface{}, interface{},
interface{}, interface{})
+}
+
+type shimCaller6x0 struct {
+ inner Caller
+}
+
+func (c *shimCaller6x0) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller6x0) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller6x0) Call6x0(arg0, arg1, arg2, arg3, arg4, arg5
interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4, arg5})
+ _ = ret
+ return
+}
+
+func ToCaller6x0(c Caller) Caller6x0 {
+ if c.Type().NumIn() != 6 || c.Type().NumOut() != 0 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller6x0); ok {
+ return sc
+ }
+ return &shimCaller6x0{inner: c}
+}
+
+func MakeCaller6x0(fn interface{}) Caller6x0 {
+ return ToCaller6x0(MakeCaller(fn))
+}
+
+type Caller6x1 interface {
+ Caller
+ Call6x1(interface{}, interface{}, interface{}, interface{},
interface{}, interface{}) interface{}
+}
+
+type shimCaller6x1 struct {
+ inner Caller
+}
+
+func (c *shimCaller6x1) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller6x1) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller6x1) Call6x1(arg0, arg1, arg2, arg3, arg4, arg5
interface{}) interface{} {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4, arg5})
+ _ = ret
+ return ret[0]
+}
+
+func ToCaller6x1(c Caller) Caller6x1 {
+ if c.Type().NumIn() != 6 || c.Type().NumOut() != 1 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller6x1); ok {
+ return sc
+ }
+ return &shimCaller6x1{inner: c}
+}
+
+func MakeCaller6x1(fn interface{}) Caller6x1 {
+ return ToCaller6x1(MakeCaller(fn))
+}
+
+type Caller6x2 interface {
+ Caller
+ Call6x2(interface{}, interface{}, interface{}, interface{},
interface{}, interface{}) (interface{}, interface{})
+}
+
+type shimCaller6x2 struct {
+ inner Caller
+}
+
+func (c *shimCaller6x2) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller6x2) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller6x2) Call6x2(arg0, arg1, arg2, arg3, arg4, arg5
interface{}) (interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4, arg5})
+ _ = ret
+ return ret[0], ret[1]
+}
+
+func ToCaller6x2(c Caller) Caller6x2 {
+ if c.Type().NumIn() != 6 || c.Type().NumOut() != 2 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller6x2); ok {
+ return sc
+ }
+ return &shimCaller6x2{inner: c}
+}
+
+func MakeCaller6x2(fn interface{}) Caller6x2 {
+ return ToCaller6x2(MakeCaller(fn))
+}
+
+type Caller6x3 interface {
+ Caller
+ Call6x3(interface{}, interface{}, interface{}, interface{},
interface{}, interface{}) (interface{}, interface{}, interface{})
+}
+
+type shimCaller6x3 struct {
+ inner Caller
+}
+
+func (c *shimCaller6x3) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller6x3) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller6x3) Call6x3(arg0, arg1, arg2, arg3, arg4, arg5
interface{}) (interface{}, interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4, arg5})
+ _ = ret
+ return ret[0], ret[1], ret[2]
+}
+
+func ToCaller6x3(c Caller) Caller6x3 {
+ if c.Type().NumIn() != 6 || c.Type().NumOut() != 3 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller6x3); ok {
+ return sc
+ }
+ return &shimCaller6x3{inner: c}
+}
+
+func MakeCaller6x3(fn interface{}) Caller6x3 {
+ return ToCaller6x3(MakeCaller(fn))
+}
+
+type Caller7x0 interface {
+ Caller
+ Call7x0(interface{}, interface{}, interface{}, interface{},
interface{}, interface{}, interface{})
+}
+
+type shimCaller7x0 struct {
+ inner Caller
+}
+
+func (c *shimCaller7x0) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller7x0) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller7x0) Call7x0(arg0, arg1, arg2, arg3, arg4, arg5, arg6
interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4, arg5,
arg6})
+ _ = ret
+ return
+}
+
+func ToCaller7x0(c Caller) Caller7x0 {
+ if c.Type().NumIn() != 7 || c.Type().NumOut() != 0 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller7x0); ok {
+ return sc
+ }
+ return &shimCaller7x0{inner: c}
+}
+
+func MakeCaller7x0(fn interface{}) Caller7x0 {
+ return ToCaller7x0(MakeCaller(fn))
+}
+
+type Caller7x1 interface {
+ Caller
+ Call7x1(interface{}, interface{}, interface{}, interface{},
interface{}, interface{}, interface{}) interface{}
+}
+
+type shimCaller7x1 struct {
+ inner Caller
+}
+
+func (c *shimCaller7x1) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller7x1) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller7x1) Call7x1(arg0, arg1, arg2, arg3, arg4, arg5, arg6
interface{}) interface{} {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4, arg5,
arg6})
+ _ = ret
+ return ret[0]
+}
+
+func ToCaller7x1(c Caller) Caller7x1 {
+ if c.Type().NumIn() != 7 || c.Type().NumOut() != 1 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller7x1); ok {
+ return sc
+ }
+ return &shimCaller7x1{inner: c}
+}
+
+func MakeCaller7x1(fn interface{}) Caller7x1 {
+ return ToCaller7x1(MakeCaller(fn))
+}
+
+type Caller7x2 interface {
+ Caller
+ Call7x2(interface{}, interface{}, interface{}, interface{},
interface{}, interface{}, interface{}) (interface{}, interface{})
+}
+
+type shimCaller7x2 struct {
+ inner Caller
+}
+
+func (c *shimCaller7x2) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller7x2) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller7x2) Call7x2(arg0, arg1, arg2, arg3, arg4, arg5, arg6
interface{}) (interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4, arg5,
arg6})
+ _ = ret
+ return ret[0], ret[1]
+}
+
+func ToCaller7x2(c Caller) Caller7x2 {
+ if c.Type().NumIn() != 7 || c.Type().NumOut() != 2 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller7x2); ok {
+ return sc
+ }
+ return &shimCaller7x2{inner: c}
+}
+
+func MakeCaller7x2(fn interface{}) Caller7x2 {
+ return ToCaller7x2(MakeCaller(fn))
+}
+
+type Caller7x3 interface {
+ Caller
+ Call7x3(interface{}, interface{}, interface{}, interface{},
interface{}, interface{}, interface{}) (interface{}, interface{}, interface{})
+}
+
+type shimCaller7x3 struct {
+ inner Caller
+}
+
+func (c *shimCaller7x3) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller7x3) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller7x3) Call7x3(arg0, arg1, arg2, arg3, arg4, arg5, arg6
interface{}) (interface{}, interface{}, interface{}) {
+ ret := c.inner.Call([]interface{}{arg0, arg1, arg2, arg3, arg4, arg5,
arg6})
+ _ = ret
+ return ret[0], ret[1], ret[2]
+}
+
+func ToCaller7x3(c Caller) Caller7x3 {
+ if c.Type().NumIn() != 7 || c.Type().NumOut() != 3 {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller7x3); ok {
+ return sc
+ }
+ return &shimCaller7x3{inner: c}
+}
+
+func MakeCaller7x3(fn interface{}) Caller7x3 {
+ return ToCaller7x3(MakeCaller(fn))
+}
diff --git a/sdks/go/pkg/beam/core/util/reflectx/calls.tmpl
b/sdks/go/pkg/beam/core/util/reflectx/calls.tmpl
new file mode 100644
index 00000000000..0d68b5c3d6b
--- /dev/null
+++ b/sdks/go/pkg/beam/core/util/reflectx/calls.tmpl
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package reflectx
+
+import "reflect"
+
+// Generated arity-specialized Caller implementations to avoid runtime
temporary
+// slices. Code that knows the arity can potentially avoid that overhead in
+// addition to avoiding the reflection call overhead.
+//
+// We force CallerZxY to implement Caller as well to have a single registry.
Concrete
+// caller implementations should implement the most specific supported
variant. This
+// also allows more specific intermediate interfaces, such as Caller2bool, to
be added
+// later.
+
+{{range $in := upto 8}}
+{{range $out := upto 4}}
+type Caller{{$in}}x{{$out}} interface {
+ Caller
+ Call{{$in}}x{{$out}}({{mktuple $in "interface{}"}}) ({{mktuple $out
"interface{}"}})
+}
+
+type shimCaller{{$in}}x{{$out}} struct {
+ inner Caller
+}
+
+func (c *shimCaller{{$in}}x{{$out}}) Type() reflect.Type {
+ return c.inner.Type()
+}
+
+func (c *shimCaller{{$in}}x{{$out}}) Call(args []interface{}) []interface{} {
+ return c.inner.Call(args)
+}
+
+func (c *shimCaller{{$in}}x{{$out}}) Call{{$in}}x{{$out}}({{mkargs $in "arg%v"
"interface{}"}}) ({{mktuple $out "interface{}"}}) {
+ ret := c.inner.Call([]interface{}{ {{mktuplef $in "arg%v"}} })
+ _ = ret
+ return {{mktuplef $out "ret[%v]"}}
+}
+
+func ToCaller{{$in}}x{{$out}}(c Caller) Caller{{$in}}x{{$out}} {
+ if c.Type().NumIn() != {{$in}} || c.Type().NumOut() != {{$out}} {
+ panic("incompatible caller type")
+ }
+ if sc, ok := c.(Caller{{$in}}x{{$out}}); ok {
+ return sc
+ }
+ return &shimCaller{{$in}}x{{$out}}{inner: c}
+}
+
+func MakeCaller{{$in}}x{{$out}}(fn interface{}) Caller{{$in}}x{{$out}} {
+ return ToCaller{{$in}}x{{$out}}(MakeCaller(fn))
+}
+{{end}}
+{{end}}
diff --git a/sdks/go/pkg/beam/transforms/filter/filter.go
b/sdks/go/pkg/beam/transforms/filter/filter.go
index 3a6f5881b35..eb3de1e5b11 100644
--- a/sdks/go/pkg/beam/transforms/filter/filter.go
+++ b/sdks/go/pkg/beam/transforms/filter/filter.go
@@ -23,6 +23,7 @@ import (
"github.com/apache/beam/sdks/go/pkg/beam"
"github.com/apache/beam/sdks/go/pkg/beam/core/funcx"
"github.com/apache/beam/sdks/go/pkg/beam/core/typex"
+ "github.com/apache/beam/sdks/go/pkg/beam/core/util/reflectx"
)
var (
@@ -78,11 +79,17 @@ type filterFn struct {
Predicate beam.EncodedFn `json:"predicate"`
// Include indicates whether to include or exclude elements that
satisfy the predicate.
Include bool `json:"include"`
+
+ fn reflectx.Caller1x1
+}
+
+func (f *filterFn) Setup() {
+ f.fn = reflectx.MakeCaller1x1(f.Predicate.Fn.Interface())
}
func (f *filterFn) ProcessElement(elm beam.T, emit func(beam.T)) {
- ret := f.Predicate.Fn.Call([]reflect.Value{reflect.ValueOf(elm)})
- if ret[0].Bool() == f.Include {
+ match := f.fn.Call1x1(elm).(bool)
+ if match == f.Include {
emit(elm)
}
}
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> Reduce Go runtime reflective overhead
> -------------------------------------
>
> Key: BEAM-3388
> URL: https://issues.apache.org/jira/browse/BEAM-3388
> Project: Beam
> Issue Type: Improvement
> Components: sdk-go
> Reporter: Henning Rohde
> Assignee: Henning Rohde
>
> Go reflection is slow and we should avoid it in the Go SDK at runtime, when
> possible -- especially on the fast paths. It seems unlikely that the language
> runtime/libraries will improve any time soon:
> https://github.com/golang/go/issues/7818.
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)