Emacs with the SpiderMonkey garbage collector
lists.gnu.org
lists.gnu.org
https://github.com/Wilfred/remacs
It's a port of the EmacsOS to Rust, should be able to run all your elisp code at some point.
It may also come with speed improvements, as Rust did for FF. :)
And I can imagine that writing (parts of) Emacs' plugins in Rust (for speed and/or hackability) may also be a great addition.
I think such kind of approach could be adopted by emacs without having to rewrite everything from scratch. Taking advantage of this would require of course rewriting a good amount of code (both elisp and C), but it could be done bit by bit over the course of a long time.
Indeed. I think mrighele is talking about server side web app performance, which is a much higher level game and because a lot is stateless allows scale-out + loadbalancing to achieve resource utilization maximization.
When writing hi-perf systems (like a browser), this is a very different game. In this game threading is a tool you need to make sure all cores utilized.
Out of all the types of gc out there going to a copying gc seems not very compelling. Mark and sweep is not bad at all (well understood, straight forward to implement), and you don't have to worry about double dereferencing pointers (ie some implementations of Cheneys, I don't know if spidermonkey refercences are indirect pointers to one of two buffers).
The Microsoft .NET implementation use a copying GC. IIRC the HotSpot JVM GC is compacting as well. Conservative GCs are much easier when interacting with C though, especially if you have to share pointers.
The only downfall is needing enough free space to perform the copy.
Value semantics covers 95% of your object-lifetime needs. The other 5% can be covered with some form of reference counting and being smart about strong vs. weak references. Tracing GC is like bubble sort: almost always a suboptimal solution.
What you are talking in the 2nd paragraph is total nonsense in a lisp world. Lisp solved this problem decades ago, with copying collectors. Stack values are 20%, plus refcounts do not work with rplac* able trees and are super slow.
As it turns out, compared to the analysis and tree traversal inherent in even a fast GC algorithm, the overhead of malloc() and free() is really quite small. So yes, it takes twice as much memory to use a copying GC, right out of the starting gate -- but in order to match the performance of the equivalent explicitly managed program, it takes even more memory on top of that. And real time -- forget about it. It takes highly tuned, specialized algorithms to run a GC language that can meet hard real-time deadlines. You'll know you've found a decent algorithm because it will be proprietary -- part of some expensive, specialized JVM the Navy uses to crunch radar data aboard ship or something. The conventional algorithms (stop-and-copy, generational, etc.) are all fucking terrible.
And I wasn't talking about "in a Lisp world". Lisp is dead for real application development. Hell, the scruffies won, and C++ is now the predominant language in AI -- where Lisp was once said to thrive. Of course refcounts don't work if you try to build a graph with only one kind of reference. But a) you should know what kind of data structure you're building (cyclic or acyclic, graph or tree) and b) you should use weak references where possible to inform the deallocator which references not to chase. It's called being smart. Yes, it's a little more work than using a tracing GC, but it's still far less cognitively taxing or error-prone than using malloc() and free() manually.
That article was presented at OOPSLA '05 which ran from October 16–20, 2005. I don't know when it was written, nor when the data for it was worked out. That said, it seems safe to say that it's more than twelve years out of date.
Any GC uses much less memory than a refcount or malloc application. That's common sense. Just copying uses more vmem during the copying, compaction step, but even this size is usually less than the refcount and malloc overhead. The copying one even uses no stack-space, due to Cheney.
A GC is always superior to refcounts and manual malloc, because it's much too hard to do that by yourself. With real-time you use incremental collections. Just store the state where to continue.
Agreed, the conventional m&s, stop the world collectors as eg. used in most major fancy languages are all terrible. You only need that for an FFI. But a good GC is far superior. And most importantly faster and safe. You don't update refcounts with a GC. You don't pollute your cache and concurrent updates with that.
Look at Java or .NET if you don't like lisp. Same tech, a solved problem.
That's plain wrong.
> because it's much too hard to do that by yourself.
Too hard to do yourself? There are some of us who have been doing it for decades. In places where performance, predictable runtime and memory usage is of paramount importance (like the linux kernel) it is still done manually. I'll grant you Moore's law has made those places increasing rare nowadays.
Yes it harder to do it manually, but only in the sense that it's harder to do anything manually than have it automated. But being hard and error prone doesn't mean the result is slower, or uses more memory. A moments thought should have told you that. GC delays freeing memory until there is sufficient memory pressure. The mental load imposed by tracking malloc's means a programmer does it immediately so he can forget about it. Thus the memory is available for re-use immediately.
In my experience a long running program manually managing it's heap has a heap about twice the size of actual space in use. In theory some degenerate cases caused by fragmentation can make it far worse - but I've never been bitten by it. Long running GC languages (they tend to be written in Java) it's around 5 times. Again, if you done any sort of server administration, you would know this. All of us who do have watched Java VM's grow over with amazement and dismay. Ironically, the cure is a form of manual memory management - kill them and restart.
Get to punt the allocator as a bump allocator
Basic answer is if there are complaints with the garbage collector causing stalls or other hiccups, then moving to a faster one could help.
Now, this implies that a new one would, ipso facto, be faster. That is not guaranteed. But, garbage collectors have gotten quite effective in modern times. Extra memory helps, of course.
The current emacs GC can introduce long pauses, so I’d be happy to see something which improved Thant, and I have seen annoying increased memory usage in long emacs processes so experiments in this area would be welcome.
Is that an actual problem, though?
Maybe I just don't push Emacs that far, but I have never felt GC performance to be much of a problem on even remotely capable hardware (say, anything at least as fast as a Raspberry Pi model 2).
Plus, Emacs allows the user to configure the frequency at which the garbage collector kicks in. Tweaking gc-cons-threshold has been entirely sufficient for my needs.
To your point, though, I suspect better async processing would be of much greater benefit.
EDIT: Apparently my experience is not universal -- see below: https://news.ycombinator.com/item?id=15803046
i also really don't like having my editor pause to do gc.
(i'm addicted to emacs flexibility, but i would love a better-engineered replacement. maybe xi editor, someday. (though their multiprocess approach seems _insane_ to me, _especially_ in a language that gives you safe shared-memory concurrency!))
here's the necessary incantations, in any case anyone wants to try this at home:
;; never collect.
(setq gc-cons-threshold 10000000000)
(defun garbage-collect (&rest args)
(message "trying to garbage collect. probably you want to quit emacs."))
(setq garbage-collection-messages t)
the message kicks in at 10GB.i remembered what the driving reason was to disable gc:
turning off gc gets my emacs startup time down to ~400ms from ~600ms.
The root scanning problem with nested calls causing races is known. I do have the same problem. You need to assign to volatile temps, or implement boehm-like scanning of registers. Which is not easily portable. Volatile temps are, and they are fast enough for me. Still running circles around boehm or any other m&s GC.