Live data from Hacker News

A Rust shaped hole

mnvr.in

51–60 of 319 posts

Re: A Rust shaped hole

#51
post #42

> 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,…

> 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!)

Re: A Rust shaped hole

#52
post #7

>To paraphrase Norvig's Latency numbers a programmer should know, if we imagine a computer that executes 1 CPU instruction every second, it would take it days to read from RAM. It's a detail, but this is a little bit off. RAM latency is roughly around ~100ns, CPUs average a couple instructions per cycle and a few cycles per ns. Then in the analogy, a stall on RAM is about a 10 minute wait; not quite as bad as losing…

In current machines, that's way off depending on how you choose to count "1 CPU instruction" for the metaphor.

Take Apple's latest laptops. They have 16 CPU cores, 12 of those clocking at 4.5 GHz and able to decode/dispath up to 10 instructions per cycle. 4 of those clocking at 2.6 GHz, I'm not sure about their decode/dispatch width but let's assume 10. Those decoder widths don't translate to that many instructions-per-cycle in practice, but let's roll with it because the order of magnitude is close enough.

If the instructions are just right, that's 824 instructions per nanosecond. Or, roughly a million times faster than the 6502 in the Apple-II! Computers really have got faster, and we haven't even counted all the cores yet.

Scaling those to one per second, a RAM fetch taking 100ns would scale to 82400 seconds, which 22.8 hours, just short of a day.

Fine, but we forgot about the 40 GPU cores and the 16 ANE cores! More instructions per ns!

Now we're definitely into "days".

For the purpose of the metaphor, perhaps we should also count the multiple lanes of each vector instruction on the CPU, and lanes on the GPU cores, as if thery were separate processing instructions.

One way to measure that, which seems fair and useful to me, is to look at TOPS instead - tera operations per second. How many floating-point calculations can the processor complex do per second? I wasn't able to find good figures for the Apple M4 Max as a whole, only the ANE component, for which 38 TOPS is claimed. For various reasons tt's reasonable to estimate the GPU is the same order of magnitude in TOPS on those chips.

If you count 38 TOPS as equivalent to "CPU instructions" in the metaphor, then scale those to 1 per second, a RAM fetch taking 100ns scales to a whopping 43.9 days on a current laptop!

Re: A Rust shaped hole

#53
post #9

I don't think you need an elaborate process of elimination when one of your axioms is "must manage memory manually".

I don't think you need an elaborate comment when one of your axioms is "must not read the post that you're responding to".

Re: A Rust shaped hole

#54
post #38

Wow, a lot of stuff in here surprises me. C definitely can/does have spooky at a distance. Just share a pointer to a resource with something else and enjoy the spooky modifications. Changes are local as long as you program that way, but sometimes it can be a bit not-obvious that this is happening. regarding redefining functions, what could the author mean? using global function pointers that get redefined? otherwise…

> Wow, a lot of stuff in here surprises me. C definitely can/does have spooky at a distance. Just share a pointer to a resource with something else and enjoy the spooky modifications. Changes are local as long as you program that way, but sometimes it can be a bit not-obvious that this is happening. I think the author means that the language constructs themselves have well-defined meanings, not that the semantics don…

Thanks for explaining what you think the author meant; i meant to reiterate that I was trying to actually understand as opposed to argue, but I forgot; I think sometimes "hey I don't get what you're saying because of reasons XYZ..." comes across as "I think you're wrong".

Composing monads is another one of those painful parts of haskell. I remember being so frustrated while learning Haskell that there was all of this "stuff" to learn to "use monads" but it seemd to not have anything to _do_ with `Monad`, and people told me what I needed to know was `Monad`. Someday I wanna write all that advice I wish I had received when learning Haskell. A _lot_ of it will be about dealing with general monad "stuff".

The thing that frustrated me in Rust coming from something like Ruby was how frequently I could not _do_ a very straightforward thing, because, for example, some function is a fnOnce instead of fnMulti, or the other way around, or whatever. Here's some of the experience from that time https://joelmccracken.github.io/entries/a-simple-web-app-in-.... It became clear to me eventually that some very minor changes in requirements could necessitate massive changes in how the whole data model is structured. Maybe eventually I'd get good enough at rust that this wouldn't be a huge issue, but I had no way of seeing how to get to that point from where I was.

In contrast, I can generally predict when some requirement is going to necessitate a big change in haskell: does it require a new side effect? if so, it may need a big change. If not, then it probably doesn't. But, I've found it surprisingly easy to make big changes from the nice type system.

I really don't get when rust folks claim "memory safety" like this; we've had garbage collection since 1959. Rust gives you memory safety with tight control over resource usage; memory safety is an advantage that Rust has over C or C++, but not over basically every other language people still talk about.

If you just clone/copy every data structure left and right, then you're at a _worse_ spot than with garbage collection/reference counting when it comes to memory usage. I _guess_ you are getting the ability to avoid GC pauses, but, why not use a reference counted language if that's the problem? copy/clone data all of the time can't be faster than the overhead from a reference counting, can it??

In haskell, I did find that once I understood the various pieces I needed to work with, actually solving problems (e.g. composing monads) is much easier. I don't generally have a hard time actually programming Haskell. All that effort is front-loaded though, and it can be hard to know exactly what you need to learn in order to understand some new unfamiliar thing.

