Does it make sense to build a map of pointers to structs instead of structs?

1,829 views
Skip to first unread message

Manuel Kiessling

unread,
Aug 7, 2012, 7:17:39 AM8/7/12
to golan...@googlegroups.com
Hi all,

I'm currently building a web server that will serve an api. Through api requests, I can add things ("experiments" in this case), and, as of now, I can check if for a given key (an url in this case), a thing already exists.

The things only live in memory, i.e., in a map. In order to make this server as efficient as possible memory-wise, I thought it could make sense to have this map only store the pointers to the things, but not the things itself.

But I'm very new to Go and still don't get the whole "reference" thing, thus I'm not sure if the code would be just as efficient if I stored the things into the map directly.

Here is my current version of the code:


Regards,
Manuel

Volker Dobler

unread,
Aug 7, 2012, 7:42:44 AM8/7/12
to golang-nuts

On 7 Aug., 13:17, Manuel Kiessling <man...@kiessling.net> wrote:

> The things only live in memory, i.e., in a map. In order to make this
> server as efficient as possible memory-wise, I thought it could make sense
> to have this map only store the pointers to the things, but not the things
> itself.
>
> But I'm very new to Go and still don't get the whole "reference" thing,
> thus I'm not sure if the code would be just as efficient if I stored the
> things into the map directly.

This is a question which cannot be answered as the answer depends
on your definition of "efficient". Both variants will use the same
amount
of memory. I wouldn't care about execution time as a pointer
de-reference is negligible compared to the latency of http.

I would recommend: Don't reason about such stuff. Refactor iff
you run into an identifiable issue.

Some remarks on the code:

* Go is smart enough to dereference a pointer: Instead of
(*experiment).Name just write experiment.Name which works
with both: experiment being a types.Experiment or a pointer
to it.

* Instead of
experiment := experiments[url]
if experiment != nil { }
use the comma ok idiom:
if experiment, ok := experiments[url]; ok { }
Again this works for both variants (pointer/value)

* Instead of experiment := new(types.Experiment) I would
use experiment := &types.Experiment{}

With these little changes your code will be almost exactly
the same, regardless whether you store experiment values
or experiment pointers in your map. Refactoring will be
done in 2 minutes (if needed).


Volker
Message has been deleted

Volker Dobler

unread,
Aug 7, 2012, 8:15:40 AM8/7/12
to golang-nuts
On 7 Aug., 14:10, Manuel Kiessling <man...@kiessling.net> wrote:
> Thanks a lot! The
>
> > Both variants will use the same amount of memory
>
> part is the most relevant for me - not because my app will see Google scale
> anytime soon, but because I wanted to understand how Go works. I wasn't
> sure if
>
> experiment := experiments[url]
>
> wouldn't "pull" a copy of the struct out of the map, resulting in higher
> memory usage.

Ah! No, of course experiment := experiments[url] will always
create a copy. if types.Experiment itself is big this might be
an issue, but typically most Go structs are small (if they do
not contain arrays).

Volker

chl

unread,
Aug 7, 2012, 8:15:51 AM8/7/12
to golan...@googlegroups.com
Well there's no clear cut answer to your question. 

The answer i would give is it depends. If you are going to share large data, in multiple places than use a pointer, if not than use a struct to avoid a little bit of overhead.

And another note, instead of this: 

experiment := types.Experiment{}
  experiment.Name = data["name"]
  experiment.SetUrl(data["url"])

You could do this:
experiment := types.Experiment{
Name: data["name"],
SetUrl: data["url"],
}

Thats about all i have to save. And on a personal level, i would avoid a variable name that is one character different than another variable name, ie experiments, and experiment (this is just my personal tastes of course).

Good luck.

chris dollin

unread,
Aug 7, 2012, 8:18:46 AM8/7/12
to Volker Dobler, golang-nuts
On 7 August 2012 12:42, Volker Dobler <dr.volke...@gmail.com> wrote:

> This is a question which cannot be answered as the answer depends
> on your definition of "efficient". Both variants will use the same
> amount
> of memory.

Not true, in two different ways:

(a) the pointer variant will use more store than the struct variant, because
we well as the struct there is the pointer value.

(b) The pointer variant will use less store than the struct variant, because
multiple copies of the value (such as happen when you do something
like `x := theMap["theField"]) will only be pointer-sized.

Note that the contradiction between (a) and (b) is resolved by deciding
whether there will be lots of copies of the value around at the same time
or not, and the size of the individual values. (And the secret workings of
store management, which might allocated different amounts of store
behind the scenes ...).

In general: if worried, profile

Chris

--
Chris "allusive" Dollin

Manuel Kiessling

unread,
Aug 7, 2012, 8:29:58 AM8/7/12
to golan...@googlegroups.com
(Repost, as Groups somehow messed with my previous post)

Thanks a lot! The

> Both variants will use the same amount of memory 

part is the most relevant for me - not because my app will see Google scale anytime soon, but because I wanted to understand how Go works. I wasn't sure if

experiment := experiments[url]

wouldn't "pull" a copy of the struct out of the map, resulting in higher memory usage.

Thanks again,
Manuel

Manuel Kiessling

unread,
Aug 7, 2012, 8:35:42 AM8/7/12
to golan...@googlegroups.com
Thanks all for your kind advice, this really helps a lot!

André Moraes

unread,
Aug 7, 2012, 2:15:10 PM8/7/12
to Manuel Kiessling, golan...@googlegroups.com
Also, if you want to know more about that, take a look at this post:
http://research.swtch.com/godata

--
André Moraes
http://amoraes.info

Manuel Kiessling

unread,
Aug 8, 2012, 4:03:23 AM8/8/12
to golan...@googlegroups.com
That's a great read, thanks!

2012/8/7 André Moraes <and...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages