5 ms·
> And the very point of writing a native program in the first place is to make it feel solid. What does that mean, and what is it about native programs (i.e. p
by pron 1y ago
> And the very point of writing a native program in the first place is to make it feel solid.
What does that mean, and what is it about native programs (i.e. programs AOT-compiled to machine code) that makes them feel solid? BTW, such programs are often more, not less, sensitive to OS changes.
> realizing that I was just spawning complexity that is unrelated to the problem at hand
Wait till you use Rust for a while, then (you should try, though, if the language interests you).
For me, the benefit of languages with manual memory management is the significantly lower memory footprint (speed is no longer an issue; if you think Haskell and Go are good enough, try Java, which is faster). But this comes at a price. Manual memory management means, by necessity, a lower level of abstraction (i.e. the same abstraction can cover fewer implementations). The price is usually paid not when writing the first version, but when evolving the codebase over years. Sometimes this price is worth it, but it's there, and it's not small. That's why I only reach for low level languages when I absolutely must.
- Expurple 1y ago> such programs are often more, not less, sensitive to OS changes. You may be technically correct that they are more sensitive to the kernel interface changes. But the point is that native, static binaries depend only on the kernel interface, while the other programs also depend on the language runtime that's installed on that OS. Typical Python programs even depend on the libraries being installed separately (in source form!)
- pron 1y ago> But the point is that native, static binaries depend only on the kernel interface Many binaries also depend on shared libraries. > while the other programs also depend on the language runtime that's installed on that OS You can (and probably should) embed the runtime and all dependencies in the program (as is easily done in Java). The runtime then makes responding to OS selection/changes easier (e.g. musl vs glibc), or avoids less stable OS APIs to begin with.
- Expurple 1y ago> Many binaries also depend on shared libraries. Yeah, and those are also the opposite of "solid" :) That's why I qualified with "static". I'm so glad that Go and Rust promote static linking as the default (ignoring glibc). > You can (and probably should) embed the runtime and all dependencies in the program (as is easily done in Java). Congrats to the Java team and users, then. That makes it similar to the Go approach to binaries and the runtime, which I approve
- pron 1y ago> Yeah, and those are also the opposite of "solid" :) So if that's what the author meant by "solid", i.e. few environmental dependencies, then it's not really about "native" or not, but about how the language/runtime is designed. Languages that started out as "scripting" languages often do rely on the environment a lot, but that's not how, say, Java or .NET work. > I'm so glad that Go and Rust promote static linking as the default (ignoring glibc). That doesn't work so well (and so usually not done) once you have a GUI, although I guess you consider the GUI to be part of the kernel.
- pjmlp 1y agoEven C has a runtime, even if tiny one.
- Expurple 1y agoI meant a runtime that has to be installed separately. It's possible to statically link a C runtime if you use musl, for example
- pjmlp 1y agoYou mean like it happens on many OSes that aren't GNU/Linux? A language runtime remains one, independently on how it was linked into the binary. A language runtime are the set of operations that support the language semantics, which in C's case are everything that happens before main(), threading support (since C11), floating point emulation (if needed), execution hooks for running code before and after main(), delayed linking, and possibly more, depending on the compiler specific extensions.
- Expurple 1y agoYou're being pedantic and trying to argue as if I misunderstand language runtimes and am speaking against language runtimes in general. That's not true. I qualified "the language runtime that's installed on that OS" from the beginning.
- Mawr 1y ago> For me, the benefit of languages with manual memory management is the significantly lower memory footprint (speed is no longer an issue; if you think Haskell and Go are good enough, try Java, which is faster). ... what? Speed is no longer an issue? Haskell and Go? ??? How'd we go from manual memory management languages to Haskell and Go and then somehow to Java? Gotta plug that <my favorite language> somehow I guess... It seems to me you have a deep misunderstanding of performance. If one program is 5% faster than another but at 100x memory cost, that program is not actually more performant. It just traded all possible memory for any and all speed gain. What a horrible tradeoff. This thinking is typical in Java land [1]. You see: 8% better performance. I see: 28x the memory usage. In other words, had the Rust program been designed with the same insane memory allowance in mind as the Java program, it'd wipe the floor with it. [1]: https://old.reddit.com/r/java/comments/n75pa0/java_beats_out_c_rust_c_and_golang_in_grpc/ https://old.reddit.com/r/java/comments/n75pa0/java_beats_out...
- pron 1y ago> How'd we go from manual memory management languages to Haskell and Go Because that's what's discussed in the article, which discusses Go and Haskell specifically. > In other words, had the Rust program been designed with the same insane memory allowance in mind as the Java program, it'd wipe the floor with it. No, it wouldn't (I've worked with C and C++ for almost 30 years - including on embedded and safety-critical hard realtime software - with Java for over 20, and I work on the HotSpot VM). That's because tracing GCs convert memory to speed, but that's not the case for other memory management techniques. To see why, look at a highly simplified view of tracing collectors (modern collectors don't quite work like that, but the idea generalises): When the heap is exhausted, live objects are traced and compacted to the "top" of the heap. I.e. the cost of each collection is only dependent on the working set, i.e. the size of objects that are still live. Because the working set is more-or-less a constant for a given program under a given workload, the larger the heap the less frequent the collections (each of a constant cost), and so the cost of memory management with a tracing collector goes to zero as the heap size grows. There are details in the actual implementations that are worse and others that are better than this idealised description, but the point is that tracing garbage collection is a mechanism that is very effectively converts RAM to speed as its cost scales with the ratio working-set/heap-size. This is not the case for manual memory management or for primitive ref-counting GCs. Of course, even when memory management is zero, there are still computational costs, but Java compiles to the same machine instructions as C with that kind of work (with some important caveats in certain situations that will soon be gone). It is true that even outside those specific areas, you can, with significant additional effort, get a C program (or a program in any other low-level language) to be faster than a Java program but that's due to the availability of micro-optimisations (that we don't want to offer in Java as to not to complicate the language or make it too dependent on a particular hardware/OS architecture), but that effect isn't large.
- ignoramous 1y ago> What does that mean, and what is it about native programs (i.e. programs AOT-compiled to machine code) that makes them feel solid? BTW, such programs are often more, not less, sensitive to OS changes TFA also concludes Since I want native code ... I think by "solid" they mean as close to metal as possible, because, as you suggest, one can go "native" with AOT. With JS/TS (languages TFA prefers), I'm not sure how far WASM's AOT will take you ... Go (the other language TFA prefers) even has PGO now on top of "AOT".
- pron 1y ago> I think by "solid" they mean as close to metal as possible A JIT compiler compiles your code to machine code just as an AOT compiler does, so I don't think that's what's meant here (and they don't mean the level of the source code because they consider Haskell to be "native").
- ignoramous 1y agoHm. TFA has the terms confused or uses them inconsistently, I guess.
- vips7L 1y ago> What does that mean, and what is it about native programs (i.e. programs AOT-compiled to machine code) that makes them feel solid? Im a little late here and as a Java user most of the time people tell me: 1. They just want to ship a binary. Most are not aware of Jpackage, but correct me if I’m wrong that just makes installers right? I’m hopeful that the “hermetic” work from Leyden will help here. 2. They frequently complain about Java’s memory usage, but don’t really understand how setting the heap size works and what the defaults are. I’m also hopeful that ZGC’s automatic heap sizing will solve this. With those two features I think the view of Java will change, as long as there is good build tooling for them. It would be nice to make that the default, but that would break many builds.