
Manual Memory Management in Go - deferpanic
https://deferpanic.com/blog/manual-memory-management-in-go/
======
jgrahamc
The article references a blog post that I wrote a long while ago about how we
do memory management for some Go programs at CloudFlare:
[https://blog.cloudflare.com/recycling-memory-buffers-in-
go/](https://blog.cloudflare.com/recycling-memory-buffers-in-go/) We've
switched most of that stuff to use sync.Pool now. And we've done a lot of
pprof work to simply reduce garbage in the first place.

We can't wait for Go 1.5 where the Stop-The-World GC goes away:
[https://docs.google.com/document/d/1wmjrocXIWTr1JxU-3EQBI6BK...](https://docs.google.com/document/d/1wmjrocXIWTr1JxU-3EQBI6BK6KgtiFArkG47XK73xIQ/edit#)

~~~
pjmlp
Nice article.

Regardless of my opinion about some Go issues, I really look forward to see
the language becoming widespread.

My experience with Oberon back in the mid-90's, made me aware that it is
possible to have systems languages with GC.

The main problem is that many developers don't experience the variety from GC
implementations that exist out there, and equate all implementations alike.

In Oberon's case it wasn't the best GC in the world, specially in mid-90's PC
hardware, but coupled together with value types it was good enough to fully
implement an OS in Oberon (and its derivatives).

------
timtadh
Not a very useful article from the perspective of you are the point where you
need to take some control over memory management in Go. The article spends a
lot of time telling you should probably don't have that problem or you are not
going to do any better than the Go. However, it is pretty easy to start
proving you have that problem. Furthmore, you can make a real dent in the
problem if you spend enough time working on it.

I should probably not just complain but explain

1\. How to prove via pprof and other tools that you have problems related to
memory allocation or GC.

2\. Some strategies for addressing that problem that don't involve writing an
allocator. Using sync.Pool or a recycler pattern. Keeping allocations on the
stack etc...

3\. How to write a allocation interface in Go for allocating arbitrary
objects. Aka emulating New and Make.

4\. How to write a allocator backed by a memory mapped files.

I have been working for a while in this space because of my academic research
which involves frequent subgraph mining. That particular data mining problem
is exponential and certain techniques can use a lot of memory. In order to
scale my solution I have need to get the memory allocations under tight
control. Sometimes I think I should just re-write in C++ or Rust but Go has
provided me a lot of benefits from the concurrency angle so it isn't a win/win
to move languages.

Maybe I will write up all of this stuff at some point. It is a bit much for an
HN comment.

~~~
nulltype
I agree that this doesn't seem to actually cover practical memory management.
In Go (and perhaps most languages) this seems to mean avoid allocations, and
if you have to allocate, avoid the heap.

Maybe some information about how heap size and mutation rate affect GC would
be interesting, as well as the future of the Go GC.

One interesting thing about Go is that if your objects contain no pointers,
the Go GC does not have to scan them. So you can supposedly create huge slices
of any type containing no pointers and the GC will have a much lower load on
it.

There's a really good article from Dmitry Vyukov including memory related
stuff here: [https://software.intel.com/en-
us/blogs/2014/05/10/debugging-...](https://software.intel.com/en-
us/blogs/2014/05/10/debugging-performance-issues-in-go-programs)

------
Profan
The title seems a bit misleading, the author goes on to talk about possible
performance issues and how people view GC's and issues with manual memory
management, but never actually touches on how to actually use any of the
alternatives mentioned.

.. So it's actually just an advertisement for their product, the title should
really be something else, I feel a bit mislead initially assuming something
useful might be had from reading the article.

------
jenandre
"Imagine doing lots of small allocations - you can cause a lot of
fragmentation resulting in needlessly having to resize your heap which in dire
scenarios can result in thrashing."

The article repeatedly talks about how managing memory manually increases the
risk of fragmentation. And that this risk somehow goes away with gc managed
heaps.

...so garbage collectors don't also have to manage their own internal heaps
and have fragmentation issues? Hm, not sure I buy this.

~~~
plorkyeran
Compacting garbage collectors don't have fragmentation issues, but of course
Go doesn't have one. A GC isn't even strictly a prerequisite for compaction.
Manually combining memory allocations to reduce allocator overhead and
fragmentation is a lot of work, but not unheard of.

~~~
ridiculous_fish
The Classic Mac OS API (the "toolbox") had a compacting manual memory
management scheme. Instead of raw pointers like what malloc might return, you
worked with double-pointers called Handles (different from Win32 Handles),
which indirected through a global Handle table. System calls may compact or
rearrange the blocks of memory referenced by Handles. If you wanted to
dereference the Handle across a system call, you had to HLock it to keep it
from being moved, similar to object pinning in C#.

In modern OSes, virtual memory plays an analogous role. We still have a double
indirection, but it goes through the TLB and page table.

------
jdright
As if managing memory manually was only the need of calling malloc and free at
will. The problem with pro-GC is that they think the ones against it only want
and like to do malloc and free for fun. Their simplist view of the issue is
really as much annoying as they dismiss of the performance* issue.

*real-time, embedded and gamedev for example. where us scale have as much importance as ms for other fields.

------
vvanders
Usually when you want to manual memory management it's for two reasons:

1\. You have more domain knowledge about the objects you're creating so you
can special case and beat malloc()/free()(which can be extremely painful in
some cases).

2\. You need to control the _memory layout_ of your objects so that the data
access patters line up with memory layout. The speed improvements here are on
the order of 50-100x depending on your case.

Usually(but not always) GC'd languages don't give you value types that let you
do #2. C# and a few others happen to be a nice exception. If you're using Java
you end up being out of luck unless you decided to leverage a library that
provides views into byte buffers like FlatBuffers. Although then you pay the
indirection costs.

I haven't worked much with Go to know if it supports composing values types
like C# but when we talk about performance that's usually what crosses a lot
of GC'd languages from my list.

------
Dewie3
> This is at the point when another developer on the team will pipe in stating
> their preference for another langauge, that if you might not be a software
> engineer, you might confuse w/the chemical compound of Fe2O3.

Or a certain fungi. :)

[http://stackoverflow.com/questions/16494822/why-is-it-
called...](http://stackoverflow.com/questions/16494822/why-is-it-called-rust)

