top | item 28378275

(no title)

hootbootscoot | 4 years ago

no Zig nor Nim nor D but you include 2 GC'ed languages as suitable for "low-level code"???

discuss

order

t8sr|4 years ago

You know, it's interesting to me how much people fixate on garbage collection.

Taking Go as example, there are many pitfalls to using it in low-level situations, but the GC is, in practice, never a source of significant issues.

The real problems are:

1) The foreign function interface (CGO) requires a context switch in both directions. (Not because of GC, but because of Go's threading model.) A lot of work ends up being in trying to avoid calls between Go and C in hot loops.

2) Especially talking to the kernel, there are surprising sharp edges in the ABI and C calling convention. I once spent a week trying to populate a bit field correctly. (But other languages would have the same problems matching any C behavior that's left up to the compiler.)

3) The lack of memory fences is a big deal when trying to use kernel-managed ring buffers.

The GC, comparatively, is problem-free for two reasons:

1) A lot of embedded code uses static buffers anyway.

2) The problem of managing memory doesn't go away just because you're in ring0. The Linux VFS, for example, is heavily garbage collected, it just uses a jerry-rigged GC consisting of counting references. I'm sure if I make a categorial statement on this someone on HN will take me to school, but I think a real GC might be a net performance win in some places in the Kernel, like the VFS.

Finally, people often bring up that GC is fine for throughput, but not for latency. Fair enough, but manual reference counting is also not better: someone has to call free at some point, and if you happen to draw the short straw in a blocking system call, it still affects latency. The amortization behavior is probably different, but not in any way that I think matters to most people.

runevault|4 years ago

Maybe at small scales like embedded, but Go's GC has proven problematic even with static memory allocation. Some company (Discord?) ran into issues where the large heaps were scanned every 2 minutes because Go refuses to go longer than that w/o a GC check even if it has no reason to believe it needs to.

mumblemumble|4 years ago

I can't make categorical statements, either. But here's another concrete observation to offer as evidence that things are not so clear cut: in generational GC, heap allocation is typically O(1). A heap allocation is typically O(n), where n is the size of the heap.

Of course that difference also tends to go away if you're using static buffers.

frashelaw|4 years ago

D is excellent for systems programming