HNHacker News
TopNewBestAskShowJobs

dzaima

1,742 karma · joined September 30, 2019

https://github.com/dzaima/

https://codeberg.org/dzaima/

submissionscomments
dzaima··on Dirtyfrag: Universal Linux LPE
That's specific libraries, when using the default linker. You could construct that same behavior on desktop linux too. And you can avoid it equally well on Android - you can statically-link things just fine, you can use libraries you actually control, and presumably use a custom linker if desired. It's utterly non-surprising that "you run code you don't control" results in "said code...can do arbitrary things for unsupported use". (Never mind that, instead of a "sherif", they could've just renamed all private symbols, or just naturally replaced them over time, breaking your code all the same, just in a more confusing way)

Also some obligatory Linux vs GNU/Linux comment. (and it's not like GNU/Linux doesn't ever change under your feet - see the glibc DT_HASH debacle)

dzaima··on Jujutsu megamerges for fun and profit
eh, there have been a good amount of breaking changes. `-d`/`--destination` → `-o`/`--onto` (the former isn't yet deprecated though); deprecated `--allow-new` on push (or, forcibly making it the default for `--bookmark`); deprecated `jj bookmark track foo@bar` (and `jj bookmark track foo` having a really-weird system (I personally just call it broken, even though the behavior is intentional) of sometimes tracking the bookmark on all remotes; really I'd call jj's entire system of bookmark tracking/pulling/pushing quite incomplete outside of the trivial cases); various changed revset functions over time that break configs; and a really-annoying thing of `jj git fetch` sometimes abandoning ascendants of `@` leaving you in a confusing state (if not one with conflicts), with the solution being a future `jj git sync`.

It's certainly very usable despite all that, and the changes are simple enough to adapt to, but it's a pretty new thing.

dzaima··on Jujutsu megamerges for fun and profit
Don't necessarily need heavy parallel work, or even anything parallel, to make use of jj; it's very nice for even just manipulating one local sequence of commits (splitting commits up, reordering them, moving files/hunks/lines between them or into/out of the working copy, without needing to checkout anything).

Won't get you much if you don't like to mutate commits in general, of course; at that point it's just a different committing workflow, which some may like and some dislike. (I for one am so extremely-happy with the history-rewriting capabilities that I've written some scripts for reinventing back a staging area as a commit, and am fine to struggle along with all the things I don't like about jj's auto-tracking)

As a fun note, git 2.54 released yesterday, adding `git history reword` and `git history split` in the style of jj (except less powerful because of git limitations) because a git dev discovered jj.

dzaima··on A simplified model of Fil-C
Then you run into the problem of infinite loops, which nothing can prevent (sans `main { exit(-1); }` or other forms of losing turing-completeness), and are worse than crashes - at least on crashes you can quickly restart the program (something something erlang).

try-catch isn't a particularly complete solution either if you have any code outside of it (at the very least, the catch arm) or if data can get preserved across iterations that can easily get messed up if left half-updated (say, caches, poisoned mutexes, stuck-borrowed refcells) so you'll likely want a full restart to work well too, and might even prefer it sometimes.

dzaima··on jj – the CLI for Jujutsu
`edit` is still useful; just, for ..editing (!) something, instead of viewing it.

If you have some unfinished changes at the tip and want to temporarily checkout something 2 weeks ago, you `jj new` to there (similar to `git stash; git switch whatever`), and then later `jj edit your-old-tip` to go back (equivalent to `git switch main; git stash pop`; I think `jj edit` being an extended replacement for stash-popping things is a reasonable way to think about it). (and if you don't have any uncommitted changes, you always `jj new`)

jj also has a concept of immutable commits (defaulting to include tagged commits, and trunk at origin, which it'll disallow editing as a layer of defense)

dzaima··on Optimization of 32-bit Unsigned Division by Constants on 64-bit Targets
Unfortunately, that's only vector, and ≤16-bit ints at that, no 32-bit ints; and as the other reply says, nearly non-existent multiply-high which generally makes vectorized div-by-const its own mini-hell (but doing a 2x-width multiply with fixups is still better than the OP 4x-width method).

(...though, x86 does have (v)pmulhw for 16-bit input, so for 16-bit div-by-const the saturating option works out quite well.)

(And, for what it's worth, the lack of 8-bit multiplies on x86 means that the OP method of high-half-of-4x-width-multiply works out nicely for vectorizing dividing 8-bit ints too)

dzaima··on Git commands I run before reading any code
jj's template and revset languages are very simple syntactically, so once you're comfortable with the few things you do use often it's just a question of learning about the other existing functions (even if only enough to know to look them up), which slot right in and compose well with everything else you know (unlike flags which typically have each their own system).

Or, perhaps better yet, defining your own functions/helpers as you go for things you might care about, which, by virtue of having been named you, are much easier to remember (and still compose nicely).

dzaima··on Two studies in compiler optimisations
> It surprises me that the compiler doesn't still take the inference from the assert and just disable emitting the code to perform the check.

That's because that's what the <assert.h> assert() must do; it's specified to do and imply nothing when assertions are disabled. (the standard literally fully defines it as `#define assert(...) ((void)0)` when NDEBUG)

Whereas `[[assume(...)]]` is a thing specifically for that "infer things from this without actually emitting any code".

dzaima··on The future of version control
In git if you, say, do some `git rebase -i`, edit some commit, continue the rebase, and hit a conflict, and realize you edited something wrong that caused the conflict, your only option is aborting the entire rebase and starting over and rebuilding all changes you did.

In jj, you just have a descending conflict, and if you edit the past to no longer conflict the conflict disappears; kinda as if you were always in interactive rebase but at all points have the knowledge of what future would look like if you `git rebase --continue`d.

Also really nice for reordering commits which can result in conflicts, but leaves descendants non-conflicting, allowing delaying resolving the conflicts after doing other stuff, or continuing doing some reordering instead of always starting from scratch as with `git rebase -i`.

dzaima··on The future of version control
But you do have the op log, giving you a full copy of the log (incl. the contents of the workspace) at every operation, so you can get out of such mistakes with some finagling.

You can choose to have a workflow where you're never directly editing any commit to "gain back autonomy" of the working copy; and if you really want to, with some scripting, you can even emulate a staging area with a specially-formatted commit below the working copy commit.

dzaima··on Google details new 24-hour process to sideload unverified Android apps
> as it's an app from a verified developer.

Well that's if they go through the verification process, which does not seem like a thing they'd want to do - https://f-droid.org/en/2026/02/24/open-letter-opposing-devel...

dzaima··on The unlikely story of Teardown Multiplayer
As far as I know, the ARM (at least aarch64) situation should be about the same as x86-64. Anything specific that's bad about it? (there's aarch32 NEON with no subnormal support or whatever, but you can just not use it if determinism is the goal)

that RECIP14 link is AVX-512, i.e. not available on a bunch of hardware (incl. the newest Intel client CPUs), so you wouldn't ever use it in a deterministic-simulation multiplayer game anyway, even if you restrict yourself to x86-64-only; so you're still stuck to the basic IEEE-754 ops even on x86-64.

x86-64 is worse than aarch64 is a very important aspect - baseline x86-64 doesn't have fused multiply-add, whereas aarch64 does (granted, the x86-64 FMA extension came out around not far from aarch64/armv8, but it's still a concern, such is life). Of course you can choose to not use fma, but that's throwing perf away. (regardless you'll want -ffp-contract=off or equivalent to make sure compiler optimizations don't screw things up, so any such will need to be manual fma calls anyway)

dzaima··on Prefix sums at gigabytes per second with ARM NEON
> This means that all medium price or high price smartphones that were introduced during the last 4 years have SVE2 support.

Except Qualcomm chipsets, which disable SVE even if all ARM cores used support it. ("Snapdragon 8 Elite Gen 5" supposedly finally supports SVE? but that's like only half a year old)

dzaima··on RISC-V Is Sloooow
Indeed we shall hope heuristics update; but of course if no compilers emit it hardware has no reason to actually bother making fast misaligned ops, so it's primed for going wrong.
dzaima··on RISC-V Is Sloooow
> No, it was released to customers in June 2021, almost five years ago.

Ah, okay. (still, like, at least a couple decades newer than the last x86-64 chip with slow unaligned mem ops, if such ever existed at all? Haven't heard of / can't find anything saying any aarch64 ever had problems with them either, so still much worse for the RISC-V side).

Well, I suppose we can hope that business/politics messes will all never happen again and won't affect anything RVA23.

dzaima··on RISC-V Is Sloooow
P550 is, like, what, only a year old? I suppose there has been some laughing at it at least.

Also Kendryte K230 / C908, but only on vector mem ops, which adds a whole another mess onto this.

I'd hope all the massive OoO will have fast misaligned mem ops, anything else would immediately cause infinite pain for decades.

But of course there'll be plenty of RVA23 hardware that's much smaller eventually too, once it becomes a general expectation instead of "cool thing for the very-top-end to have".

I do agree that it'd be reasonable to just assume fast misaligned ops, but for whatever reason gcc and clang just don't, and that's what we have for defaults.

dzaima··on RISC-V Is Sloooow
Of course that'd result in entirely-avoidable slowdown for the potentially-misaligned ops. Perhaps fine for a program that doesn't use them frequently, but quite bad for ones that need misaligned ops everywhere.

In terms of correctness, there's also the possibility of partially-misaligned ops (e.g. an 8B load with 4B alignment, loading two adjacent int32_t fields) so you're not handling everything with correct faults anyways.

dzaima··on RISC-V Is Sloooow
2 is basically infeasible with RISC-V being intended for a wide range of use-cases. 1 might be ok but introduces a bunch of opcode space waste.

Indeed extremely sad that Zicclsm wasn't a thing in the spec, from the very start (never mind that even now it only lives in the profiles spec); going through the git history, seems that the text around misaligned handling optionality goes all the way back to the very start of the riscv/riscv-isa-manual repo, before `Z*` extensions existed at all.

More broadly, it's rather sad that there aren't similar extensions for other forms of optional behavior (thing that was recently brought up is RVV vsetvli with e.g. `e64,mf2`, useful for massive-VLEN>DLEN hardware).

dzaima··on RISC-V Is Sloooow
Yeah, that is quite funky; and indeed gcc does that. Relatedly, super-annoying is that `vle64.v` & co could then also make use of that same hardware, but that's not guaranteed. (I suppose there could be awful hardware that does vle8.v via single-byte loads, which wouldn't translate to vle64.v?)
dzaima··on RISC-V Is Sloooow
There is Zmmul for multiplication-but-not-divide.
dzaima··on RISC-V Is Sloooow
Well, we don't necessarily have to wait for Oilsm; software that wants to could just choose to be opinionated and run massively-worse on suboptimal hardware. And, of course, once Oilsm hardware becomes the standard, it'd be fine to recompile RVA23-targeting software to it too.

> RISC-V could've easily avoided all this mess by properly mandating misaligned pointer handling as part of the I extension.

Rather hard to mandate performance by an open ISA. Especially considering that there could actually be scenarios where it may be necessary to chicken-bit it off; and of course the fact that there's already some questionability on ops crossing pages, where even ARM/x86 are very slow.

dzaima··on RISC-V Is Sloooow
> How is that different for RISC-V?

RISC-V hardware with slow misaligned mem ops does exist to non-insignificant extent, and it seems not enough people have laughed at them, and instead compilers did just surrender and default to not using them.

> As you observed there's a feedback loop between what compilers output and what gets optimised in hardware.

Well, that loop needs to start somewhere, and it has already started, and started wrong. I suppose we'll see what happens with real RVA23 hardware; at the very least, even if it takes a decade for most hardware to support misaligned well, software could retroactively change its defaults while still remaining technically-RVA23-compatible, so I suppose that's good.

dzaima··on RISC-V Is Sloooow
I don't think x86/ARM particularly guarantee fastness, but at least they effectively encourage making use of them via their contributions to compilers that do. They also don't really need to given that they mostly control who can make hardware anyway. (at the very least, if general-purpose HW with horribly-slow misaligned loads/stores came out from them, people would laugh at it, and assume/hope that that's because of some silicon defect requiring chicken-bit-ing it off, instead of just not bothering to implement it)

Indeed one can make any instruction take basically-forever, but I think it's a fairly reasonable expectation that all supported hardware instructions/behaviors (at least non-deprecated ones) are not slower than a software implementation (on at least some inputs), else having said instruction is strictly-redundant.

And if any significant general-purpose hardware actually did a 10k-cycle div around the time the respective compiler defaults were decided, I think there's a good chance that software would have defaulted to calling division through a function such that an implementation can be picked depending on the running hardware. (let's ignore whether 10k-cycle-division and general-purpose-hardware would ever go together... but misaligned-mem-ops+general-purpose-hardware definitely do)

dzaima··on RISC-V Is Sloooow
The option to generate or not generate misaligned loads/stores does exist (-mno-strict-align / -mstrict-align). But of course that's a compile-time option, and of course the preferred state would be to have use of them on by default, but RVA23 doesn't sufficiently guarantee/encourage them not being unreasonably-slow, leaving native misaligned loads/stores still effectively-unusable (and off by default on clang/gcc on -march=rva23u64).

aka, Zicclsm / RVA23 are entirely-useless as far as actually getting to make use of native misaligned loads/stores goes.

dzaima··on Decimal-Java is a library to convert java.math.BigDecimal to and from IEEE-754r
The type seems to just be a small wrapper around a BigDecimal; the actual conversion arithmetic will presumably be relatively extremely slow regardless, a single extra allocation (in addition to BigDecimal's ≥3) won't change much.
dzaima··on Minecraft Java is switching from OpenGL to Vulkan
To be clear I do kinda agree with the general idea that modding isn't that important to Minecraft Java; but it's still very important at least indirectly - were there not as large of a modding scene, I'd imagine many more content creators would've long ran out of content to make on it (or at least unique ways to do things), and the technical research/farms/whatever would be hampered by less available tooling.

(for what it's worth, last I played minecraft, like 1-2 years ago, I did so lightly-modded - Do A Barrel Roll for much more fun elytra; lithium; Distant Horizons; Hydrophobic Elytra to fix a stupid extremely-annoying elytra bug (might be fixed now?), BetterF3 (kinda superceded by the more recent F3 overhaul now I suppose?))

dzaima··on Minecraft Java is switching from OpenGL to Vulkan
The main actual speedrunning categories don't allow any RNG changes; but I doubt anyone doing RSG would have any interest whatsoever going back to the 20x-or-whatever slower seed rolling, that's just a completely utterly dumb waste of time doing literally nothing except clicking a button every 5 seconds (effectively changing the category from "who can play the game the best" to much more like "who has the most beast of a machine to run as many minecraft instances in parallel to more quickly roll a good seed"). Viewership would definitely go down from there being less actual gameplay.

Ranked is intended to be a fun competitive thing; waiting 10 minutes for a dragon perch doing nothing is Not Fun; waiting forever at a spawner is Not Fun; simple as that, people wouldn't play it if it wasn't fun. (oh, also, I believe Ranked also just generally includes making mob drops consistent for the same seed (and consistent portal locations, and probably other things), without which the whole entire concept of competitively playing the same seed would not work whatsoever, devolving to just who got the better RNG, distinctly Not Fun; also the ability to review a replay of your game afterwards for learning). Viewership and player counts would go down because you'd just be looking at very slow gambling instead of something actually meaningfully-skill-based.

A second account might work for freecam (though it adds more editing work, aka makes you not want to actually use it much), but making pretty timelapses is not feasible that way. Granted, you could still live without it, but the quality of content would undoubtedly go down. The little things go a long, long, long way.

dzaima··on Minecraft Java is switching from OpenGL to Vulkan
Speedrunning is very much modded - ranked (the big content) is just flat out modded (not just the match setup, there are game tweaks too (guaranteed blaze drops after 20 or so iirc, guaranteed dragon perch in ≤3 mins)), and even RSG/SSG/AA/etc have a long list of allowed mods (much quicker seed rerolling, timer, perf improvement mods, etc). Many(/most/all? idk) Many (/most/all? idk) hermits use mods (esp. freecam, replaymod for creating timelapses / pretty camera perspectives). Never mind shaders sprinkled in a portion of everything.
dzaima··on RISC-V Vector Primer
You don't need to write a new loop every time a new vector size drops, but over time you'll still get more and more cases of wanting to write multiple copies of loops to take advantage of new instructions; there are already a good bunch of extensions of RVV (e.g. Zvbb has a good couple that are encounterable in general-purpose code), and many more to come (e.g. if we ever get vrgathers that don't scale quadratically with LMUL, some mask ops, and who knows what else will be understood as obviously-good-to-have in the future).

This kinda (though admittedly not entirely) balances out the x86 problem - sure, you have to write a new loop to take advantage of wider vector registers, but you often want to do that anyway - on SSE→AVX(2) you get to take advantage of non-destructive ops, all inline loads being unaligned, and a couple new nice instrs; on AVX2→AVX512 you get a ton of masking stuff, non-awful blends, among others.

RVV gets an advantage here largely due to just simply being a newer ISA, at a time where it is actually reasonably possible for even baseline hardware to support expensive compute instrs, complex shuffles, all unaligned mem ops (..though, actually, with RISC-V/RVV not mandating unaligned support (and allowing it to be extremely-slow even when supported) this is another thing you may want to write multiple loops for), and whatnot; whereas x86 SSE2 had to work on whatever could exist 20 years ago, and as such made respective compromises.

In some edge-cases the x86 approach can even be better - if you have some code that benefits from having different versions depending on hardware vector size (e.g. needs to use vrgather, or processes some fixed-size data that'd be really bad to write in a scalable way), on RVV you may end up needing to write a loop for each combination of VLEN and extension-set (i.e. a quadratic number of cases), whereas on x86 you only need to have a version of the loop for each desired extension-set.

dzaima··on RISC-V Vector Primer
RVV still very much requires you to write a manual code/assembly loop doing the "compute how many elements can be handled, decrease count by that, repeat if necessary" thing. All it does is make it slightly less instructions to do so (and also allows handling a loops tail in the same loop while at it).
← PreviousPage 3 of 32Next →