FAQ
So "Effective Go" informs me that if I first use, say

file, err := someFileFoo()

and later in the same scope

foo, err := Bar()

then while err "looks" redeclared, only 1 variable "slot" is being used for
err.

Now I'm wondering about the following situation:

for i := 0; i < 10; i++ {
if p := someFunc(); somePredicate(p) {
....
}
}

Do we have 10 variables / memory slots being allocated / created for p, or
is that the same case as above -- just one for p?

--

Search Discussions

  • Tim Harig at Nov 24, 2012 at 3:59 pm

    On Sat, Nov 24, 2012 at 07:34:38AM -0800, Philipp Schumann wrote:
    for i := 0; i < 10; i++ {
    if p := someFunc(); somePredicate(p) {
    ....
    }
    }

    Do we have 10 variables / memory slots being allocated / created for p, or
    is that the same case as above -- just one for p?
    You only have one variable. Whether memory is being allocated or reused,
    depends on what sumFunc() returns.

    --
  • Steven Blenkinsop at Nov 24, 2012 at 5:18 pm

    On Saturday, November 24, 2012, Philipp Schumann wrote:

    So "Effective Go" informs me that if I first use, say

    file, err := someFileFoo()

    and later in the same scope

    foo, err := Bar()

    then while err "looks" redeclared, only 1 variable "slot" is being used
    for err.

    Now I'm wondering about the following situation:

    for i := 0; i < 10; i++ {
    if p := someFunc(); somePredicate(p) {
    ....
    }
    }

    Do we have 10 variables / memory slots being allocated / created for p, or
    is that the same case as above -- just one for p?

    --

    You have 10 variables for p, which may be optimized down to one if p
    doesn't escape the if statement. However, there is only one i.

    As a demonstration, here I store the addresses of p and i on each
    iteration. There's a different address for p each time, but only ever one
    address for i.

    http://play.golang.org/p/_wkqWKt2Mn

    --
  • Philipp Schumann at Nov 24, 2012 at 5:48 pm
    Exactly what I was wondering and a great way to figure out the answer (now
    just why didn't I come up with this myself... tsk, tsk..) Cheers!




    On Sunday, November 25, 2012 1:18:30 AM UTC+8, Steven Blenkinsop wrote:


    On Saturday, November 24, 2012, Philipp Schumann wrote:

    So "Effective Go" informs me that if I first use, say


    file, err := someFileFoo()


    and later in the same scope


    foo, err := Bar()


    then while err "looks" redeclared, only 1 variable "slot" is being used for
    err.


    Now I'm wondering about the following situation:


    for i := 0; i < 10; i++ {
    if p := someFunc(); somePredicate(p) {
    ....
    }
    }


    Do we have 10 variables / memory slots being allocated / created for p, or
    is that the same case as above -- just one for p?

    --

    You have 10 variables for p, which may be optimized down to one if p
    doesn't escape the if statement. However, there is only one i.


    As a demonstration, here I store the addresses of p and i on each
    iteration. There's a different address for p each time, but only ever one
    address for i.


    http://play.golang.org/p/_wkqWKt2Mn

    --
  • Ken Allen at Nov 24, 2012 at 6:00 pm
    Keep in mind that the act of taking the address of p is what is causing it
    to be allocated multiple times. Go sees that the address is escaping the
    function (by being appended to ps) and is then causing it to be allocated
    on the heap. I imagine i is also on the heap in this case but it's only
    declared once. If p wasn't being used this way it would be allocated once
    on the stack and that's it. At least, that's my understanding of it.
    On Saturday, November 24, 2012 12:48:04 PM UTC-5, Philipp Schumann wrote:

    Exactly what I was wondering and a great way to figure out the answer (now
    just why didn't I come up with this myself... tsk, tsk..) Cheers!




    On Sunday, November 25, 2012 1:18:30 AM UTC+8, Steven Blenkinsop wrote:


    On Saturday, November 24, 2012, Philipp Schumann wrote:

    So "Effective Go" informs me that if I first use, say


    file, err := someFileFoo()


    and later in the same scope


    foo, err := Bar()


    then while err "looks" redeclared, only 1 variable "slot" is being used
    for err.


    Now I'm wondering about the following situation:


    for i := 0; i < 10; i++ {
    if p := someFunc(); somePredicate(p) {
    ....
    }
    }


    Do we have 10 variables / memory slots being allocated / created for p, or
    is that the same case as above -- just one for p?

    --

    You have 10 variables for p, which may be optimized down to one if p
    doesn't escape the if statement. However, there is only one i.


    As a demonstration, here I store the addresses of p and i on each
    iteration. There's a different address for p each time, but only ever one
    address for i.


    http://play.golang.org/p/_wkqWKt2Mn
    --
  • Philipp Schumann at Nov 24, 2012 at 6:06 pm
    Interesting! Would that also be the case for this slightly modified version?

    http://play.golang.org/p/hqLAIseX3K

    Here the pointer is taken only once per iteration to fmt.Printf it, it is
    not really "escaping" or being re-used. Still 10x different variables. Is
    that still in a quantum-esque way just because we access the address of p
    in the first place?

    I think I'll declare such variables outside loops from now on just to be
    sure they'll be properly reused.

    On Sunday, November 25, 2012 2:00:57 AM UTC+8, Ken Allen wrote:

    Keep in mind that the act of taking the address of p is what is causing it
    to be allocated multiple times. Go sees that the address is escaping the
    function (by being appended to ps) and is then causing it to be allocated
    on the heap. I imagine i is also on the heap in this case but it's only
    declared once. If p wasn't being used this way it would be allocated once
    on the stack and that's it. At least, that's my understanding of it.
    On Saturday, November 24, 2012 12:48:04 PM UTC-5, Philipp Schumann wrote:

    Exactly what I was wondering and a great way to figure out the answer
    (now just why didn't I come up with this myself... tsk, tsk..) Cheers!




    On Sunday, November 25, 2012 1:18:30 AM UTC+8, Steven Blenkinsop wrote:


    On Saturday, November 24, 2012, Philipp Schumann wrote:

    So "Effective Go" informs me that if I first use, say


    file, err := someFileFoo()


    and later in the same scope


    foo, err := Bar()


    then while err "looks" redeclared, only 1 variable "slot" is being used
    for err.


    Now I'm wondering about the following situation:


    for i := 0; i < 10; i++ {
    if p := someFunc(); somePredicate(p) {
    ....
    }
    }


    Do we have 10 variables / memory slots being allocated / created for p,
    or is that the same case as above -- just one for p?

    --

    You have 10 variables for p, which may be optimized down to one if p
    doesn't escape the if statement. However, there is only one i.


    As a demonstration, here I store the addresses of p and i on each
    iteration. There's a different address for p each time, but only ever one
    address for i.


    http://play.golang.org/p/_wkqWKt2Mn
    --
  • Minux at Nov 24, 2012 at 6:11 pm

    On Sun, Nov 25, 2012 at 2:06 AM, Philipp Schumann wrote:

    Interesting! Would that also be the case for this slightly modified
    version?

    http://play.golang.org/p/hqLAIseX3K

    Here the pointer is taken only once per iteration to fmt.Printf it, it is
    not really "escaping" or being re-used. Still 10x different variables. Is
    that still in a quantum-esque way just because we access the address of p
    in the first place?

    I think I'll declare such variables outside loops from now on just to be
    sure they'll be properly reused.
    because the escape analysis of the gc compiler is not smart enough to see
    that fmt.Printf doesn't
    keep copies of &p sent to it, so it must assume it retains a copy of &p,
    and allocate a new p on each
    iteration.

    --
  • Minux at Nov 24, 2012 at 6:18 pm

    On Sun, Nov 25, 2012 at 2:11 AM, minux wrote:
    On Sun, Nov 25, 2012 at 2:06 AM, Philipp Schumann <
    philipp.schumann@gmail.com> wrote:
    Interesting! Would that also be the case for this slightly modified
    version?

    http://play.golang.org/p/hqLAIseX3K

    Here the pointer is taken only once per iteration to fmt.Printf it, it is
    not really "escaping" or being re-used. Still 10x different variables. Is
    that still in a quantum-esque way just because we access the address of p
    in the first place?

    I think I'll declare such variables outside loops from now on just to be
    sure they'll be properly reused.
    because the escape analysis of the gc compiler is not smart enough to see
    that fmt.Printf doesn't
    keep copies of &p sent to it, so it must assume it retains a copy of &p,
    and allocate a new p on each
    iteration.
    unless you're just want to know the gc implementation, i'd suggest just
    forget about all these
    details, and just remember each time you create a variable via, say var p
    int or p := 1, p is
    created anew.

    the rest is just compiler optimization, and as a Go users, you don't need
    to know about them
    (just trust the compiler will try its best. only when you do know that the
    allocation is creating
    bottleneck after proper profiling, do you need to rethink about the
    details. frankly speaking,
    that is pretty low level optimizations, and normally you should avoid it).

    --
  • Minux at Nov 24, 2012 at 6:08 pm

    On Sun, Nov 25, 2012 at 2:00 AM, Ken Allen wrote:

    Keep in mind that the act of taking the address of p is what is causing it
    to be allocated multiple times. Go sees that the address is escaping the
    function (by being appended to ps) and is then causing it to be allocated
    on the heap. I imagine i is also on the heap in this
    theoretically speaking, the address of p doesn't escape the main func, so
    in theory, an optimizing compiler
    might indeed allocate p on stack.
    case but it's only declared once. If p wasn't being used this way it would
    be allocated once on the stack and that's it. At least, that's my
    understanding of it.
    the behavior of variable declaration is pretty easy to understand, provided
    you just don't think of any lower level
    concepts like heap/stack.

    each time this statement:
    p := f(x)
    executes, p is created anew.

    and an optimizing compiler will try hard to not allocate new p if she knows
    that you can't observe the
    difference.

    in this way, you are truly thinking about Go the language, not gc the
    implementation.

    --
  • Kamil Kisiel at Nov 24, 2012 at 6:07 pm
    You can figure out the answers to these questions yourself by inspecting
    the assembly output of the compiler:

    go build -a -gcflags -S

    The documentation for the assembly output format is here:

    http://doc.cat-v.org/plan_9/4th_edition/papers/asm
    On Saturday, November 24, 2012 7:34:39 AM UTC-8, Philipp Schumann wrote:

    So "Effective Go" informs me that if I first use, say

    file, err := someFileFoo()

    and later in the same scope

    foo, err := Bar()

    then while err "looks" redeclared, only 1 variable "slot" is being used
    for err.

    Now I'm wondering about the following situation:

    for i := 0; i < 10; i++ {
    if p := someFunc(); somePredicate(p) {
    ....
    }
    }

    Do we have 10 variables / memory slots being allocated / created for p, or
    is that the same case as above -- just one for p?
    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedNov 24, '12 at 3:34p
activeNov 24, '12 at 6:18p
posts10
users6
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase