Mojo is much faster than Rust, but slower than Go. I don't have much experience with Zig.
Mojo is designed to be very fast to compile, so many decisions were made to keep the core language simple, one example is in `where` clause, the checking there happens entirely in the parser. It can be stupid in situations where other languages are smart, and make you explicitly do checks that could be inferred in other languages. But on the other hand, it can be very fast since it doesn't have to do all the complicated resolving.
Another reason is how LLVM is used, Modular found ways to parralize LLVM code generation by introducing novel techniques that'll likely become a lot more popular with other languages.
I think they had a good dive here
https://www.youtube.com/watch?v=SEwTjZvy8vw
The gist is that MLIR (unlike LLVM) was designed to be multithreaded so the whole stack above LLVM IR is parallel, and then LLVM is used as a per-function codegen tool in parallel, so although LLVM itself is single threaded there are multiple seperate contexts of it. also I think they wrote their own linker.
Well, LLVM itself is still single-threaded; they just designed Mojo's compiler in such a way that the code generation part can be parallelised, which is something you can do if you understand LLVM from top to bottom. As far as I can see, no other production-grade LLVM consumer has been able to make it parallel; the single-threaded nature remains a major performance bottleneck.
> Modular found ways to parralize LLVM code generation by introducing novel techniques
> The novelty is in parrelizing LLVM, which is traditionally a single-thread code generator.
You said they parallelized LLVM with novel techniques, but then claimed the novelty is the very act of parallelizing it. That's circular, you still haven't explained what are the novel techniques?
Here is a presentation talking about the parallelization techniques, I skipped to the relevant part but the entire presentation is helpful in understanding how Mojo's compiler works: https://youtu.be/yuSBEXkjfEA?t=813&si=MlB7IsBDsj3o-PTX
From experience, Zig compile times are at least as fast as Go for debug builds that don't need to do linking with C libraries, etc. It does have to use LLVM for release builds however which is a lot slower.
Mojo compiles with O2 by default, it is similar to Go here. Release build is the default, debug is something you opt into. It is still very fast nonetheless
> It’s the language behind Kubernetes admission policies, Envoy’s RBAC rules, Google Cloud IAM conditions, and gRPC’s protovalidate
Very small nitpick, but AFAIK protovalidate comes from Buf, not Google. While protovalidate DOES work with gRPC via backward compatibility (but also Buf's ConnectRPC), saying "gRPC's protovalidate" probably makes people think it came from Google.
Disclaimer: I have no affiliation with either Buf or Google.
Very fair point that protovalidate comes from Buf, not Google.
But it's worth noting that protovalidate can also work with plain gRPC - it's an independent library, and anyone can write a gRPC interceptor that uses it. Here's a community-supported example in Go: https://pkg.go.dev/github.com/grpc-ecosystem/go-grpc-middlew...
I think its more important that protovalidate is not affiliated with grpc in any way. One needs a custom middleware to implement the protovalidate rules for your language used.
Checked exceptions were actually the "right way" to do exceptions (if there is such a thing), the problem was just that developers hated them, but I think that draws the wrong conclusion. That tells me their syntax/usage was seen as too much forced boiler plate making code unwieldy, not that they didn't have benefits for correctness (something often not appreciated until years later).
Unchecked exceptions lead to unhandled exceptions at runtime. We've all seen screens with Java programs running with tons of exceptions in the log, or worse, that crash with unhandled exceptions. This is the result of the unchecked exceptions mess, which is why I won't use languages that use them for routine error handling for anything more than trivial programs.
> developers hated them, but I think that draws the wrong conclusion
Exception handling is just annoying from a syntax perspective. Also checked Exceptions have the problem that they bubble up types that a different layer shouldn’t even be aware of due to exception chaining (cause of a cause etc), unless you carefully re-throw them, which nobody did.
Lower ceremony errors are just better to deal with.
> When I write new code in Fil-C, I just lean into the GC all the way, which makes programming in C and C++ so much nicer. I don’t ref count, I don’t use smart pointers, I don’t free and I don’t delete. It makes these languages so much nicer!
Sure, GC's are nice which is why so many langs have them, but that removes the deterministic allocation performance which most C/C++ programmers want (and many times need). Why not just use something like Go then? You have a much richer stdlib available out of the box.
I don't have a horse in this race, but to me this makes GPT-5.6 Sol Max look better. It is about half the cost for nearly the exact same performance. It just goes to show how expensive Fable really is when Opus 5 is still this expensive relative to GPT 5.6.
I've always thought it odd that we don't use ECC as a standard on all computers. I think people really downplay the impact of memory issues. They can be devastating, especially over time. They will slowly corrupt your file system, documents, binary files, code, everything. You notice when things like your compressed files start giving CRC/checksum errors or your downloads don't match SHA-512. You are then left with this "icky" feeling. What parts of your work are compromised? Obviously this is far worse with things like binary files and structures than those built on readable text. I have normally just rebuilt my system from scratch in these instances (after fixing the issue of course), but not all our files are replaceable, and you forever and always might have corrupted files you are unaware of that got written during this time. You might not find them until years later.
This fact comes mostly down to Intel choosing to use ECC support for market segmentation. If you care about your data, you buy the server chips that cost double what the desktop chips with ECC support lasered out cost.
You need the ECC RAM for your filesystem with integrity only then can you be confident you aren't going to be familiar with a concept like this happening 9 or 10 times.
Systems with "consumer amounts of RAM" are often run with what you might call "consumer amounts of sysadmin knowledge" and not notice the errors.
One time I took a working workstation from my home to my parents' home to give them. When I booted it up it gave a lot of strange kernel errors which I googled and discovered were reports of ECC correction. I reseated all DIMMs and it was fine. If that gave errors a few times a year instead of thousands of times on the first boot I wouldn't have noticed.
Sometimes I get a few per day. I only know that because my Linux kernel configuration happens to have whatever settings enabled to get them reported in dmesg.
...No? Faulty storage will almost always show up as I/O errors, modern storage generally doesn't want to send a block of data to the CPU if there is an error in it. If your bits are flipping, chances are it's RAM and not storage. Your storage already has ECC.
Some crappy flash drives might not do this, though. Seems to behave like a floppy disk at times.
The majority of storage errors I've seen since using BTRFS and ZFS everywhere have shown up only as the storage returning corrupt data and claiming it to be good. I've seen drives and SSDs return dozens of errors per month for months on end without any SAS or SATA errors or any SMART errors.
I've seen this in DC grade SSDs, NAS grade hard drives, and SSDs sold in high end laptops.
AMD has historically supported ECC on all it's chips. That's changed in the last gen or two where some of the lower end APUs don't support ECC but the Pro APUs do and all the ryzen stuff (5, 7, 9) support ECC if you get a motherboard that supports it.
Laptops are pretty much unavailable with ECC especially with soldered memory becoming common. On the desktop side, there's multiple motherboards that explicitly note that they support ECC memory. AsRock and Asus both include ECC memory on their QVL lists. I'm not sure how many ITX boards support ECC though so getting it on something that's not a tower might be tough.
But it's definitely possible, I have an ECC setup on my desktop and it's caught a memory error or two over the last few years.
It's hard to get more ECC guaranteed than the mobo manufacturer having ECC ram on their QVL (qualified vendor list) for the motherboard and indicating that ECC is supported in the specs. I suppose you can just get a complete workstation with ECC from HP or DELL and that'll be guaranteed to work but you'll certainly pay a hefty premium for that.
Sort of, often there's workstation chips, like the xeon E3, which is a warmed over desktop chip ... with ECC. Price difference when I bought was $20 CHEAPER for the CPU (at the cost of 100 MHz or so). I did pay $50 more for a motherboard and 10-15% more for ram.
It's very important IMO that the ECC failures get reported and logged. The DDR5 on-die correction is not true ECC; the correction happens silently and is not reported or logged.
I have DDR4 ECC memory on my home server. Last week I got a crash... logged into my BMC and saw that one of the modules had "uncorrectable ECC". Then I looked over the logs and saw about 200 or so errors for the exact same module but "correctable ECC". They would happen over a short period of time followed by 4 months of no issues. Thanks to ECC and logging it was quick and easy to catch the issue right on the first occurrence, no data corruption. I have 4 modules in total, and only this one was having issues, so clearly a hardware fault.
Now imagine it was a regular non-ECC memory. There won’t be any crashes due to uncorrectable ECC; another 3 or more years would pass before corruption would become frequent enough for the issue to be noticed. At that point, there would be hundreds of corrupted files.
> I think people really downplay the impact of memory issues.
I don't think so. I've got my important data backed up on offline HDDs and SSDs and my most important data lives on a RAID system (ZFS) on a Xeon with ECC RAM but...
... there are simply a huge lot of checks everywhere making it so that bit flips on non ECC systems simply aren't that serious.
We live in a world of checksums and retries at every layer and distributed systems that are just about everywhere.
I went on for decades without ECC memory and nothing bad happened. Yes, I had the occasional bitflips. I did found out faulty mem using memtest (or weirder stuff, like some RAM stick identical to the other three, same chip everywhere, same sticker: but reported by memstick as being some other mem).
But I don't think that the "one bitflip cascading into corruption of your life's data" is something necessary to freak about.
It's not happening. Never happened to anyone.
If you (or other) are really concerned, you can use my scheme:
- dsc09874.jpg
becomes:
- dsc09874-b3-73b0835221.jpg
which means "that file's Blake3 checksum begins with 73b0835221" (use something else than Blake3 if so desired).
About 1/3rd of all my files are "tagged" this way, directly in the filename: this survive different medium and different OSes.
I then have my custom rsync backuping script doing a dry-run and warning me in a "stop the world!" fashion if it detects a bogus checksum (either on the source or on the dest: during the dry-run any modification to a file with a checksum is verified and any checksum mismatch means "stop the world").
I then also have, in addition to my custom backuping script, another script that allows me to verify either all files with that naming convention or a percentage I pick of those files (so basically some random sampling).
It's not mutually exclusive with ZFS / a system with ECC RAM.
> but not all our files are replaceable, and you forever and always might have corrupted files you are unaware of that got written during this time
I hear you but... How much do you really need, years later, a file that you haven't needed for years? That one file is unlikely to be a big loss.
Now I'm not saying you're wrong: I ended up with my naming scheme (appending a partial cryptographic hash to the filename) after finding a series of about 20 pictures that were corrupted. And on all the backups I first checked, they were also corrupted. I ended up finding a very old data CD on which that series of .jpg files were fine. And I decided "never again, I want such SNAFU to be detected in the future".
But truth is: with 40 000 pictures, life without those 20 pictures would still be fine.
Honest caveat, none of us have really used SurveyJS, so correct me if I'm off.
Biggest overlap is the JSON-schema idea, which is our first point here:
1. A JSON engine. The form is governed by a JSON definition that you can store in a DB, version, diff, or generate it with LLMs as a validated JSON.
2. We provide also 28 headless components (and growing) that you can style with CSS variables. We offer APIs so you can drop in Material, Shoelace, or your own components.
3. A DX typed authoring layer on top to write forms programmatically, that generates JSON. So you don't have to write it.
4. The same definition can render the UI components in React, Angular, Vue, Lit, or Vanilla JS.
5. We also have a deterministic MCP that has tools for to validate the model's output, generate JSONs or code, and ensure that the definition returned by the LLM is always valid.
If you don't even know what tools exist in the ecosystem, how can you possibly know that your tool even scratches a new itch ... let alone "creates a new paradigm"?
> why do languages like Crystal and D still use Boehm?
Languages use Boehm for exactly one reason: it is easy to shim into an otherwise manual memory system (it was designed for use in C/C++). I mean no respect to its authors, but using Boehm in production is the worst of all worlds: slow allocations (free list allocator), poor cache locality, and not precise (so you can expect memory leaks). If you are going to do a GC language you want: 1) precise 2) bump allocator 3) compacting collector 4) generations. Essentially you want to allocate fast, only touch live objects (most objects die young), compact them for locality, and only process objects each cycle of similar age. There is a huge amount of engineering that goes into a state of the art collector, but those are the basics.
This is all true but is a somewhat Java-flavoured perspective i.e. generations ties you into a moving collector, which ties you into barriers and complicates FFI, which is not always the right tradeoff.
A non-fragmenting allocator goes a long way to alleviating the need for compactions too.
Not necessarily Java-flavored, but internally vs externally focused, yes. More difficult FFI assuming that is the exception not the rule, and that the language itself takes precedence. Write barriers are also not a given if using segmented heaps. Many ways to do this and no single right way. Memory allocation scheme isn't something that is just bolted on, but needs to be aligned to the rest of the language. For example, Java needs such fast allocations and good GC because it does almost no inline allocation whatsoever, so without the best GC on the planet, it would be a lot slower than it is. Contrast this with Go, which has a solid amount of inline allocations, and hence, can get by with a much slower allocator (~3-4x slower by my measurements) and a more basic mark-sweep allocator since the memory pressure is solidly less.
1) Induces a large performance penalty
2) Introduces a GC into C code bases (higher memory requirements, performance profile changes)
3) Is x86-64 only atm I believe
An idiomatic Rust port would have none of these issues, so it would be more a stop gap measure than a long term strategy.