Hacker News new | ask | show | jobs
by diffxx 740 days ago
> One of the interesting tradeoffs in programming languages is compile speed vs everything else.

Yes, but I don't think that compile speed has really been pushed aggressively enough to properly weigh this tradeoff. For me, compilation speed is the #1 most important priority. Static type checking is #2, significantly below #1 and everything else I consider low priority.

Nothing breaks my flow like waiting for compilation. With a sufficiently fast compiler (and Go is not fast enough for me), you can run it on every keystroke and get realtime feedback on your code. Now that I have had this experience for a while, I have completely lost interest in any language that cannot provide it no matter how nice their other features are.

3 comments

I think this is a false choice. It comes from the way we design compilers today.

When you recompile your program, usually a tiny portion of the lines of code have actually changed. So almost all the work the compiler does is identical to the previous time it compiled. But, we write compilers and linkers as batch programs that redo all the compilation work from scratch every time.

This is quite silly. Surely it’s possible to make a compiler that takes time proportional to how much of my code has changed, not how large the program is in total. “Oh I see you changed these 3 functions. We’ll recompile them and patch the binary by swapping those functions out with the new versions.” “Oh this struct layout changed - these 20 other places need to be updated”. But the whole rest of my program is left as it was.

I don’t mind if the binary is larger and less efficient while developing, so long as I can later switch to release mode and build the program for .. well, releasing. With a properly incremental compiler, we should be able to compile small changes into our software more or less instantly. Even in complex languages like Rust.

> But, we write compilers and linkers as batch programs that redo all the compilation work from scratch every time.

I don't think that there are that many production level compilers that don't perform the kind of caching that you're advocating for. Part of them problem is what the language semantics are. https://www.pingcap.com/blog/rust-huge-compilation-units/ gives an example of this.

> Surely it’s possible to make a compiler that takes time proportional to how much of my code has changed, not how large the program is in total.

Language design also affects what can be done. For example Rust relies a lot on monomorphisation, which in turn makes much harder (not necessarily impossible) to do in-place patching, but a language like Java or Swift, where a lot of checks can be relegated to runtime, it becomesuch easier to do that kind of patching.

I think that there's a lot left to be done to get closer to what you want, but changing a compiler that has users in such an extensive way is a bit like changing the engine of a plane while it's flying.

Yes, rust has an incremental compilation mode that is definitely faster than compiling the whole program from scratch. But linking is still done from scratch every time, and that gets pretty slow with big programs.

I agree that it would be a lot of work to retrofit llvm like this. But personally I think that effort would be well worth it. Maybe the place to start is the linker.

You're in good company: multiple people want to experiment with taking ownership of the linking and codegen steps to enable this kind of behavior. I would be more than happy to see that happen. I feel that the problem is a project of that magnitude requires a benefactor for a small group of people to work completely dedicated to it for maybe 2 years. Those don't come along often. The alternative is that these projects don't happen, lose steam or take a really long time.
Given that VC++ does incremental linking, it seems to be the usual care of having someone caring enough to sort it out.
That's called incremental compilation and is fully supported by languages like Java or Kotlin. The JVM also supports this, being able to recompile methods on the fly whilst the program runs. And the IDE plugins for these types of languages are actually "presentation compilers". They do all the work of compiling and type checking, except for code emission, and they run fast enough to run continuously in the background on every keystroke.
Not only, some C++ compilers like VC++, Eiffel, CLR, Common Lisp,...

As addendum.

Agreed. For example, Julia (which is a compiled language) has a package called Revise, which provides incremental compilation. A cold start on a package / project / script will take awhile, and even when dependencies are precompiled, but the code you're working on is not, REPL startup takes noticeable amounts of time.

But once you have your REPL prompt, it's just: edit code, test it. Revise figures out what needs recompiling and does it for you. There are some limitations, most notably, any redefinition of a struct requires a reboot, but it's a great experience.

A lot of the current work going into the Zig compiler is to greatly increase the compile time of debug builds, by cutting the LLVM dependency, and then add incremental compilation. I'm looking forward to the fruits of that labor; I don't like to wait.

Is it baked in as the main mode yet? Or as an option to juliac?
s/increase/decrease
> Surely it’s possible to make a compiler that takes time proportional to how much of my code has changed [...]

My understanding is that this is how Eclipse's Java compiler works, but I'm not positive.

> Nothing breaks my flow like waiting for compilation. With a sufficiently fast compiler (and Go is not fast enough for me), you can run it on every keystroke and get realtime feedback on your code.

I already get fast feedback on my code inlined in my editor, and for most languages it only takes 1-2 seconds after I finish typing to update (much longer for Rust, of course). I've never personally found that those 1-2 seconds are a barrier, since I type way faster than I can think anyway.

By the time I've finished typing and am ready to evaluate what I've written, the error highlighting has already popped up letting me know what's wrong.

Yeah even with a large C++ codebase, any decent IDE will flag errors very quickly in real time. I dunno, I've never found that waiting a minute to run a test or whatever is particularly detrimental to my workflow.

I understand the benefits of super fast iteration if you're tweaking a GUI layout or something, but for the most part I'd prioritize many many other features first.

Fast compilation + unit tests allows me to quickly check if I broke a lot more stuff than IDE local checks.
>With a sufficiently fast compiler (and Go is not fast enough for me), you can run it on every keystroke and get realtime feedback on your code.

What language are you using?