x/mobile/bind: byte slice parameter support without copy #12113

Closed
hyangah opened this Issue Aug 11, 2015 · 4 comments

5 participants

@hyangah
Contributor
hyangah commented Aug 11, 2015

When a Go function or method taking a byte slice is called, the current implementation
creates a copy of the arguments and passes it to the Go function. The implementation
was based on the assumption that the Go function is free to keep the slice for later use.
This prevents implementation like io.Read([]byte) where the parameter's content
is modified during call. Moreover, it costs an extra copy & memory which can be significant
depending on the byte slice size.

Instead, I propose to pass a slice backed by the foreign language's byte array if possible.

Users who want to keep the slice for later use have to be aware of the limitation and somehow
create a copy for now.

More discussion on automation or tool support to detect such use cases
(another kind of escape analysis) is welcome.

@crawshaw

@hyangah hyangah self-assigned this Aug 11, 2015
@hyangah hyangah added a commit to golang/mobile that referenced this issue Aug 11, 2015
@hyangah @hyangah hyangah + hyangah bind: update doc to include objective-C interface type support.
Also mention the current limitation in byte slice binding.
golang/go#12113.

Change-Id: Ie75780c2d203431ca26a188dfdb8f000f6805c18
Reviewed-on: https://go-review.googlesource.com/13531
Reviewed-by: David Crawshaw <crawshaw@golang.org>
73792b1
@ianlancetaylor ianlancetaylor added this to the Unreleased milestone Aug 11, 2015
@hyangah
Contributor
hyangah commented Oct 21, 2015

I plan to work on this in Nov.

@gopherbot

CL https://golang.org/cl/19821 mentions this issue.

@gopherbot gopherbot pushed a commit to golang/mobile that closed this issue Mar 3, 2016
@eliasnaur eliasnaur mobile/bind: replace seq serialization with direct calls
The seq serialization machinery is a historic artifact from when Go
mobile code had to run in a separate process. Now that Go code is running
in-process, replace the explicit serialization with direct calls and pass
arguments on the stack.

The benefits are a much smaller bind runtime, much less garbage (and, in
Java, fewer objects with finalizers), less argument copying, and faster
cross-language calls.
The cost is a more complex generator, because some of the work from the
bind runtime is moved to generated code. Generated code now handles
conversion between Go and Java/ObjC types, multiple return values and memory
management of byte slice and string arguments.

To overcome the lack of calling C code between Go packages, all bound
packages now end up in the same (fake) package, "gomobile_bind", instead of
separate packages (go_<pkgname>). To avoid name clashes, the package name is
added as a prefix to generated functions and types.

Also, don't copy byte arrays passed to Go, saving call time and
allowing read([]byte)-style interfaces to foreign callers (#12113).

Finally, add support for nil interfaces and struct pointers to objc.

This is a large CL, but most of the changes stem from changing testdata.

The full benchcmp output on the CL/20095 benchmarks on my Nexus 5 is
reproduced below. Note that the savings for the JavaSlice* benchmarks are
skewed because byte slices are no longer copied before passing them to Go.

benchmark                                 old ns/op     new ns/op     delta
BenchmarkJavaEmpty                        26.0          19.0          -26.92%
BenchmarkJavaEmptyDirect                  23.0          22.0          -4.35%
BenchmarkJavaNoargs                       7685          2339          -69.56%
BenchmarkJavaNoargsDirect                 17405         8041          -53.80%
BenchmarkJavaOnearg                       26887         2366          -91.20%
BenchmarkJavaOneargDirect                 34266         7910          -76.92%
BenchmarkJavaOneret                       38325         2245          -94.14%
BenchmarkJavaOneretDirect                 46265         7708          -83.34%
BenchmarkJavaManyargs                     41720         2535          -93.92%
BenchmarkJavaManyargsDirect               51026         8373          -83.59%
BenchmarkJavaRefjava                      38139         21260         -44.26%
BenchmarkJavaRefjavaDirect                42706         28150         -34.08%
BenchmarkJavaRefgo                        34403         6843          -80.11%
BenchmarkJavaRefgoDirect                  40193         16582         -58.74%
BenchmarkJavaStringShort                  32366         9323          -71.20%
BenchmarkJavaStringShortDirect            41973         19118         -54.45%
BenchmarkJavaStringLong                   127879        94420         -26.16%
BenchmarkJavaStringLongDirect             133776        114760        -14.21%
BenchmarkJavaStringShortUnicode           32562         9221          -71.68%
BenchmarkJavaStringShortUnicodeDirect     41464         19094         -53.95%
BenchmarkJavaStringLongUnicode            131015        89401         -31.76%
BenchmarkJavaStringLongUnicodeDirect      134130        90786         -32.31%
BenchmarkJavaSliceShort                   42462         7538          -82.25%
BenchmarkJavaSliceShortDirect             52940         17017         -67.86%
BenchmarkJavaSliceLong                    138391        8466          -93.88%
BenchmarkJavaSliceLongDirect              205804        15666         -92.39%
BenchmarkGoEmpty                          3.00          3.00          +0.00%
BenchmarkGoEmptyDirect                    3.00          3.00          +0.00%
BenchmarkGoNoarg                          40342         13716         -66.00%
BenchmarkGoNoargDirect                    46691         13569         -70.94%
BenchmarkGoOnearg                         43529         13757         -68.40%
BenchmarkGoOneargDirect                   44867         14078         -68.62%
BenchmarkGoOneret                         45456         13559         -70.17%
BenchmarkGoOneretDirect                   44694         13442         -69.92%
BenchmarkGoRefjava                        55111         28071         -49.06%
BenchmarkGoRefjavaDirect                  60883         26872         -55.86%
BenchmarkGoRefgo                          57038         29223         -48.77%
BenchmarkGoRefgoDirect                    56153         27812         -50.47%
BenchmarkGoManyargs                       67967         17398         -74.40%
BenchmarkGoManyargsDirect                 60617         16998         -71.96%
BenchmarkGoStringShort                    57538         22600         -60.72%
BenchmarkGoStringShortDirect              52627         22704         -56.86%
BenchmarkGoStringLong                     128485        52530         -59.12%
BenchmarkGoStringLongDirect               138377        52079         -62.36%
BenchmarkGoStringShortUnicode             57062         22994         -59.70%
BenchmarkGoStringShortUnicodeDirect       62563         22938         -63.34%
BenchmarkGoStringLongUnicode              139913        55553         -60.29%
BenchmarkGoStringLongUnicodeDirect        150863        57791         -61.69%
BenchmarkGoSliceShort                     59279         20215         -65.90%
BenchmarkGoSliceShortDirect               60160         21136         -64.87%
BenchmarkGoSliceLong                      411225        301870        -26.59%
BenchmarkGoSliceLongDirect                399029        298915        -25.09%

Fixes golang/go#12619
Fixes golang/go#12113
Fixes golang/go#13033

Change-Id: I2b45e9e98a1248e3c23a5137f775f7364908bec7
Reviewed-on: https://go-review.googlesource.com/19821
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
6fca37c
@nishant-kumbhare

Hello,
Please help me out.

I created a golang function with returntype array
it is not created function with array return type, with message
"skipped function with unsupported return type or parameter"
eg.

my golang function is
unc Sample() []string {

letters := []string{"a", "b", "c", "d"}
return letters

}

and after this i run the bind command it generate the framework and show header file with following result.
"skipped function Sample with unsupported parameter or return types"

@eliasnaur
Contributor

Gomobile does not (yet) support binding to function that takes or returns slices or arrays. If you need access to a Go slice or array from native code, use something like:

func LetterAt(i int) string {
    return letters[i]
}

Please use the golang-nuts discussion group for support questions in the future:

https://groups.google.com/d/forum/golang-nuts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment