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/ 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.
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).
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.
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.
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.
"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.
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.
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.
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.
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.
> 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.
We can't wait for Go 1.5 where the Stop-The-World GC goes away: https://docs.google.com/document/d/1wmjrocXIWTr1JxU-3EQBI6BK...