Escape analysis through interface methods?

90 views
Skip to first unread message

thebroke...@gmail.com

unread,
Feb 11, 2016, 7:19:33 PM2/11/16
to golang-nuts
Consider the following two functions:
func Foo(w *bytes.Buffer) {
arr := []byte("Hello, world")
w.Write(arr)
}
 
func Bar(w io.Writer) {
arr := []byte("Hello, world")
w.Write(arr)
}

In Foo, arr doesn't escape because the compiler can reason that bytes.Buffer.Write does not leak arr. However, in Bar, arr does escape because the compiler cannot reason what some generic implementation of io.Writer.Write will do with arr. I find this unfortunately, especially since there is a documented rule in io.Writer that "implementations must not retain p", so it should be the case that arr never escapes.

I was thinking about this, but wouldn't the compiler be able to do a global analysis of all concrete types that implement io.Writer. Suppose it was able to determine that none of the implementers of io.Writer ever leak the input argument, then it can then also reason that when the Write is called in Bar, that arr also does not escape (since none of the implementations of io.Writer that could possibly be used ever leak arr).

Going even further, suppose the compiler had the ability to track whether inputs were mutated, then I can imagine a allocation-free version of the following:
w.Write([]byte(someString))

This would work since the compiler can globally reason that none of the implementations of io.Writer ever leak the input, and also that they never mutate the input (assuming they obey the documented rule in io.Writer that "Write must not modify the slice data, even temporarily"). This would avoid the duplication of Write and WriteString methods that permeate the standard library.

Of course, I realize that there difficulties with implementing this:
  • What about recursive calls to Write? That is, if an implementation of Write calls io.Writer.Write under the hood (as is very common in wrappers like bufio.Writer), how does it determine that the implementation doesn't leak (when the analysis hasn't come to any conclusions about io.Writer yet)?
  • When components are iteratively compiled (package by package), what does the compiler output for a given package at the moment of compilation? It clearly doesn't have global knowledge of what types could end up implementing io.Writer and what their behavior would be like.
What are people's thoughts?

JT

Ian Lance Taylor

unread,
Feb 11, 2016, 8:00:44 PM2/11/16
to Joe Tsai, golang-nuts
On Thu, Feb 11, 2016 at 4:19 PM, <thebroke...@gmail.com> wrote:
>
> I was thinking about this, but wouldn't the compiler be able to do a global
> analysis of all concrete types that implement io.Writer.

The compiler can only see the package being compiled and whatever
information it can glean from the packages that it imports. In this
case Bar might be called by some other package that hasn't even been
written at the time that Bar is being compiled. There is no way for
the compiler to know whether that unwritten package implements a Write
method that lets the argument escape.

This kind of optimization can be done at link time (assuming no shared
libraries are involved). At link time you really do see all the
relevant code. But of course at that point code has already been
generated, so you are really talking about a different kind of
compiler architecture. Compilers like GCC and LLVM are in fact
capable of doing this kind of optimization. The gc compiler is not,
and there are no current plans to make it work that way.

Ian

Steven Blenkinsop

unread,
Feb 12, 2016, 12:32:43 AM2/12/16
to golang-nuts, thebroke...@gmail.com
You could do it with local analysis if you had annotations on the method signature, but that would add significant annotational burden and wouldn't be backwards compatible.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages