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

It's kinda sad to read as most of their arguments might seem right at first but if put under scrutiny really fall apart.

Like why defend C in 2025 when you only have to defend C in 2000 and then argue you have a old, stable, deeply tested, C code base which has no problem with anything like "commonly having memory safety issues" and is maintained by a small group of people very highly skilled in C.

Like that argument alone is all you need, a win, simple straight forward, hard to contest.

But most of the other arguments they list can be picked apart and are only half true.





At the very least, I find this argument to be fairly reasonable:

> Safe languages usually want to abort if they encounter an out-of-memory (OOM) situation. SQLite is designed to recover gracefully from an OOM. It is unclear how this could be accomplished in the current crop of safe languages.

I don't think most Rust code written today has guardrails in the case of OOM. I don't think this disqualifies Rust for most things, because I happen to find the trade-off worth it compared to the things it does protect against that C doesn't, but I don't think it's a particularly controversial take that Rust still could use some ergonomic improvements around handling allocation failures. Right now, trying to create a Box or Vec can theoretically fail at runtime if no memory is available, and those failures aren't returned from the functions called to create them. Handling panics is something you can normally do in Rust, but if you're already OOM, things get complicated pretty fast.

I agree that in the long run it would probably make sense to have something like this in Rust when eventually the current maintainers aren't around, but I also don't think it makes much sense to criticize them for continuing to maintain the code that already exists.


> But most of the other arguments they list can be picked apart and are only half true

I'd like to see you pick the other arguments apart


> Other programming languages sometimes claim to be "as fast as C". But no other language claims to be faster than C for general-purpose programming, because none are.

Not OP, And I'm not really arguing with the post, but this struck me as a really odd thing to include in the article. Of course nothing is going to be faster then C, because it compiles straight to machine code with no garbage collection. Literally any language that does the same will be the same speed but not faster, because there's no way to be faster. It's physically impossible.

A much better statement, and one inline with the rest of the article, would be that at the time C and C++ were really the only viable languages that gave them the performance they wanted, and C++ wouldn't have given them the interoperability they wanted. So their only choice was C.


> Literally any language that does the same will be the same speed but not faster, because there's no way to be faster. It's physically impossible.

There is nothing special about C that makes this true. C has semantics, just like any language, that are higher level than assembly, and sometimes, those semantics make the code slower than other languages that have different semantics.

Consider this C function:

    void redundant_store(int *a, int *b) {
        int t = *a + 1;
        *a = t;
        *b = 0; // May clobber *a if (b == a)
        *a = t;
    }
Because a and b may point to the same address, you get this code (on clang trunk):

  redundant_store:
          mov     eax, dword ptr [rdi]
          inc     eax
          mov     dword ptr [rdi], eax
          mov     dword ptr [rsi], 0
          mov     dword ptr [rdi], eax
          ret
That fifth line there has to be kept in, because the final `*a = t;` there is semantically meaningful; if a == b, then a is also set to 0 on line four, and so we need to reset it to t on line five.

Consider the Rust version:

    pub fn redundant_store(a: &mut i32, b: &mut i32) {
        let t = *a + 1;
        *a = t;
        *b = 0; // a and b must not alias, so can never clobber
        *a = t;
    }
You get this output (on Rust 1.90.0):

  redundant_store:
          mov     eax, dword ptr [rdi]
          inc     eax
          mov     dword ptr [rsi], 0
          mov     dword ptr [rdi], eax
          ret
Because a and b can never alias, we know that the extra store to *a is redundant, as it's not possible for the assignment to *b to modify *a. This means we can get rid of this line.

Sure, eliminating one single store isn't going to have a meaningful difference here. But that's not the point, the point is that "it's not possible to be faster than C because C is especially low level" just simply isn't true.


Leave it to hackernews to be overly pedantic.

Yes, obviously different languages will produce different assembly based on the language semantics. So you will get performance differences. And it's certainly possible for code written in Rust or Zig or Odin to be more performant then C code depending on how it's written.

My point was about classes of languages (for lack of a better term). Loosely, from fastest to slowest you have:

1. Compiled languages (meaning straight to machine code) with manual memory management

2. Compiled languages with garbage collection

3. Languages that run in VMs but are AOT compiled or JITed

4. Purely interpreted languages.

I acknowledge that not all languages fit nicely into these and there will be exceptions, but it's a convenient mental model that's close enough for these purposes.

Languages in the first category are going to be the most performant. Obviously there will be some variation between them based on how the code is written, but unless it's written really poorly it's not going to drop into an entirely different category. Where as languages in other categories are going to be far more difficult if not impossible to get close to the same kind of performance.

And there is no meaningfully huge jumps left after the first group. We are all the way down at optimizing assembly code, and that's where you start to hit physical limitations. Some number of operations have to be executed and the CPU can only execute them so fast.


I agree with you that there are broad, loose categories. The only thing I object to is splitting C out from category 1 and putting it into some kind of category 0.

I'm not? I'm literally saying C, Rust, Zig, Odin, and any other manually memory managed language that compiles straight to machine code is the fastest category you can have, because at that point your bumping against literal hardware limitations. There is no category below them in terms of performance.

"None faster" means you can't just change languages like you could from Java to C (assuming you can write quality code in both) and see a substantial performance boost.


> Of course nothing is going to be faster then C, ... because there's no way to be faster. It's physically impossible.

This reads to me as if you're saying C is in a class of its own. That may not be what you meant! But it's what I understood. C is the fastest language, period, and others may approach its speed (which is the ... part) but cannot surpass it. This is different than something like "C, Rust, Zig, and Odin are roughly the fastest languages."

Anyway, it's all good, we understand each other now. Sorry for appearing overly pedantic.


Fair. I was using C as short hand for that entire class of languages. I could have been clearer.

"Because none are" is a particularly hollow claim because to support it you have to caveat things so heavily.

You have to say OK, I allow myself platform specific intrinsics and extensions even though those aren't standard ISO C, and that includes inline assembler. I can pick any compiler and tooling. And I won't count other languages which are transpiled to C for portability because hey in theory I could just write that C myself, couldn't I so they're not really faster.

At the end you're basically begging the question. "I claim C is fastest because I don't count anything else as faster" which is no longer a claim worth disputing.

The aliasing optimisations in Fortran and Rust stand out as obvious examples where to get the same perf in C requires you do global analysis (this is what Rust is side-stepping via language rules and the borrowck) which you can't afford in practice.

But equally the monomorphisation in C++ or Rust can be beneficial in a similar way, you could in principle do all this by hand in your C project but you won't, because time is finite, so you live without the optimisations.


I think one additional factor that should be taken into account is the amount of effort required to achieve a given level of performance, as well as what extensions you're willing to accept. C with potentially non-portable constructs (intrinsics, inline assembly, etc.) and an unlimited amount of effort put into it provides a performance ceiling, but it's not inconceivable that other programming languages could achieve an equal level of performance with less effort, especially if you compare against plain standard C. Languages like ISPC that expose SIMD/parallelism in a more convenient manner is one example of this.

Another somewhat related example is Fortran and C, where one reason Fortran could perform better than C is the restrictions Fortran places on aliasing. In theory, one could use restrict in C to replicate these aliasing restrictions, but in practice restrict is used fairly sparingly, to the point that when Rust tried to enable its equivalent it had to back out the change multiple times because it kept exposing bugs in LLVM's optimizer.


The argument you propose only works for justifying a maintenance mode for and old codebase. If you want to take the chance to turn away new developers from complex abominations like C++ and Rust and garbage collected sloths like Java and get them to consider a comparatively simple but ubiquitous language that is C, you have to offer more.

Is SQLite looking for new developers? Will they ever need a large amount of developers like a mega-corp that needs to hire 100 React engineers?

No, but as morbid as this sounds, the three(?) devs one day will pass away so now what?

> No, but as morbid as this sounds, the three(?) devs...

Two full-time core devs and three part-time "peripheral" devs.

> ... one day will pass away ...

And not a one of us are young :/.


Well the point is that it’s not hard to find 3 people who are C experts. Yes, even young ones.

Then the rights will be sold to a FAANG or an open souce fork like libSQL will live on.

SQLite is public domain (as much as is legally possible). So there's no "rights" to "sell" except the trademark.

The testing suite is not open, which is one of the most important part of the project.

I assume they have written this extensive document with lots of details in response to two and a half decades of thousands of “why not rewrite in X?” questions they’ve had to endure.

(it’s from 2017)



Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

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

Search: