Live data from Hacker News

Bit-twiddling optimizations in Zed's Rope

zed.dev

11–20 of 51 posts

Re: Bit-twiddling optimizations in Zed's Rope

#11
post #3

> // Parallel bit count intermediates > let a = v - ((v >> 1) & (u64::MAX / 3)); > let b = (a & (u64::MAX / 5)) + ((a >> 2) & (u64::MAX / 5)); > let c = (b + (b >> 4)) & (u64::MAX / 0x11); > let d = (c + (c >> 8)) & (u64::MAX / 0x101); That "parallel bit count" is almost certainly slower than using two POPCNT instructions on a modern cpu. Should just call __builtin_popcount() and let the compiler do it the most optim…

Which compilers support __builtin_popcount()? From memory, it's a gcc extension. If the compiler selects a CPU POPCOUNT instruction for it, are you sure it will work on all machines that you want to run it on? The above code is completely source- and binary-portable and reasonably fast -- certainly faster than naively looping through the bits, and within a small constant factor of a CPU POPCOUNT instruction.

Everything supports __builtin_popcount or some variant these days (__popcnt for MSVC). It's a complete non-issue, really.

And the compiler is not required to lower it to a single instruction. It will if the target architecture is specified appropriately, but there's nothing that says it has to explode if it can't. In fact, by doing it this way, the compiler is actually more free to generate code in a way that's optimal for the architecture in all cases, because all the implementation details are hidden e.g. loads of large constants may be avoided if the compiler is allowed to choose the exact implementation, while using the portable version may tie its hands more depending on how it's feeling on that day. Here's __builtin_popcount working just fine while targeting a ~20yo architecture without native support for SSE4.2; it can generate this code knowing what the proper instructions and schedules are: https://godbolt.org/z/ra7n5T5f3

The moral here is that the primitives are there for you to use. Just use them and save yourself and your would-be code reviewer's time.

Re: Bit-twiddling optimizations in Zed's Rope

#12
post #8

Earlier quoted context omitted.

Which compilers support __builtin_popcount()? From memory, it's a gcc extension. If the compiler selects a CPU POPCOUNT instruction for it, are you sure it will work on all machines that you want to run it on? The above code is completely source- and binary-portable and reasonably fast -- certainly faster than naively looping through the bits, and within a small constant factor of a CPU POPCOUNT instruction.

Your compiler will know the best way to popcount, that is the point of that builtin. It'll use the best method - sometimes this one. GCC does this, MSVC does this, clang does this, i think even rust has some way to do it (EDIT: it does: count_ones()). On archs which lack POPCNT, it will use this method or another, based on knowing the target. On x86 this approach is OK as is. On arm64, for example, it will be subopti…

Note that by default rustc targets x86-64-v1 when compiling for x86-64, and that lacks the popcount instruction. You need to change the target_cpu to at least x86-64-v2 or enable the popcount target_feature. This means that even if your cpu is relatively new and you intend to run your code on relatively new cpus, rustc will still generate older and slower code for count_ones() using bitshifts and masks. That said, I don't see the point in writing them manually if the compiler can generate them for you.

Re: Bit-twiddling optimizations in Zed's Rope

#14
post #7

Earlier quoted context omitted.

> it does not take full advantage of how good computers are today, e.g. gpu rendering or multicore Why does Emacs need that though? I hear people say this all the time and I don't get it. Multicore kind of works against the structure that Emacs touts as a feature. And GPU rendering? In many applications, I totally agree with these complaints. But it's a text editor. I tried Zed myself, and it's good. But it doesn't d…

> Multicore kind of works against the structure that Emacs touts as a feature. I have consistent issues with emacs locking up when executing network requests. I'm sure there's a specific bug that could be hunted down and addressed, but this sort of thing shouldn't happen much in an editor that's multicore by default. I'm not trying to dismiss emacs' reasoning, of course, but I can understand being disgruntled with it…

Yeah this is one reason, or Emacs freezing for up to a minute when updating packages. Also when using an LSP I notice latency.

I use Emacs GUI (outside of the terminal) and comparing performance for rending to something like Zed or Sublime is definitely noticeable. It’s great that Emacs is so resource efficient but sometimes I wish it used more of my beefy computer(s).

Like I said I still love Emacs and it’s okay for it to make a different set of trade-offs. I honestly didn’t think I’d ever switch editors but here we are!

Re: Bit-twiddling optimizations in Zed's Rope

#15
post #14

Earlier quoted context omitted.

> Multicore kind of works against the structure that Emacs touts as a feature. I have consistent issues with emacs locking up when executing network requests. I'm sure there's a specific bug that could be hunted down and addressed, but this sort of thing shouldn't happen much in an editor that's multicore by default. I'm not trying to dismiss emacs' reasoning, of course, but I can understand being disgruntled with it…

Yeah this is one reason, or Emacs freezing for up to a minute when updating packages. Also when using an LSP I notice latency. I use Emacs GUI (outside of the terminal) and comparing performance for rending to something like Zed or Sublime is definitely noticeable. It’s great that Emacs is so resource efficient but sometimes I wish it used more of my beefy computer(s). Like I said I still love Emacs and it’s okay for…

That's fair I guess. In the case of IO that can be an issue. When I hear multicore, I assume we're talking about parallelism, not concurrency.

As for LSP, other than the Nim langserver, I've been quite satisfied with Eglot's performance. I'm curious what your setup is like. To be fair, I'm running a highly customized Doom Emacs config, so it's possible I inherited some non-vanilla optimizations I'm not aware of.

