FAQ
If I had the following function (which is useless, I know, but that's not
the point here):

func f() int {
     buf := make([]byte, 1024)
     return len(buf)
}

If the compiler discovers through escape analysis that buf does not escape,
shouldn't it be able to generate code equivalent to the following as an
optimization?

func f2() int {
     var bufArray [1024]byte
     buf := bufArray[:]
     return len(buf)
}

Of course in this case the compiler could do much more than that, but I
think my point is clear. The call to make() could be replaced with a
stack-allocated array.

Does the compiler currently do this? If not, shouldn't it? Is there
something I'm missing that would make this harder than other optimizations
currently done based on escape analysis?


--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Andrey mirtchovski at Feb 12, 2014 at 7:11 pm
    you can check for yourself:

    $ cat t.go
    package test

    func f() int {
          buf := make([]byte, 1024)
          return len(buf)
    }
    $ go build -gcflags=-m t.go
    # command-line-arguments
    ./t.go:3: can inline f
    ./t.go:4: f make([]byte, 1024) does not escape
    $

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • David Thomas at Feb 13, 2014 at 12:07 am
    That tells me that the compiler realizes that the result of make([]byte,
    1024) doesn't escape. My question was, what does it do with this
    information? Does it the byte slice's backing array to be allocated on the
    stack instead of the heap?

    After looking at the generated assembly for a few different variations of a
    function like this, I've realized that the compiler DOES make this
    optimization already. But the -m flag only tells us that the compiler will
    consider the optimization. The decision to allocate it on the stack or heap
    seems to depend on the buffer size.

    In particular, for a function like f above, a buffer size of 1024 compiled
    into something like f2 above. But when I changed 1024 to 65536, it actually
    called makeslice to put it on the heap.
    On Wednesday, February 12, 2014 2:11:13 PM UTC-5, andrey mirtchovski wrote:

    you can check for yourself:

    $ cat t.go
    package test

    func f() int {
    buf := make([]byte, 1024)
    return len(buf)
    }
    $ go build -gcflags=-m t.go
    # command-line-arguments
    ./t.go:3: can inline f
    ./t.go:4: f make([]byte, 1024) does not escape
    $
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dave Cheney at Feb 13, 2014 at 12:18 am

    On Thu, Feb 13, 2014 at 11:06 AM, David Thomas wrote:

    That tells me that the compiler realizes that the result of make([]byte,
    1024) doesn't escape. My question was, what does it do with this
    information? Does it the byte slice's backing array to be allocated on the
    stack instead of the heap?
    Yes

    After looking at the generated assembly for a few different variations of
    a function like this, I've realized that the compiler DOES make this
    optimization already. But the -m flag only tells us that the compiler will
    consider the optimization. The decision to allocate it on the stack or heap
    seems to depend on the buffer size.
    Yes. As stack frames are taken from the heap anyway, if the local
    allocation would cause a stack split, and thus an allocation on the heap
    anyway, the compiler takes the lesser of evils and allocates your large
    buffer on the heap in an effort to avoid a stack split.

    In particular, for a function like f above, a buffer size of 1024 compiled
    into something like f2 above. But when I changed 1024 to 65536, it actually
    called makeslice to put it on the heap.
    On Wednesday, February 12, 2014 2:11:13 PM UTC-5, andrey mirtchovski wrote:

    you can check for yourself:

    $ cat t.go
    package test

    func f() int {
    buf := make([]byte, 1024)
    return len(buf)
    }
    $ go build -gcflags=-m t.go
    # command-line-arguments
    ./t.go:3: can inline f
    ./t.go:4: f make([]byte, 1024) does not escape
    $
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • David Thomas at Feb 13, 2014 at 4:33 pm
    That makes a lot of sense. Thanks.

    Now I feel like I really have an answer to my underlying question--I
    shouldn't worry about declaring a local backing array by hand for
    performance, since the compiler will make the right decision for me anyway.
    On Wednesday, February 12, 2014 7:18:06 PM UTC-5, Dave Cheney wrote:




    On Thu, Feb 13, 2014 at 11:06 AM, David Thomas <davidth...@gmail.com<javascript:>
    wrote:
    That tells me that the compiler realizes that the result of make([]byte,
    1024) doesn't escape. My question was, what does it do with this
    information? Does it the byte slice's backing array to be allocated on the
    stack instead of the heap?
    Yes

    After looking at the generated assembly for a few different variations of
    a function like this, I've realized that the compiler DOES make this
    optimization already. But the -m flag only tells us that the compiler will
    consider the optimization. The decision to allocate it on the stack or heap
    seems to depend on the buffer size.
    Yes. As stack frames are taken from the heap anyway, if the local
    allocation would cause a stack split, and thus an allocation on the heap
    anyway, the compiler takes the lesser of evils and allocates your large
    buffer on the heap in an effort to avoid a stack split.

    In particular, for a function like f above, a buffer size of 1024
    compiled into something like f2 above. But when I changed 1024 to 65536, it
    actually called makeslice to put it on the heap.

    On Wednesday, February 12, 2014 2:11:13 PM UTC-5, andrey mirtchovski
    wrote:
    you can check for yourself:

    $ cat t.go
    package test

    func f() int {
    buf := make([]byte, 1024)
    return len(buf)
    }
    $ go build -gcflags=-m t.go
    # command-line-arguments
    ./t.go:3: can inline f
    ./t.go:4: f make([]byte, 1024) does not escape
    $
    --
    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 <javascript:>.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dave Cheney at Feb 13, 2014 at 9:52 pm
    I think the rules of carpentry apply just as well in this instance; measure, then cut, not the other way around.
    On 14 Feb 2014, at 3:33, David Thomas wrote:

    That makes a lot of sense. Thanks.

    Now I feel like I really have an answer to my underlying question--I shouldn't worry about declaring a local backing array by hand for performance, since the compiler will make the right decision for me anyway.
    On Wednesday, February 12, 2014 7:18:06 PM UTC-5, Dave Cheney wrote:


    On Thu, Feb 13, 2014 at 11:06 AM, David Thomas wrote:
    That tells me that the compiler realizes that the result of make([]byte, 1024) doesn't escape. My question was, what does it do with this information? Does it the byte slice's backing array to be allocated on the stack instead of the heap? Yes
    After looking at the generated assembly for a few different variations of a function like this, I've realized that the compiler DOES make this optimization already. But the -m flag only tells us that the compiler will consider the optimization. The decision to allocate it on the stack or heap seems to depend on the buffer size.
    Yes. As stack frames are taken from the heap anyway, if the local allocation would cause a stack split, and thus an allocation on the heap anyway, the compiler takes the lesser of evils and allocates your large buffer on the heap in an effort to avoid a stack split.
    In particular, for a function like f above, a buffer size of 1024 compiled into something like f2 above. But when I changed 1024 to 65536, it actually called makeslice to put it on the heap.
    On Wednesday, February 12, 2014 2:11:13 PM UTC-5, andrey mirtchovski wrote:
    you can check for yourself:

    $ cat t.go
    package test

    func f() int {
    buf := make([]byte, 1024)
    return len(buf)
    }
    $ go build -gcflags=-m t.go
    # command-line-arguments
    ./t.go:3: can inline f
    ./t.go:4: f make([]byte, 1024) does not escape
    $
    --
    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/groups/opt_out.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Kevin Gillette at Feb 14, 2014 at 6:31 am

    On Wednesday, February 12, 2014 5:18:06 PM UTC-7, Dave Cheney wrote:
    Yes. As stack frames are taken from the heap anyway, if the local
    allocation would cause a stack split, and thus an allocation on the heap
    anyway, the compiler takes the lesser of evils and allocates your large
    buffer on the heap in an effort to avoid a stack split.
    Do non-escaping heap allocations get marked free when the corresponding
    stack frame gets unrolled?

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Minux at Feb 14, 2014 at 6:53 am

    On Feb 14, 2014 1:31 AM, "Kevin Gillette" wrote:
    On Wednesday, February 12, 2014 5:18:06 PM UTC-7, Dave Cheney wrote:

    Yes. As stack frames are taken from the heap anyway, if the local
    allocation would cause a stack split, and thus an allocation on the heap
    anyway, the compiler takes the lesser of evils and allocates your large
    buffer on the heap in an effort to avoid a stack split.
    Do non-escaping heap allocations get marked free when the corresponding
    stack frame gets unrolled?
    No. Generally the runtime doesn't explicitly free memory now. (e.g. it will
    only be freed until the next GC).

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Jiří Techet at Feb 14, 2014 at 10:57 am

    On Thursday, February 13, 2014 1:18:06 AM UTC+1, Dave Cheney wrote:
    Yes. As stack frames are taken from the heap anyway, if the local
    allocation would cause a stack split, and thus an allocation on the heap
    anyway, the compiler takes the lesser of evils and allocates your large
    buffer on the heap in an effort to avoid a stack split.
    Just wondering, what are the plans regarding this once segmented stacks are
    gone in go 1.3? It would be theoretically possible to push everything on
    the stack then, on the other hand using stack for big arrays might cause
    quite dramatic stack size fluctuations and the need to reallocate the
    complete stack more often.

    Jiri

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Ian Lance Taylor at Feb 14, 2014 at 2:11 pm

    On Fri, Feb 14, 2014 at 2:57 AM, Jiří Techet wrote:
    On Thursday, February 13, 2014 1:18:06 AM UTC+1, Dave Cheney wrote:

    Yes. As stack frames are taken from the heap anyway, if the local
    allocation would cause a stack split, and thus an allocation on the heap
    anyway, the compiler takes the lesser of evils and allocates your large
    buffer on the heap in an effort to avoid a stack split.

    Just wondering, what are the plans regarding this once segmented stacks are
    gone in go 1.3? It would be theoretically possible to push everything on the
    stack then, on the other hand using stack for big arrays might cause quite
    dramatic stack size fluctuations and the need to reallocate the complete
    stack more often.
    I don't think there are any plans to change anything. I think you've
    correctly identified the tradeoffs.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedFeb 12, '14 at 7:06p
activeFeb 14, '14 at 2:11p
posts10
users7
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase