Comment by mi_lk
12 hours ago
Would you mind sharing some thoughts about fil-c? AFAICT its claims mostly check out so besides implementation details (GC?) it seems directionally good.
12 hours ago
Would you mind sharing some thoughts about fil-c? AFAICT its claims mostly check out so besides implementation details (GC?) it seems directionally good.
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.
> 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.
1 reply →
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.
Rust advocates and Hacker News moderators love vote manipulation to upvote Rust topics.
1 reply →
I'll come back and say some more in a bit, but in short: I like the idea of fil-c, but I also have some issues. I think it's overall a good and interesting project, but with some caveats.
[flagged]
Not OP, but AFAIK one big issue with FIL-C it does the checks at runtime, adding overhead, don't quote me on this, but IIRC is around 20% slower.
2x slower and 4x less memory efficient were the numbers I heard a year or so ago. Reaching within 20% of full native performance while using a garbage collector sounds too good to be true.
Do you have any actual benchmarks?
Okay so: in general, as a rule of thumb: anything that makes stuff have more memory safety is good. And experiments towards that end are also good.
What I do not like, primarily comes down to how the project is talked about and marketed. First, because it promotes an "us vs them" mindset, instead of a "we're all trying to improve memory safety" mindset, and second, because in doing so, it also overstates its case.
These things are sort of intertwined. Let's talk about the overstatement first. Fil-c has its own definition of memory safety that is slightly different than others. For example, I saw this recently:
This, when invoked with "012345678" passed in, will print "I am root!". In my understanding, this is deliberately allowed.
But beyond corners like this, fil-c's author will go on about "Rust has unsafe as a hatch, fil-c does not" while if you control-f for "zunsafe_" on https://fil-c.org/stdfil you get ... escape hatches.
The author regularly erases the difference between "traps at runtime" and "is prevented at compile time", which are legitimate tradeoffs where one or the other may be better depending on what you're doing. But they're presented as either equivalent, or one is superior, and I find this muddles the discourse. The performance issues also tie into this, "add a GC" is absolutely a valid way to handle these sorts of issues, but it is not the same thing as what Rust does. And that's okay! But presenting it as purely superior means that it's just hard to talk about.
Speaking of muddling the discourse, the author regularly trolls on X, providing tons of bad faith arguments and generally trying to rile up a "fil-c vs Rust" war that I think reduces our ability to talk about these differences in a calm, engineering focused context.
Finally, due to its design, fil-c is effectively Linux only. That's great for Linux, but many people also use other systems, and so it is not a meaningful option for them.
Anyway, after saying all that: I still think that it is a good project, and that it should exist and continue to be worked on. I just wish that the heat was turned down, and people could talk about the various approaches and their tradeoffs without turning it into a culture war.
I generally agree with all of this, but I'll add a few additional remarks. Because it's come up a bunch lately, I decided to do a bunch of code review/audit of the Fil-C codebase, and I'd say while it's got a lot of good bones, there's a long way to go to being a foundation I'd be ready to build on. I've reported a few UAF's upstream, and I've got a few PRs I'll add on, but if it only took me a day or two to find some of these big holes, I'm sure there's more lurking under the surface. I'd consider it to at this point be more of an engineering demo that this approach is feasible and tractable, but not a production ready language that I'd want to ship code in.
On the muddling the discourse, I'm not on twitter and don't engage there, so I don't have an opinion on that, but I did come across https://news.ycombinator.com/item?id=49044561 recently, and I just don't see how the author can make such bold claims while examples like the one Steve provided above are still in the language. Corrupting memory in Fil-C is still easy, type confusion is still easy, intra-object overflows are still easy. Fil-C prevents a range of classes of bugs from being exploitable, but it doesn't stop the bugs from happening.
Yeah. In that thread the Fil-C author said of typescript, go and C#:
> Those languages rely on a much larger pile of YOLO C/C++ code for their runtimes and standard libraries than Fil-C does. So Fil-C is safer than those
Given the relative immaturity of Fil-C, this seems wildly wrong to me. I’m not sure how to take his claims about his runtime seriously.
[ https://news.ycombinator.com/item?id=49042736 ]
> it promotes an "us vs them" mindset, instead of a "we're all trying to improve memory safety" mindset
But you did the same thing when, on the spectrum that ranges from C to ATS, with Zig, Rust, and Java somewhere in the middle (though all closer to C than to ATS), you declared the exact compromise that Rust makes "table stakes"! [1]
Zig improves on C's memory safety when it comes to spatial safety, possibly the more impactful kind, so it, too, could be part of the "we're all trying to improve memory safety", yet you exclude it.
You're trying to draw some hard line that passes exactly between Rust and Zig on the C to ATS spectrum, and I'm trying to say that that line isn't there (your attempt at a definition of delineating safe and unsafe code also applies to C). Obviously, C, Zig, Rust, Java, and ATS all make very different tradeoffs, all of which may be more or less attractive to different people and in different circumstances, but there is no sharp line, at least not one that is meaningful enough to be "table stakes". Your personal inclinations place a premium on the things Rust offers and Zig doesn't while mine are the opposite, but I make no claim to universality.
I'm happy to accept that not everyone shares my aesthetics and can understand why some people prefer Rust, but those claims to or hints at universality annoy me (as they did when they were made by Haskellers, and I actually find Haskell's aesthetics quite pleasing), as they are simply unsupported. I've spent a lot of time studying formal methods and software correctness in general (https://pron.github.io) and if there's one thing we know in that field is that things are never that simple (and, bringing this back to this posts topic, even something like incremental compilation can contribute to program correctness).
(Now, you may argue that you're only talking about "memory safety" and not correctness in general, but what gives memory safety value is that violations are causes of many dangerous vulnerabilities; but once, say, Java eliminates all of them, 100% of bugs/vulnerability - which are still numerous - will be caused by other problems, all potentially avoidable with ATS, so why isn't ATS table stakes? Of course, the answer is cost, but all the languages on the spectrum differ in their costs.)
[1]: I assume that you meant Rust's compromise, because you implied that Zig doesn't pass that bar but Rust does.
> But you did the same thing when,
I do not go around posting "omg Rust is SO MUCH BETTER than zig or fil-c, which are TRASH." I talk about engineering tradeoffs, and what matters to me personally. I do not say "if you use Zig, you are a bad person." I am not saying that any comparison is bad. I am saying that the way that the comparison is presented is bad. That is different.
> you declared the exact compromise that Rust makes "table stakes"
Table stakes for me.
> Zig improves on C's memory safety when it comes to spatial safety,
I agree that it's an improvement on C!
> yet you excluded it.
I said that it is not pursuing a design that I personally find compelling enough to use to write software. That doesn't mean that I think it's worthless. This whole thing started off with me talking about how much I respect the Zig project! Yet you're trying to turn this into something where I'm talking shit. I presented a specific technical tradeoff that is important to me. That is very different.
> You're trying to draw some hard line on a spectrum that passes exactly between Rust and Zig, and I'm trying to say that that line isn't there (your attempt at a definition of delineating safe and unsafe code also applies to C)
I don't believe you've shown that. And my "attempt" does apply to C: it fails the bar, because it does not delineate between a safe subset and an unsafe superset.
> you may argue that you're only talking about "memory safety" and not correctness in general,
I am in fact talking about "memory safety" and have been this whole time, yes.
> what gives memory safety value is that violations are causes of many dangerous vulnerabilities; but once, say, Java eliminates all of them, 100% of bugs/vulnerability - which are still numerous - will be caused by other problems, all potentially avoidable with ATS, so why isn't ATS table stakes?
This is just an entirely different question. Yes, there are other forms of safety that are important too. That's just not what we're talking about here.
1 reply →
There's a distinction between claiming something is objectively better, which is what Fil-C claims with respect to its "idea" about memory safety compared to Rust... and claiming a personal preference for one approach versus another approach, which is what OP is saying about their own personal preference about how Zig reduces errors compared to how Rust reduces errors.
It is absolutely possible that one language might actually have an objectively better approach to memory safety than another, and in such cases it is usually possible to argue for this using sound technical or empirical arguments. But the way the author of Fil-C presents their arguments it often comes across in a kind of antagonistic manner, like he has a chip on his shoulder.
1 reply →
> But you did the same thing
So your defense is a tu quoque fallacy? Note that "the same thing" is an admission.
I’ve been watching this debate online and in my opinion both sides are guilty. Fil is intentionally trying to be funny or at least “interesting “ when he makes his points and I, for one, enjoy his humor, which includes having a go at Rust and other languages. It seems Rust people just can’t take a little criticism, even when it comes from a clearly trolling language! Yes it’s true Rust has an escape hatch, and we’ve seen serious memory safety bugs due to unsafe Rust in the wild. Fil-C does not have one, what you post seems to be internal or even temporary stuff given the author clearly has a goal of not providing one? I would say you and others need to just relax and not treat all and every Rust criticism as an offense to you.
Maybe I'm just old, but I want to focus on engineering outcomes, not "trolling." If that means "can't take a joke," that's fine, but also "haha I'm just joking" is often what people use to try and hide behind their actual intentions.
I don't even work on Rust anymore, and in fact started this thread with a criticism of Rust. There are lots of good criticisms of Rust. There is a difference between "this criticism isn't good" and "every criticism is an offense."
1 reply →
Yes! I think Fil is great so far but I think as he gets a bigger audience he should, well, consider that and focus on clarity a little more than humor. You can see Andrew’s growth in that respect.
Rust folks, this whole thing is a thread about Zig’s new feature - not even a memory safety-related feature! - and we cannot spend the whole damn time talking about Rust.
Steve, even you - I don’t believe I have ever seen you say an unkind word. But have you considered that it may be unkind to have written more than half of the words on a thread about a Zig performance feature?
5 replies →
> It seems Rust people just can’t take a little criticism, even when it comes from a clearly trolling language
I think this is a case of people who can dish it out but can't take it. As far as I'm concerned if you troll someone you should expect to get trolled back.
4 replies →
[dead]