5 ms·
I think it's less about not wanting memory safety and more that compilation speeds are so time-wastingly abysmal that it's a few orders of magnitude more import
by moffkalast 3y ago
I think it's less about not wanting memory safety and more that compilation speeds are so time-wastingly abysmal that it's a few orders of magnitude more important to address.
The whole deal with interpreted languages was to avoid sitting there for a few minutes every time you make a god damn one letter change, with the unfortunate but usually acceptable trade-off of some execution speed.
- mxmlnkn 3y agoAnd the additional trade-off that some bugs are only noticed at runtime when that particular line is executed while it could have been noticed by the compiler of a strongly typed language. Pytype helps but at this point you have a static analyzer that potentially runs as slow as a compiler without the additional performance benefit.
- moffkalast 3y agoIdk as long as you can develop at speed I don't see why a static analyser that's a few times slower than compiling couldn't run on the latest commit overnight? More as a sonarqube type thing I suppose.
- josephg 3y agoThere’s no good reason for type checking to be super slow. I’m no fan of Go, but the language compiles insanely fast while being fully statically typed. As I understand it, C++’s slow compilation comes from the fact that it usually parses all of your header files n times instead of once. This isn’t a problem with static typing. It’s a problem with C++, and to a lesser extent C.
- aw1621107 3y ago> As I understand it, C++’s slow compilation comes from the fact that it usually parses all of your header files n times instead of once. That's one of the things that can slow compilation down but it's definitely not the only one. It helps that precompiled headers (and maybe modules?) can go a long way towards reducing and possibly eliminating these costs as well. I think some (most?) of the larger remaining costs revolve around template instantiation, especially it impacts link times as well due to the fact that the linker needs to do extra work to eliminate redundant instantiations.
- josephg 3y ago> due to the fact that the linker needs to do extra work to eliminate redundant instantiations. Yeah, I see this as another consequence of C++'s poor compilation model: - Compilation is slow because a template class in your header file gets compiled N times (maybe with precompiled headers). The compiler produces N object files filled with redundant code. - Then the linker is slow because it needs to parse all those object files, and filter out all the redundant code that you just wasted time generating. Its a bad design.
- aw1621107 3y agoI'm not sure I'd call the design "bad". At the very least it's a product of the design constraints, and I'm not sure there's an obviously better implementation without sacrificing something else. I think separate compilation and monomorphization are the biggest contributors, but I wouldn't be surprised if there was something I was forgetting. Somewhat related, there was some work in Rust about sharing monomorphized generics across crates, but it appears it was not a universal win at the time[0]. I'm not sure if anything has changed since that point, unfortunately, or if something similar could be applied to C++ somehow. [0]: https://github.com/rust-lang/rust/issues/47317#issuecomment-478894318 https://github.com/rust-lang/rust/issues/47317#issuecomment-...
- josephg 3y ago> I'm not sure I'd call the design "bad". At the very least it's a product of the design constraints, and I'm not sure there's an obviously better implementation without sacrificing something else. It was a product of the design constraints in the 70s when memory was expensive, and compilers couldn't store a whole program in memory during compilation. The problem C++ has now is that the preprocessor operates on the raw text of a header file (which is a relic from C). This means the same header file can generate totally different source code each time its included in your program. C++ can't change that behaviour without breaking backwards compatibility. So headers get parsed over and over again "just in case" - wasting time producing excess code that just gets stripped back out again by the linker. The way C++ works doesn't make any sense now that memory is so much cheaper. Go, C#, java, rust, zig - basically every compiled language younger than C++ compiles faster than C++ because these languages don't contain C++'s design mistake. Rust doesn't share monomorphized generics across crates, but at least each crate is compiled as a single compilation unit.
- bsder 3y ago> As I understand it, C++’s slow compilation comes from the fact that it usually parses all of your header files n times instead of once. Sort of. The primary issues are: 1) The C/C++ grammar is garbage. Note that every single modern language has grammatical constructs so that you can figure out what is "type" and what is "name" without parsing the universe. "typedef" makes that damn near impossible in C without parsing the universe, and C++ takes that to a whole new level of special. 2) C++ monomorphization You basically compile up your tempate for the universe of every type that works, and then you optimize down to the one you actually use. This means that you can wind up with M*N*O*P versions of a function of which you use only 1. That's a lot of extra work that simply gets thrown away. The monomorphization seems to be the biggest compile time problem. It's why Rust struggles with compile times while something like Zig blazes through things--both of those have modern grammars that don't suck.
- fluoridation 3y ago1. No, the grammar is not the issue per se. As you say, C has the same problem, and C code invariably compiles dozens of times faster than C++, and both Zig and Rust have modern grammars, but Zig compiles about as quickly as C and Rust is only somewhat faster than C++ (depending on features used). 2. This is incorrect. What's happening is that each template instantiation for a new set of template arguments requires reprocessing the template to check types and generate code, and also that is done per translation unit instead of per project. Each distinct template instantiation increases the compilation time a bit, much more than it takes to parse the use itself. That's why it's easy to have a small C++ source that takes several seconds to compile.
- bsder 3y ago> 1. No, the grammar is not the issue per se. As you say, C has the same problem, and C code invariably compiles dozens of times faster than C++, and both Zig and Rust have modern grammars, but Zig compiles about as quickly as C and Rust is only somewhat faster than C++ (depending on features used). Sorry, the C++ grammar is terrible. There are lots of things where C++ can't figure out whether something is a class or name or template or constructor call until looking way far down the chain. However, you are the first person I think I have ever heard claim that Rust is faster than C++. Rust is notoriously slow to compile. Zig generally compiles much faster than most C projects I've used. However, that is difficult to lay at the hands of C as a lot of those are the build system being obtuse.
- neonsunset 3y ago(one of the reasons Go compiles fast is its compiler is really bare bones, comparatively speaking it does very little in the optimization area vs what you would see out of .NET and JVM implementations, not even mentioning GCC or LLVM)
- UncleMeat 3y agoIt isn't just that, but there are a number of ways that templates can cause superlinear type checking behavior.
- JohnFen 3y agoI know I'm weird, but as long as I can compile individual units and link them to other already-compiled units then compilation speed is something I don't care about much at all.
- carlmr 3y agoThat's fine and dandy as long as you don't use C++ with templates and other stuff that needs 90% of the code to be in the headers. Any recompile triggers a lot of recompilation. And no, I can't change the code the other hundred devs are writing in my company. In C++ there is no individual units. In C it's somewhat plausible with some discipline.
- penguin_booze 3y ago> In C++ there is no individual units There's a still a notion of the compilation unit, which is the cpp file on which you invoke the compiler. Due to templates being prevalent in C++, included files contain the implementation as well; so any changes you make there lead to re-compiling a lot more compilation units than, for example, in C.
- carlmr 3y agoThat is kind of restating my point. There might be these translation units, but they're tightly coupled to all the other translation units, making them not very individual IMO.
- JohnFen 3y agoyes, that's why I used the disclaimer "as long as I can compile individual units and link them". The problem with C++ templates is accurate, and is one of the several reasons why I avoid using templates in my own C++ code. I don't have that freedom in the code I write for my employer, though. > In C++ there is no individual units. Yes, there are. Those unit boundaries are often blurred by other C++ features, but they do exist.