How noticeable is this in “real life” usage? Are there modes or use-cases that run into GC problems?
I can believe it, I’m just curious what they are. I don’t recall it ever being a problem for me.
It was very noticeable to me because I have a lot of minor modes running that send requests and receive responses that are pretty large, so they create lots of temporary objects, and the slowdowns went from being noticeably distracting on my end to never noticing a GC pass. In practice, the real GCs are probably even faster than the benchmark implies because most regular GCs would fit inside a single block, and the experiment used a lot more conses than would fit in a single block.
Edit: I should add that I have gc-cons-threshold set a lot higher than the default as well, so that trades longer pauses for less GC passes. I like having as little friction as possible for typing, so I generally don’t want the GC running while in Evil insert mode.
hey, this is rad; scrolling down to your background thread Io buffering for eshell, I’m wondering if your patches are headed upstream?
I’m really impressed, and checking out what else is in your fork, cheers!
Thanks! Yeah, I’ve signed over copyright to the GNU for it, but there’s still some work to be done to get it ready to be committed upstream. I recently worked on making it so that writing to the subprocess is also handled with a background thread and just recently fixed a deadlock that arose from that. I haven’t observed any issues with the latest build, but my branch has some other changes that are a bit more idiosyncratic.
I generally work on: https://github.com/tyler-dodge/emacs/tree/tyler-main-2
I also might push a branch with just the latest background output / input changes, if https://github.com/jimeh/build-emacs-for-macos/issues/77 gains traction.
I haven’t profiled it much in that direction, so below is theoretical and not verified. Anecdotally, I’ve had multiple days of uptime with this change where memory stayed within reasonable boundaries.
It mainly impacts memory usage on the margins, in that the size of an empty block will be larger so it adds a larger constant overhead that doesn’t scale with memory usage. That overhead is pretty negligible though since it’s less than 64KB.
Have you tried smaller block alignments? What jumps out to me - an ignoramus in low level computing - is that 1<<10 sets the 11th bit which seems arbitrary but 1<<15 sets the 16th bit which is obviously a “nicer” number. I wonder if 1<<7 would also be “nice” for the branch predictor.
That’s an interesting idea, I’m setting up a build now and I’ll post below a few times generated by the experiment.
Yeah, the effect from having to walk more blocks is even more apparent with switching to a 1 << 7 buffer. There might still be some benefit from the number being “nicer”, but it’s hard to verify without finding out why 1 << 15 is the current limit.
14.237648010253906 seconds
14.998963117599487 seconds
I assume yes but I didn’t see this mentioned: is there still backpressure? I assume you don’t want the background thread to buffer data forever and make emacs OOM if the command runs too much faster than eshell can consume its output for too long.
Yes, this is still back pressure at the background output thread level. The nice thing about this though is it’s back pressure at a larger size instead of 1024 byte back pressure.
Eshell was always frustrating so I tend to always use ansi-term
when inside Emacs, but even that one has issues because of how wonky the terminal is with evil-mode
for me (difficulties escaping insert mode, or difficulties coming back into focus with insert mode).
Very cool patch and I hope others get use out of it.
Try https://github.com/akermu/emacs-libvterm, it’s much better than ansi-term.
Makes sense, the interop with evil mode is one of the reasons I use eshell over a different terminal emulator.
This change also speeds up ansi-term because that also uses a PTY to communicate with emacs.
I probably should’ve emphasized that more in the blog post originally, since it’s really improving subprocess output handling across all of emacs.
Very interesting! Process output latency has bothered me numerous times in Emacs.
Does your change also make M-x compile output faster?
Are you going to upstream your change?
Yes it does. Pretty much anything in emacs that uses a PTY for the subprocess is improved by this (process-connection-type does default to true, which makes it the default type for a process unless the developers explicitly opt in to it being a regular pipe.) It might have some benefits when the process-connection-type is nil, but I haven’t tested that extensively.
I’m planning on trying to upstream it once I extend it to work with the rest of the subprocess types for emacs. Currently, I’m not handling network and pipe subprocesses with the background thread.
I’m a heavy emacs user and excited to hear about this, but the page simply will not render for me.
I just archived it, so try this: https://archive.ph/GBoDb
That’s odd, which browser are you using?
Also, in the meantime, here’s a link that gets rid of most of the dynamic elements on the page, and might avoid whatever issue is happening. I’d still like to know more about this though to prevent it.
https://tdodge.consulting/blog/living-the-emacs-garbage-collection-dream-simple.html
There was an issue with the website related to service workers earlier. I just recently pushed a change that should fix it. You may have to use incognito mode to force the browser to not use the old service worker.
Yep, it’s fixed. I’m running Firefox on GNU/Linux, in case that’s still relevant.
Good article. I wonder how many other old constants (across all software) are still tuned for limited hardware?
In my experience, a lot of defaults / constants are picked more or less arbitrarily initially (speed and other priorities usually being the culprit), and it’s usually harder to argue to change them than to keep the status quo since they are currently working and there are other known priorities. This causes the values that worked reasonably at first tend to languish over time, so I definitely agree that there is a lot of opportunity in revisiting constants.