Join the discussion
Write your take first — we'll ask for email only when you're ready to publish.
- Hacker News
- Off-topic, but I seriously dislike the syntax of Rust. It is chaotic and mind-boggling to me. See the "insert" function.
Good post though.
by johnisgood - I find the short type names for integers and float hard to read. Somehow the size of the type is more important than if it is a signed integer, unsigned integer or a floating point number.
Using Vec for arrays is also annoying, repeating the mistake from C++.
by neonz80 - It really reads quite simply once you're familiar with the language. You only see chaos because there are none of the semantic hooks you'd get from experienceby mpalmer
- tbh it's bit boring to get stuck on aesthetic of writing up something. It's a bit nauseous to see how this place is hostile to rust for no reason other than "it's not pretty". It's a joke at this point we could make caricature of HN viewpoint on rust. We get it, you don't like it.by 6r17
- The first statement defines a closure. The second is an if-let statement. It's not chaotic, you're just unfamiliar with the syntax.
I actually find the Rust syntax very natural, more than C in some areas.
by Levitating - It’s promises make me interested, but the syntax is my main turnoff. I am a Go person, and I think what brings people to go is the opposite of what brings people to Rust. I am willing to sacrifice some memory safety (because I maybe naively think I can manage to write software without many memory bugs) for the simplicity and dev experience that Go offers.by figassis
- It takes at most a week to get used to just about any syntax. It should absolutely never be a reason not to try a new language. That said, it would be lovely if Rust had a more ML-like, rather than C-like, syntax (being originally inspired by O’Caml), but that would likely not help attract devs in the intended target audience!
The insert function, for what it’s worth, has nonstandard formatting; the de facto standard rustfmt tool would use more newlines, making it clearer and less dense. The function also uses a couple of syntactic features like `if let`, which may seem unfamiliar at first but become second nature in a few days at most.
by Sharlin - as a beginner rust programmer, I agree. it takes me way longer to parse someone else's rust code than it does for me to read C or C++, even though I have about the same amount of experience with them. in that example, I had to look up what "if let Err() =" does, because it's not intuitive to me. it seems like every time I read rust code, I have to learn about some strange feature that's probably convenient when you know it, but there's a billion of them and they add up to hard to read code until you've spent tons and tons of time with rust. it's just so much to memorize compared to other languages.by ikkun
- This point has been litigated to death. Read this here: https://matklad.github.io/2023/01/26/rusts-ugly-syntax.html
Almost everything that people think is ugly about Rust's syntax exists for very specific reasons. Most of the time, imo Rust made a good decision, and is just making something explicit.
Some things take time to get used to (e.g. if let), but for most people that's less an issue of syntax, and more an issue of not understanding a powerful feature (e.g. pattern matching deconstructions).
by Mond_ - -O3 -march=haswell
The second one is your problem. Haswell is 15 years old now. Almost nobody owns a CPU that old. -O3 makes a lot of architecture-dependent decisions, and tying yourself to an antique architecture gives you very bad results.
by pclmulqdq - This era of CPUs has held up surprisingly well. I built an Ivy Bridge desktop in 2012 that still sees daily productivity use (albeit with an NVMe and RAM upgrade).by ericpauley
- I do. Had to replace the plastics of the laptop and the screen's definition is unacceptable but with Linux and a SSD it's still fine for basic computer usage. Not my daily driver but kept it as a daily drivers for 10 years.by cassepipe
- The default is an even older instruction set. Maybe you meant to suggest -march native ?by wffurr
- Not as old but I am still typing this on a MacBook Pro Early 2015 with a Broadwell CPU. It is doing pretty well with Chrome and Firefox, not so much with Safari.by ksec
- My desktop computer is a Sandy Bridge from 2011. I still haven't seen any compelling reason to upgrade.by mgaunard
- The author gives a godbolt link. It takes 5 minutes to add two compilers on raptorlake and see that it gives the same result.
https://godbolt.org/z/oof145zjb
So no, Haswell is not the problem. LLVM just doesn't know about the dependency thing.
by arthur2e5 - Great post.
I wonder whether profile-guided optimization would have led LLVM to select a better (or worse) decision.
by anematode - While working on my game, I tried implementing a custom priority queue.
It ended up being > 2x faster in debug build, but 2x-5x slower in the release build (??!!?) [1]. I haven't learned much about compilers/"lower level" C++, so I moved on at that point.
How it worked:
1.) The P.Q. created a vector and resized it to known bounds.
2.) The P.Q. kept tract of and updated the "active sorting range" each time an element was inserted or popped.
2B.) So each time an element is added, it uses the closest unused vector element and updates the ".end" range to sort
2C.) Each time an element was removed, it updated the ".start" range
3.) In theory this should have saved reallocation overhead.
[1] I believe Visual Studio uses -O0 for debug, and -O2 for release.
by YesBox - And this is why you go and look at the assembly in godbolt to see wtf is going on.by FuckButtons
- I'm curious what you did with the "active sorting range" after a push/pop event. Since it's a vector underneath, I don't see any option other than to sort the entire range after each event, O(N). This would surely destroy performance, right?by shihab
- These kinds of things are really interesting, and a good example of the importance of performance testing in optimized builds. I encountered something similar and realized the issue was different sizes of structures in debug vs release which ended up causing the CPU cache lines to overlap and invalidate. Though that sounds unlikely here.by adzm
- It seems to me that if there is one way that is always faster it would hardly deserve a secret setting, it should be the default?by fifilura
- What secret setting is that? Whether taking a branch or a conditional move is faster or not depends a lot on the code and the data it's being run on so it's not easy to say up front which one is always faster.by mpyne
- As a denser gas, Ozone would have greater friction getting through small pores, so that would be one example?
- I love these type of comments! Thank you.by zippyman55
- I thought this would be an article about how ozone is heavier than oxygen and the molecules move slower or something.
I found that surprising, but not as surprising as suddenly reading about Rust!
by FredPret - Hey! I actually appreciate this kind of HN humor. As in, when you pretend to read the title badly.by arthur2e5
- Nice read. Last week I wrote a blog post about two noteworthy cases of O3 being slower than O2 in C++: https://barish.me/blog/cpp-o3-slower/
- In the branchy function, id is only compared if distance is equal, and since distance is a random float, this almost never happens and the corresponding branch is nearly perfectly predicted. The branchless function always compares both id and distance, effectively doing twice the work. It's only part of the reason why there's a 2x performance difference, but I thought it was interesting.
I really don't know how LLVM picks between branches or conditional moves, but my guess is that it doesn't assume that float equality is any less likely than other conditions, and some optimization pass in O3 turns unpredictable branches into conditional moves. I base this on the fact that adding std::hint::unlikely to the "equal" branch produces the same assembly for the function in both modes.
https://godbolt.org/z/erGPKaPcx
Whether it's safe to assume in general that float equality is unlikely for the purpose of program optimization, I'll leave to the compiler engineers. If you know the data your program will be handling, adding hints will avoid these surprises.
by spacecadet_ - You can influence the choice of conditional moves (usually inserting them) with
__builtin_expect_with_probability(..., 0.5)
https://github.com/protocolbuffers/protobuf/commit/9f29f02a3...