Re: Bit-twiddling optimizations in Zed's Rope

#16
post #7
post #2

I really like all the blog posts and videos the Zed team has put out, thank you if you’re reading this! Unrelated to this specific post I’m such a fan of Zed. It’s the first feature complete text editor in recent memory that I’ve truly enjoyed using (i.e. it stays out of the way, is really fast, feels well engineered). I’m coming to Zed after years of Emacs which I still have love for but no longer feels like a compe…

> it does not take full advantage of how good computers are today, e.g. gpu rendering or multicore Why does Emacs need that though? I hear people say this all the time and I don't get it. Multicore kind of works against the structure that Emacs touts as a feature. And GPU rendering? In many applications, I totally agree with these complaints. But it's a text editor. I tried Zed myself, and it's good. But it doesn't d…

“Need” is strong but using GPU rendering is definitely better than CPU rendering and makes things feel very snappy

Most new TTY projects use GPUs for that reason

Re: Bit-twiddling optimizations in Zed's Rope

#17
post #7
post #2

I really like all the blog posts and videos the Zed team has put out, thank you if you’re reading this! Unrelated to this specific post I’m such a fan of Zed. It’s the first feature complete text editor in recent memory that I’ve truly enjoyed using (i.e. it stays out of the way, is really fast, feels well engineered). I’m coming to Zed after years of Emacs which I still have love for but no longer feels like a compe…

> it does not take full advantage of how good computers are today, e.g. gpu rendering or multicore Why does Emacs need that though? I hear people say this all the time and I don't get it. Multicore kind of works against the structure that Emacs touts as a feature. And GPU rendering? In many applications, I totally agree with these complaints. But it's a text editor. I tried Zed myself, and it's good. But it doesn't d…

> But it's a text editor.

Long time emacs user here (+20 years, yikes). I've used it on all kinds of computers during this time. Even a relatively modest computer from 2024 is an absolute beast compared to something from the year 2000.

With that said, there are text editing operations that can cause it to grind to a complete halt, especially working with large files (or very long lines). And it shouldn't, you know? I think emacs users sort of internalize which operations they should avoid. It's kind of ridiculous to have to do that in a text editor with the massive amounts of compute that our computers have today.

Re: Bit-twiddling optimizations in Zed's Rope

#18
post #14

Earlier quoted context omitted.

> Multicore kind of works against the structure that Emacs touts as a feature. I have consistent issues with emacs locking up when executing network requests. I'm sure there's a specific bug that could be hunted down and addressed, but this sort of thing shouldn't happen much in an editor that's multicore by default. I'm not trying to dismiss emacs' reasoning, of course, but I can understand being disgruntled with it…

Yeah this is one reason, or Emacs freezing for up to a minute when updating packages. Also when using an LSP I notice latency. I use Emacs GUI (outside of the terminal) and comparing performance for rending to something like Zed or Sublime is definitely noticeable. It’s great that Emacs is so resource efficient but sometimes I wish it used more of my beefy computer(s). Like I said I still love Emacs and it’s okay for…

Removing the interpreter lock for a few specialized tasks (without sweeping runtime changes to Emacs) would be enough to fix most of these issues -- parsing JSON from process output into lisp data in a background thread is one candidate. [1]

Installing packages does not need to block either, there is no architectural limitation here. The Elpaca package manager for Emacs provides async, parallel package updates. Loading packages into the Lisp image will block though, there's no way around that.

The other big source of input lag is garbage collection, and there are some ongoing efforts to use the MPS library in Emacs for a copying, concurrent GC. This is a big change and I don't know if this experiment will go anywhere, but Eli Zaretskii and co are trying.

[1]: https://github.com/emacs-lsp/emacs

Re: Bit-twiddling optimizations in Zed's Rope

#19
post #3

> // Parallel bit count intermediates > let a = v - ((v >> 1) & (u64::MAX / 3)); > let b = (a & (u64::MAX / 5)) + ((a >> 2) & (u64::MAX / 5)); > let c = (b + (b >> 4)) & (u64::MAX / 0x11); > let d = (c + (c >> 8)) & (u64::MAX / 0x101); That "parallel bit count" is almost certainly slower than using two POPCNT instructions on a modern cpu. Should just call __builtin_popcount() and let the compiler do it the most optim…

What that code does is a per-byte-pair popcount, which is not what the POPCNT instruction does (it computes the popcount for the whole word).

On processors with BMI2 the whole algorithm reduces to a PDEP as mentioned in another comment, but if you don't have that this is pretty much the best you can do (unless you use lookup tables but those have pros and cons).

Re: Bit-twiddling optimizations in Zed's Rope

#20
post #7

Earlier quoted context omitted.

> it does not take full advantage of how good computers are today, e.g. gpu rendering or multicore Why does Emacs need that though? I hear people say this all the time and I don't get it. Multicore kind of works against the structure that Emacs touts as a feature. And GPU rendering? In many applications, I totally agree with these complaints. But it's a text editor. I tried Zed myself, and it's good. But it doesn't d…

> But it's a text editor. Long time emacs user here (+20 years, yikes). I've used it on all kinds of computers during this time. Even a relatively modest computer from 2024 is an absolute beast compared to something from the year 2000. With that said, there are text editing operations that can cause it to grind to a complete halt, especially working with large files (or very long lines). And it shouldn't , you know?…

> (or very long lines)

Long line handling has greatly improved in emacs-29. Multi-megabyte lines are not a problem anymore.

Post reply on HN