FAQ
Hi all --

I'm writing an interpreter for a simple scripting language, and the
main data structure will naturally be an AST. ASTs tend to be deeply
nested, consisting of many small nodes. The node structs look like

type ASTAssignment struct {
target string
expr ASTNode
}

type ASTFunctionCall struct {
function ASTExpression
args []ASTExpression
}

...so the cost of copying one single node is pretty small. But I'm
worried about the overhead when there are thousands of nodes kicking
around.

The obvious overhead is the cost of copying bytes in memory. But
should I also be worried about allocation costs and the impact on GC?
My gut instinct says yes, but I'm unclear on the details. Has anyone
written a guide about when/why/how to worry about allocation and GC
overhead?

On a related note, I'm also confused about the costs of a slice of
interface type vs a slice of concrete type. Consider my
ASTFunctionCall above, which includes

args []ASTExpression

ASTExpression is an interface type: lots of AST nodes are expressions.
Currently I'm putting plain structs into my node lists, without
pointers:

// for arg list (op1+op2, "foo")
arg0 := ASTAdd{op1, op2}
arg1 := ASTString{"foo"}
args = []ASTExpression {arg0, arg1}

What exactly happens to that concrete ASTAdd struct when it's put into
the []ASTExpression slice-of-interfaces? Is the struct copied? Should
I use pointers instead to reduce copies?

Thanks --

Greg

--

Search Discussions

  • Tomwilde at Nov 16, 2012 at 10:44 pm

    What exactly happens to that concrete ASTAdd struct when it's put into
    the []ASTExpression slice-of-interfaces? Is the struct copied? Should
    I use pointers instead to reduce copies?
    Yes, they are copied, as you can see in the following demo:

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

    --
  • Volker Dobler at Nov 16, 2012 at 10:55 pm

    Am Freitag, 16. November 2012 18:08:57 UTC+1 schrieb Greg Ward:
    ...so the cost of copying one single node is pretty small. But I'm
    worried about the overhead when there are thousands of nodes kicking
    around.
    Do not worry if there is no problem. If there is a problem:
    Measure with pprof and get rid of the problem.
    I would not pre-optimize such stuff without actual need.


    The obvious overhead is the cost of copying bytes in memory. But
    should I also be worried about allocation costs and the impact on GC?
    My gut instinct says yes, but I'm unclear on the details. Has anyone
    written a guide about when/why/how to worry about allocation and GC
    overhead?
    Again: Do not worry too much about something which might not be
    an issue. One of my packages was dealing with XML manipulations
    and allocated and dropped lots of small node structures. It was half a
    day work to get rid of 30% of these allocations and subsequent
    garbage collection by using the leaky buffer of effective Go:
    http://golang.org/doc/effective_go.html#leaky_buffer
    These 30% reuse could be made better, but it was not worth the
    effort as other stuff got limiting. That's why I would suggest measuring
    instead of worrying :-)

    Volker

    --
  • Russ Cox at Nov 25, 2012 at 8:04 pm

    On a related note, I'm also confused about the costs of a slice of
    interface type vs a slice of concrete type. Consider my
    ASTFunctionCall above, which includes

    args []ASTExpression

    ASTExpression is an interface type: lots of AST nodes are expressions.
    Currently I'm putting plain structs into my node lists, without
    pointers:

    // for arg list (op1+op2, "foo")
    arg0 := ASTAdd{op1, op2}
    arg1 := ASTString{"foo"}
    args = []ASTExpression {arg0, arg1}

    What exactly happens to that concrete ASTAdd struct when it's put into
    the []ASTExpression slice-of-interfaces? Is the struct copied? Should
    I use pointers instead to reduce copies?
    Yes, the struct is copied. If you would have used a struct pointer in
    C, you should probably use one in Go too. That will avoid the copy.
    Whether it matters depends on how these get used, of course. But I
    would probably use &ASTAdd{...} etc here and define the methods
    satisfying ASTExpression to take pointer receivers to keep me honest.

    http://research.swtch.com/interfaces has details about how interfaces
    are implemented.

    Russ

    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedNov 16, '12 at 5:08p
activeNov 25, '12 at 8:04p
posts4
users4
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase