FAQ
Given a type like so:

type Line struct {
   data []byte
   received time.Time
   flag bool
}

Would it be more "efficient" to send pointers to struct instances or the
struct instances themselves via a channel to another go routine? And why?
What about function calls in the same go routine?

FWIW, once passed to another go routine the sending go routine doesn't do
anything more with the struct instance. They are created in a tight loop
and "passed down a channel" for further work.

By efficient I mean it as "holistically" as possible, accounting for GC
runs and the such as well as any passing overhead.

My previous assumption was that passing a pointer would be more efficient,
but after some more reading around the internets I'm not so sure since it's
a simple, although compound, struct (slice header, time.Time (another
struct, which contains a pointer to another struct) and a bool).

--
Edward Muller
@freeformz

--
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

  • Felixzilla at Dec 1, 2013 at 11:35 pm
    the struct instances themselves via a channel to another go routine is
    better
    When sending something over channel is best to do so without pointers,
    if you wan't the channel to make changes to say your struct and then you
    use it
    later then the sync package will be better with locks and mutex,


    --
    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.
  • Edward Muller at Dec 2, 2013 at 12:13 am

    On Sun, Dec 1, 2013 at 3:35 PM, wrote:

    the struct instances themselves via a channel to another go routine is
    better
    When sending something over channel is best to do so without pointers,
    if you wan't the channel to make changes to say your struct and then you
    use it
    later then the sync package will be better with locks and mutex,
    I totally understand that, but my question has nothing to do with
    synchronization. I understand that if something later in the pipe makes
    changes to the struct that could affect the sender (or any other go
    routines that the pointer was sent to) *if* it used the structs again. As I
    stated, I know I'm not using the struct again, so that doesn't matter to me.



    --
    Edward Muller
    @freeformz

    --
    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.
  • Felix Zilla at Dec 2, 2013 at 12:38 am
    If you are not using the struct again then why keep it,
    in this case it means that the go routine you sent the struct pointer
    have to finish before you exit the sender function or else the pointer
    will be destroyed,
    ie. if go routine A send B a struct pointer A have to wait for B to
    finish execution before A exit, else A will destroy it's memory it sent
    to B.

    --
    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.
  • Jesse McNelis at Dec 2, 2013 at 1:03 am

    On Mon, Dec 2, 2013 at 11:38 AM, Felix Zilla wrote:

    If you are not using the struct again then why keep it,
    in this case it means that the go routine you sent the struct pointer
    have to finish before you exit the sender function or else the pointer
    will be destroyed,
    ie. if go routine A send B a struct pointer A have to wait for B to
    finish execution before A exit, else A will destroy it's memory it sent
    to B.
    That is incorrect.
    A pointer sent from 'A' to 'B' will point to a heap allocation that will
    exist until there are no more pointers to it and the GC can clear it up.

    Go is a memory safe language(on a single thread), you can't create dangling
    pointers like that.

    --
    =====================
    http://jessta.id.au

    --
    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.
  • Felix Zilla at Dec 2, 2013 at 1:32 am
    Maybe some code will clear out things.
    --
    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.
  • Jesse McNelis at Dec 1, 2013 at 11:39 pm

    On Mon, Dec 2, 2013 at 10:21 AM, Edward Muller wrote:

    Given a type like so:

    type Line struct {
    data []byte
    received time.Time
    flag bool
    }
    My previous assumption was that passing a pointer would be more efficient,
    but after some more reading around the internets I'm not so sure since it's
    a simple, although compound, struct (slice header, time.Time (another
    struct, which contains a pointer to another struct) and a bool).
    The best way to figure this out is to benchmark. But copying is cheap and
    allocations aren't.
    Since the pointer obviously escapes it's scope, it's pointee is going to
    have to be on the heap.
    If you don't have a pointer then you can have the value stored on the stack
    and then copied to the stack of the receiver without additional heap
    allocations.

    --
    =====================
    http://jessta.id.au

    --
    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.
  • Keith Rarick at Dec 1, 2013 at 11:40 pm
    There's no single answer to this question. It depends on
    all sorts of variables, like how many of these structs you
    need, how many you need at a time, how long they stay
    alive, not to mention how the garbage collector behaves
    (which can change over time).

    The only way to know is to measure both ways, in the
    actual application, to get realistic access patterns.

    Also, does it matter? Assume it doesn't matter until
    measurement tells you that allocation (or copying) is
    eating up too much time.
    On Sun, Dec 1, 2013 at 3:21 PM, Edward Muller wrote:
    Given a type like so:

    type Line struct {
    data []byte
    received time.Time
    flag bool
    }

    Would it be more "efficient" to send pointers to struct instances or the
    struct instances themselves via a channel to another go routine? And why?
    What about function calls in the same go routine?

    FWIW, once passed to another go routine the sending go routine doesn't do
    anything more with the struct instance. They are created in a tight loop and
    "passed down a channel" for further work.

    By efficient I mean it as "holistically" as possible, accounting for GC runs
    and the such as well as any passing overhead.

    My previous assumption was that passing a pointer would be more efficient,
    but after some more reading around the internets I'm not so sure since it's
    a simple, although compound, struct (slice header, time.Time (another
    struct, which contains a pointer to another struct) and a bool).

    --
    Edward Muller
    @freeformz

    --
    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.
  • Felix Zilla at Dec 1, 2013 at 11:56 pm
    Google IO 2012 Go Concurrency Patterns
    http://www.youtube.com/watch?v=f6kdp27TYZs
    --
    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.
  • Sokolov Yura at Dec 2, 2013 at 5:49 am
    If such structs are short living, then most efficient way is to allocate array of structs and send pointers to elements of array, so that, you cut both allocation and copying.

    --
    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.
  • Volker Dobler at Dec 2, 2013 at 8:24 am

    Am Montag, 2. Dezember 2013 00:21:16 UTC+1 schrieb freeformz:
    Would it be more "efficient" to send pointers to struct instances or the
    struct instances themselves via a channel to another go routine? And why?
    What about function calls in the same go routine?
    ...
    By efficient I mean it as "holistically" as possible, accounting for GC
    runs and the such as well as any passing overhead.
    Simple answer: Measure it. Sometimes 3 weeks in the lab can save you
    4 day in the library but this doesn't sound like such an issue.

    V.

    --
    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.
  • Edward Muller at Dec 3, 2013 at 12:22 am
    I was hoping there were some general rules wrt struct sizes and what not. I
    understand that's probably a micro-optimization.

    I'll measure the code and see which performs better.

    Thanks!



    On Mon, Dec 2, 2013 at 12:24 AM, Volker Dobler
    wrote:
    Am Montag, 2. Dezember 2013 00:21:16 UTC+1 schrieb freeformz:
    Would it be more "efficient" to send pointers to struct instances or the
    struct instances themselves via a channel to another go routine? And why?
    What about function calls in the same go routine?
    ...
    By efficient I mean it as "holistically" as possible, accounting for GC
    runs and the such as well as any passing overhead.
    Simple answer: Measure it. Sometimes 3 weeks in the lab can save you
    4 day in the library but this doesn't sound like such an issue.

    V.

    --
    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.


    --
    Edward Muller
    @freeformz

    --
    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 Dec 3, 2013 at 7:12 am
    It is important to remember that common types like time.Time and
    slices are not single words

    lucky(~/src) % cat size.go
    package main

    import "fmt"; import "unsafe"; import "time"

    func main() {
             var t time.Time
             fmt.Println("sizeof time.Time:", unsafe.Sizeof(t))
             var s []string
             fmt.Println("sizeof []string:", unsafe.Sizeof(s))
    }
    lucky(~/src) % go run size.go
    sizeof time.Time: 24
    sizeof []string: 24

    So, if your values are similar sizes, deliberately passing a pointer
    to them is probably overkill.
    On Tue, Dec 3, 2013 at 11:22 AM, Edward Muller wrote:
    I was hoping there were some general rules wrt struct sizes and what not. I
    understand that's probably a micro-optimization.

    I'll measure the code and see which performs better.

    Thanks!


    On Mon, Dec 2, 2013 at 12:24 AM, Volker Dobler wrote:

    Am Montag, 2. Dezember 2013 00:21:16 UTC+1 schrieb freeformz:
    Would it be more "efficient" to send pointers to struct instances or the
    struct instances themselves via a channel to another go routine? And why?
    What about function calls in the same go routine?
    ...
    By efficient I mean it as "holistically" as possible, accounting for GC
    runs and the such as well as any passing overhead.
    Simple answer: Measure it. Sometimes 3 weeks in the lab can save you
    4 day in the library but this doesn't sound like such an issue.

    V.

    --
    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.



    --
    Edward Muller
    @freeformz

    --
    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.
  • Edward Muller at Dec 3, 2013 at 8:49 pm
    Thanks. I did some testing and passing pointers for this common struct
    ended up being slower and causing more allocations, so I've gone back to
    just passing the struct. Bonus: I now have benchmarks to compare against
    for future code changes.

    On Mon, Dec 2, 2013 at 11:12 PM, Dave Cheney wrote:

    It is important to remember that common types like time.Time and
    slices are not single words

    lucky(~/src) % cat size.go
    package main

    import "fmt"; import "unsafe"; import "time"

    func main() {
    var t time.Time
    fmt.Println("sizeof time.Time:", unsafe.Sizeof(t))
    var s []string
    fmt.Println("sizeof []string:", unsafe.Sizeof(s))
    }
    lucky(~/src) % go run size.go
    sizeof time.Time: 24
    sizeof []string: 24

    So, if your values are similar sizes, deliberately passing a pointer
    to them is probably overkill.
    On Tue, Dec 3, 2013 at 11:22 AM, Edward Muller wrote:
    I was hoping there were some general rules wrt struct sizes and what not. I
    understand that's probably a micro-optimization.

    I'll measure the code and see which performs better.

    Thanks!



    On Mon, Dec 2, 2013 at 12:24 AM, Volker Dobler <
    dr.volker.dobler@gmail.com>
    wrote:
    Am Montag, 2. Dezember 2013 00:21:16 UTC+1 schrieb freeformz:
    Would it be more "efficient" to send pointers to struct instances or
    the
    struct instances themselves via a channel to another go routine? And
    why?
    What about function calls in the same go routine?
    ...
    By efficient I mean it as "holistically" as possible, accounting for GC
    runs and the such as well as any passing overhead.
    Simple answer: Measure it. Sometimes 3 weeks in the lab can save you
    4 day in the library but this doesn't sound like such an issue.

    V.

    --
    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.



    --
    Edward Muller
    @freeformz

    --
    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.


    --
    Edward Muller
    @freeformz

    --
    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 Dec 4, 2013 at 12:01 am

    On Wed, Dec 4, 2013 at 7:49 AM, Edward Muller wrote:
    Thanks. I did some testing and passing pointers for this common struct ended
    up being slower and causing more allocations, so I've gone back to just
    passing the struct. Bonus: I now have benchmarks to compare against for
    future code changes.
    Excellent, I had suspected this would be the case so thanks for
    validating this.

    All function arguments (and return values) are passed on the stack
    (that's why they aren't passed by reference kids) so when you pass a
    struct to an argument you're paying the cost of reading and writing a
    few words which have a very high possibility of being in the L1D
    cache, and almost guaranteed to be in the L2.

    Passing a pointer to your struct raises the possibility that the
    compiler may detect this pointer escapes and force it onto the heap.
    Escape analysis may be able to repair some of this and move the
    pointer back to the stack but then your still have to pass that
    pointer on the stack to the function.

    Compare this to the cost of heap allocation, and then the much bigger
    cost of marking and sweeping those short lived objects during the next
    gc cycle.

    I'd be very interested in seeing your benchmarks if you could make
    them available. I think they are useful resource for this common
    design question.

    Cheers

    Dave

    --
    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.
  • Brendan Tracey at Dec 4, 2013 at 7:27 pm
    I didn't understand your above point. Why is it important to remember they
    are bigger than words?

    --
    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 Dec 4, 2013 at 10:09 pm
    I believe when people hear that arguments are passed by value they look at their struct and say, that _could_ be a lot to copy, I've heard copying is bad, so instead I'll pass a pointer to tr value, that should be less copying.

    What is probably not obvious is common values like slice headers and time.Time are several times larger than a pointer but we've all been passing them as values to functions since day 1 and it's never shown up in a profile.

    As the OP discovered, on paper, passing pointers to argument values should mean less data has to be copied into the call stack, but it turns out that copying small amounts of data is something CPUs do really well, and the theoretical cost is overshadowed by the real cost of heap allocating and the collecting all those values passed by pointer.
    On 5 Dec 2013, at 6:27, Brendan Tracey wrote:

    I didn't understand your above point. Why is it important to remember they are bigger than words?
    --
    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.
  • Brendan Tracey at Dec 4, 2013 at 10:13 pm
    Ah, okay, that makes sense. Thanks for the explanation.
    On Dec 4, 2013, at 2:08 PM, Dave Cheney wrote:

    I believe when people hear that arguments are passed by value they look at their struct and say, that _could_ be a lot to copy, I've heard copying is bad, so instead I'll pass a pointer to tr value, that should be less copying.

    What is probably not obvious is common values like slice headers and time.Time are several times larger than a pointer but we've all been passing them as values to functions since day 1 and it's never shown up in a profile.

    As the OP discovered, on paper, passing pointers to argument values should mean less data has to be copied into the call stack, but it turns out that copying small amounts of data is something CPUs do really well, and the theoretical cost is overshadowed by the real cost of heap allocating and the collecting all those values passed by pointer.
    On 5 Dec 2013, at 6:27, Brendan Tracey wrote:

    I didn't understand your above point. Why is it important to remember they are bigger than words?

    --
    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.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedDec 1, '13 at 11:21p
activeDec 4, '13 at 10:13p
posts18
users8
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase