Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

My main problem with Fil-C is that it combines the worst parts of C with the worst parts of a GC language.

In a language like C (or Zig), you need to manually manage memory. This makes programming a lot more complex, and it's really easy to accidentally mess up. Especially in large projects which have a lot of separate modules.

The biggest advantage of using a garbage collector is that you don't have to think about freeing memory. The GC automatically frees objects when they're no longer referenced. This makes programming much much easier. The downside of using a garbage collector is that it hurts performance at runtime. GC languages are slower and use more RAM.

Fil-C is the worst of all worlds here. Like C, it forces you to manually manage your own memory. But you still pay the performance cost of having a runtime garbage collector. And that cost is (apparently) really high. The only performance numbers I've seen showed ~2x worse CPU performance and ~4x worse memory performance. There's no way Fil-C can compete with C, Zig and Rust for performance.

So with Fil-C, you have a language that's much slower than C, and much more difficult to program in than C#, Java, Go or Typescript.

Fil-C still has some wonderful uses. Fil-C could be a fabulous debugging tool for C programs. It could be a wonderful teaching tool if it had nice visualisations on top of the GC's view of the world. And it could be a great way to run legacy C code.

But it's not a "rust killer". Fil-C programs run too slowly to be able to compete head to head with rust. And Fil-C doesn't offer the language benefits of a GC that you get in C#, Go, and friends. It seems like a really bad deal.

 help



> GC languages are slower

This is not necessarily true. It depends on a language, e.g. Go is slow, Nim[0] is extremely fast with conventional GC and slightly faster with ARC/ORC[1].

GC programs can be faster than manually managed ones in some cases. It's just manual memory management gives you more control of where and when free is called. And a good type system is a privelege that gives Nim more control with destructors.

Another scarecrow of safe languages is GC pauses, which is also not a thing in Nim, see table in [2].

[0] - https://nim-lang.org/

[1] - https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc...

[2] - https://nim-lang.github.io/Nim/mm.html


You can always use things like arenas in C and get similar speed ups without GC overhead. If you know your memory lifetimes in advanced, avoiding granular malloc/free calls is pretty straightforward. A GC language doesn’t usually offer such options.

You can easily use arena allocation in a GCed language. With modern GCs there's not usually much performance benefit, so it tends to be limited to hot paths.

Sure it does, D just to give one example.

You provide no trustworthy benchmark for your claim that Go is slow, or that nim is faster than that. Many engineer hours have been put on the go GC and compiler

You can find a number of benchmarks with similar results, but I really like this one[0]. I didn't check all algorithms for differences, but just looking on mandelbrot bench - both are version 1 (without hacks or some manual loop unrolling thrown in) and both are implemented in semantically identical code. Nevertheless, Nim version runs 7x faster and, literally, on par with C.

[0] - https://programming-language-benchmarks.vercel.app/nim-vs-go


I haven't seen data that would confirm that the Nim ARC/ORC approach is faster than manual memory management (C/Rust/Zig/...) on programs with non-trivial lifetimes (for trivial lifetimes, Nim elides RC). I'd also be somewhat surprised if it was consistently faster than GC – most languages with automatic memory management use GC over RC because RC adds significant overhead, especially in multithreaded programs.

Good to know! Would there be any way languages like Go or C# could adopt Nim's new garbage collector? If it's better, what stops other languages from using it?

> GC programs can be faster than manually managed ones in some cases.

I've seen poorly written programs in C/C++/Rust which are slow because they allocate millions of tiny objects. Its true that generational GCs can be faster in this case. But you usually get much better performance again by using arenas and such. The reality is that I know more about the lifecycle of my data than my compiler. If you know what you're doing, you can take advantage of this information to write better programs.

If you don't want to think about memory management, then I agree - you're usually better off using a language with a GC. Personally I do a lot of my prototyping in typescript because I can iterate faster when I don't have to think about lifetimes.

Maybe some day Fil-C will run general purpose C code at native speeds, without a high memory overhead. But we're not there yet. I'm not holding my breath.


Even if you don't think about memory management, and do the naive thing in rust or rc in some other systems language, gc only comes out ahead in that many tiny objects case. Which is very domain specific. I don't ever run into that situation, or if I do, they are homogeneous in type so I handle them in bulk, not individually.

That depends on what you mean by GC. There are refcounting GCs, there are mark-and-sweep tracing GCs (like the one Go uses), and there are moving GCs (the last ones are the ones used in Java, V8, and .NET). Moving GCs win in many situations because they're just a really efficient algorithm both in theory and in practice (they win on speed, and the tradeoff is footprint). The downside is that they require 1. a lot of expertise and effort to implement (in fact, the first open-source, high-throughput, low-latency pauseless moving GC only appeared 3 years ago), which is why only specialised expert teams have implemented them, and 2. that virtually all pointers can move, which means that interop with low-level code requires some specialised API. That last restriction means that low-level languages generally cannot enjoy the optimisations that moving collectors bring.

[flagged]


complains about vote manipulation

user created an hour ago


> Fil-C is the worst of all worlds here. Like C, it forces you to manually manage your own memory.

Can you expand on this?


As far as I know calling free is optional with Fil-C. It can prevent situations where some memory is no longer needed but isn't freed due to some remaining pointer to it sitting around somewhere, but it's not required. The GC will act like a GC if given the opportunity.



Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: