3 ms·
Disagree. Using reference (pointer) syntax explicitly to avoid relying on a non-deterministic compiler optimization doesn't decrease readability. It is extrem
by loeg 3y ago
Disagree. Using reference (pointer) syntax explicitly to avoid relying on a non-deterministic compiler optimization doesn't decrease readability. It is extremely naive to assume that a heuristic-guided compiler optimization will always work or that you never need to write your code explicitly in a system that aims to be high-performance, like Tiger Beetle.
Also, some of the optimizations they are hunting are implicit and surprising. Probably not something a new compiler optimization is going to automatically fix.
- mhh__ 3y agoCompilers in general aren't always perfect so if you really genuinely care about copying that much you should be inspecting and profiling the binary they output e.g. unless you have some truly massive value types (at which point my eyebrows would be raised anyway) being copied, the cost is probably going to be in the same ballpark as some other compiler-fuckups too
- loeg 3y ago> Compilers in general aren't always perfect Right. > so if you really genuinely care about copying that much you should be inspecting and profiling the binary they output Sure, but manual inspection is burdensome and unreliable. Are you advocating against just use the language-level constructs (pointers/references) that guarantee a copy isn't performed?
- OfferFun6595 3y agoTrue, not all companies have a perfect data to be relied upon. Some of them are old and redundant
- anonymoushn 3y agoUsing the pointer syntax means "I want to mutate this" and not using it means "I don't need to mutate this." So it's unfortunate if readers cannot count on this meaning because the compiler is defective.
- loeg 3y agoMost languages have something like the ‘const’ keyword (or in Rust, eliding ‘mut’).
- anonymoushn 3y agoThe post is about a specific language. The way that you write the loop without being able to mutate the elements in this language is like this: for (items) |item| { } The way that you write the loop so that you can mutate the elements is like this: for (items) |*item| { } A way that you could try writing the loop so that it's clear that the elements are not mutated, even though you are using the pointer syntax, is maybe like this: for (items) |*_item| { const item: *const @typeInfo(@TypeOf(_item)).Pointer.child = _item; // there's no "drop _item" so unfortunately _item remains in scope but we promise not to use it. } I wasn't sure this would work, but it looks like you can also manage with this: const _items: []const @typeInfo(@TypeOf(items)).Pointer.child = items; for (_items) |*item| { // now item is of the correct type, even if items is a slice of mutable things. }
- loeg 3y agoIf Zig does not have a |*const item| syntax, maybe adding it would be a good idea (and also satisfy your concern)? (Zig already has a concept of mutable and const pointers.) For example, in C++ I would distinguish between mutating iteration and non-mutating iteration like this: for (const auto& item : collection) {} // non-mutating for (auto& item : collection) {} // mutating
- jrockway 3y ago> there's no "drop _item" so unfortunately _item remains in scope but we promise not to use it This is actually a very intriguing programming language keyword. I feel like there are lots of cases where you don't want to split something into a separate function just to avoid being able to use a variable that was used previously, and these things often get refactored over time to the point where the not-to-be-used variable gets used unexpectedly.
- JonChesterfield 3y ago> ... avoid relying on a non-deterministic compiler optimization doesn't decrease readability. It is extremely naive to assume that a heuristic-guided ... This is a post about crawling the compiler IR to find things the compiler missed so that the programmer can change their code to work around the compiler. Even if the crawl-the-IR is a heuristic, moving that into the compiler would mean exactly the cases that were reported are now fixed automatically. Non-deterministic compilers are broken. Arguably by definition, but also by heuristic as a non-deterministic compiler is enough of a nightmare to debug and fix that it can be expected to grow more errors over time. Heuristic compilers are very much a thing. Also sadly fragile optimisations are a thing, where minor changes to the application take it over some threshold and the change in output is larger than anticipated. However, the plan of attack of "change the program until the compiler did what you hoped for" is itself a heuristic that future changes to program and compiler may upset. An alternative is to patch the compiler to do the right thing, and add a regression test to the compiler so that it will continue to do the right thing. That has better engineering properties in the large.
- loeg 3y agoApologies for the confusion, but you've misread my comment and run with it. I don't think there's much here that's responsive to what I intended, so I'll elaborate a little: > Non-deterministic compilers are broken. I am not talking about non-determinism from run-to-run with identical sources and compiler version. I am talking about output variations between (1) different versions of the compiler, and (2) as the sources change slightly. Either of these things can easily nudge the heuristics a compiler uses in optimization into doing something different/worse.
- JonChesterfield 3y agoIt's all good, we're talking past each other slightly. Thanks for the clarification on non-determinism. I think you're giving sensible advice for the world as it is, I'm speculating as to what the world should be. Minor changes in compiler version and input source leading to widely varying output is a definite hazard. Especially when people change their code to make it run faster, or change the compiler to make some code run faster. That's one with no clear good solution.