Your preferring Rust over Haskell is totally fine BTW, I'm just trying to draw a distinction between something that's hard to _use_ vs something that's hard to _learn_. Many common languages are much harder to use IME; I feel like I have to think so hard all of the time about every line of code to make sure I'm not missing something, some important side effect that I don't know about that is happening at some function call. With Haskell, I can generally skim the code and find what's important quite quickly because of the type system.

I do plan to learn Rust at some point still whenever the planets align and I need to know something like it. Until then, there are so many other things that interest me, and not enough hours in the day. I still wonder if I have really missed out on some benefit from learning to think more about data ownership in programs.

Re: A Rust shaped hole

#55
post #33
post #17

Earlier quoted context omitted.

> Memory management was indeed the sore sticking point, why Rust hadn't appealed to me earlier. The author doesn't want manual memory management, but still decides to go with Rust.

Their rubric is literally just 3 items: "native compilation", "abstractions", and "manual memory management". Had they put that little table at the front of the article, there wouldn't even need to be an article: the table basically says "I'm going to use Rust". That's fine!

The author really doesn't want to do manual memory management. The table is there to summarize things discussed, but he never says he wants to do manual memory management. I just went back and checked. If you do find something that indicates that, I'd appreciate you pointing it out to me, because idgi

Re: A Rust shaped hole

#56
post #45
post #24

Earlier quoted context omitted.

You’re right that Rust is a ball of complication. I am a fan of Rust but it’s definitely a terse language. However there are definitely signs that they have thought about making it as readable as possible (by omitting implicit things unless they’re overwritten, like lifetimes). I’m reminded also about a passage in a programming book I once read about “the right level of abstraction”. The best level of abstraction is…

I do not really agree with respect to C. I often have to deal with C code written by unexperienced programmers. It is always relatively easy to refactor it step by step. For C++ this is much more painful because all the tools invented to make the code look concise make it extremely hard to follow and change. From the feature set, I would say that Rust is the same (but I have no experience refactoring Rust code).

In personal experience, the much stronger and composite type model in Rust makes it easier to refactor.

Adding features in particular is a breeze and automatically the compiler/language will track for you the places that use only old set of traits.

Tooling is still newer though and needs polish. Generic handling is interesting at times and there are related missing features for that in the language, vis a vis specializations in particular.

Basic concurrency handling is also quite different in Rust than other languages, but thus usually safer.

Re: A Rust shaped hole

#57
post #20

It is a bit unclear to me why somebody who rejects C++ because "I once spent an entire year in the heaven of C++, walking around in a glorious daze of std::vector and RAII, before one day snapping out of it and realizing that I was just spawning complexity that is unrelated to the problem at hand." (which I can absolutely agree with!) is picking Rust from all options. If there is a language that can rival C++ in term…

I've seen this idea from a few people and I don't get it at all. Rust is certainly not the simplest language you'll run into, but C++ is incredibly baroque, they're not really comparable on this axis. One difference which is already important and I think will grow only more important over time is that Rust's Editions give it permission to go back and fix things, so it does - where in C++ it's like venturing into a ho…

C++'s complexity is coming from how eager it is to let you shoot yourself in the foot. Rust will make you sweat blood to prove the bird in the sky you're shooting at is really not your own foot.

Re: A Rust shaped hole

#58
post #38

Earlier quoted context omitted.

> Wow, a lot of stuff in here surprises me. C definitely can/does have spooky at a distance. Just share a pointer to a resource with something else and enjoy the spooky modifications. Changes are local as long as you program that way, but sometimes it can be a bit not-obvious that this is happening. I think the author means that the language constructs themselves have well-defined meanings, not that the semantics don…

Thanks for explaining what you think the author meant; i meant to reiterate that I was trying to actually understand as opposed to argue, but I forgot; I think sometimes "hey I don't get what you're saying because of reasons XYZ..." comes across as "I think you're wrong". Composing monads is another one of those painful parts of haskell. I remember being so frustrated while learning Haskell that there was all of this…

Yep I feel you. Thanks!

Re: A Rust shaped hole

#59
post #28

If anyone reads this and like me fears the difficulty and complexity of rust, but still wants a language that is competitive in performance, works for system level programming as well as something more general purpose definitely give Swift a go. Over the last year I’ve started to write every new project using it. On windows, on linux and mac. It is honestly a wonderful language to work with. Its mature, well designed…

My major problem with Swift was its error messaging. “Error: -2.” Okay, well, I suppose I’ll attach a debugger and… it’s of absolutely no help, since it crashes internally to some function and I can’t get out a stacktrace.

Function calling is irksome, with implicit parameters and mandatory parameters vaguely mixing? And the typing is appalling - there are multiple bottom types with implicit narrowing casts, one of them being NSObject, so if you’re doing any work with the Apple APIs you end up with a mess.

We got it right with Java and Rust; C++ does a passable job; why Swift had to be as incomprehensible as typescript, I cannot fathom.

Re: A Rust shaped hole

#60
post #42

> 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,…

> 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 sou…

> 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.

Post reply on HN