Hacker News new | ask | show | jobs
by pizlonator 610 days ago
Malloc has its own overheads, and they are often worse than those created by GC.

Something to consider is that Fil-C permits you to do all of the things you would normally do, as a C programmer, to reduce or eliminate allocation - like having structs embedded in structs and avoidance of allocation in core algorithms.

This makes it quite different from Java or JS where the language forces you to allocate to basically do anything. I think folks conflate “GC overhead” with the overhead of languages that happen to use GC.

2 comments

> I think folks conflate “GC overhead” with the overhead of languages that happen to use GC.

That is fair to a point. Some GC languages (like Java) are significantly more inefficient than they need to be regardless of the GC.

Nonetheless, for performance C++ code you don’t see much malloc anywhere, directly or indirectly, so the efficiency doesn’t matter that much. That’s pretty idiomatic. I think this is the real point. As a C++ programmer, if you are not serious about eliminating dynamic allocation then you aren’t serious about performance. Since C++ is used for performance, you don’t see much dynamic allocation that a GC could theoretically help with. Most objects in the hot path have explicitly and carefully managed lifetimes for performance.

I use GC languages for quite a few things, but it is always for things where performance doesn’t matter. When performance matters, I’ve always been able to beat a GC for performance, and I’ve done my fair share of performance engineering in GC languages.

> Nonetheless, for performance C++ code you don’t see much malloc anywhere, directly or indirectly, so the efficiency doesn’t matter that much. That’s pretty idiomatic.

If you compile that code with Fil-C++, then you won't see much (or any) GC overhead. The GC kicks in for three things:

- malloc (this is the main client of the GC)

- stack allocations that aren't escape analyzed (these are rare, typically small, and generate minuscule GC load - it's common for code I've tested to have zero of these)

- Fil-C runtime internal allocations (these are super rare - for example if you call sigaction, pthread_create, setjmp, or dlopen then there's some GC object allocated behind the scenes - but you aren't going to be calling those a lot, and if you are then you've got bigger problems than GC).

I understand your perspective about GC languages. Most GC languages also come with other baggage, which makes it very difficult to avoid the GC. Most C++ code that avoids malloc ends up doing a bunch of `new`s when converted to Java. But C++ code that avoids malloc will avoid the GC if compiled with Fil-C++.

You've lost me here a little, sorry. If you have little to no dynamic allocations, meaning all of your memory will be automatic stack memory, then memory management wouldn't be much of an issue to begin with. But the most common pattern to me seems to be memory that is allocated upfront, and then treated as-if it were automatic in a hot loop, so not reallocated or moved etc., and then deallocated after the hot part is over. How does GC interfere with these use-cases, because I'd imagine it would only kick in after, when you'd want to deallocate anyway, but do this automatically without you messing up.
At this point you could also use C# for vastly better user experience, that builds on top of compiler that is actually GC-aware and does not have a performance penalty, aside from being just weaker than GCC (although that is improving with each release);
C# isn’t C though. The point of Fil-C is you can compile real C programs (like CPython or SQLite and many others) with it.

Fil-C’s compiler is GC aware.