[HN Gopher] A vision of a multi-threaded Emacs ___________________________________________________________________ A vision of a multi-threaded Emacs Author : pxc Score : 118 points Date : 2022-05-30 15:07 UTC (7 hours ago) (HTM) web link (coredumped.dev) (TXT) w3m dump (coredumped.dev) | CJefferson wrote: | Note: Not at all an emacs expert, but know some stuff about | trying to parallelise a long-standing language ( GAP -- www.gap- | system.org , 30 year old maths language). | | I'd strongly recommend something like Javascript's "web workers", | where each thread lives in an almost entirely independent memory | space, with sharing limited to explicitly named buffers. | | The problem with traditional "everything shared by default" | threading is even when you get the basic core working, we found | throughout the system there were buffers and caches, which all | needed making thread-safe. Even after that, every library needed | some fixes -- and while these were often simple these libraries | may not have had updates in years. | taeric wrote: | I'd argue that emacs already has that with process buffers | using sentinels. :D | | By and large, if you don't write blocking code, it doesn't | block. Big caveat here is the TRAMP logic to establish | connections can block. Not sure why those weren't done in a | more async way. | joseph8th wrote: | This is my only real gripe, as well. I really like Tramp, so | I use it anyway, but I gripe about it when it hangs | admax88qqq wrote: | WebWorkers are not very useful as a result. The communication | overhead of copying data between two memory spaces usually | dwafs any apeedups you could get from doing the work in | parallel. | | It's easier to implement as a language and runtime, but to get | truly high performance on today's many thread many core | machines you need shar d memory concurrency more like Java | CJefferson wrote: | True, they are of limited usefulness, but in Emacs you could | (probably) make them more useful over time by exposing more | and more sharing -- but (I'm again guessing, don't know | Emac's insides) it might be easier/safer to start sharing | nothing, then work on sharing as much as possible, rather | than start with full sharing and then try to make everything | work. | jlokier wrote: | _> to get truly high performance on today 's many thread many | core machines you need shared memory concurrency more like | Java_ | | JavaScript supports shared memory concurrency. | | Shared memory1 is available in browser WebWorkers these | days.2 | | Atomic ops for building multi-threaded data structures3 are | available too4. | | Including primitives for thread synchronisation56 used by | mutexes, condvars, producer-consumer queues, etc. | | 1 https://developer.mozilla.org/en- | US/docs/Web/JavaScript/Refe... | | 2 https://caniuse.com/sharedarraybuffer | | 3 https://developer.mozilla.org/en- | US/docs/Web/JavaScript/Refe... | | 4 https://caniuse.com/mdn-javascript_builtins_atomics | | 5 https://developer.mozilla.org/en- | US/docs/Web/JavaScript/Refe... | | 6 https://caniuse.com/mdn-javascript_builtins_atomics_wait | KerrAvon wrote: | The author discusses essentially this option in "A jumping off | point." | convolvatron wrote: | one really nasty conflating issue is that emacs uses a mess of | globals. partially because of the domain but largely because of | dynamic binding and the lack of namespaces. | | emacs really needs to be hoisted onto another language and | runtime. everyone says this but no one can really conceive of | doing this and rewriting or at least refactoring all the elisp | extensions. | | I guess guile emacs is still alive? I should really try | installing it | rurban wrote: | guile-emacs has atrocious string performance | funcDropShadow wrote: | In principle I agree whole heartedly. When introducing | parallelism and or concurrency into an old language, the "web | workers" aproach, or Erlangs actors, to name a decades older | reference to a similar idea, should always be considered. The | problem with emacs in particular is the use of the buffer as | the most versatile data structure. Lot's of data that could | live in some data structure lives in some overlay over some | part of the buffer. And emacs is built on dynamic variables. | Others in this thread have argued to "just refactor" them to | lexically scoped variables. But that would decimate the largest | vector to adapt and modify the system. | | Parallelizing Emacs needs to be a long-term endaveour, as the | maintainers of Emacs already said years ago. I think Emacs | could learn something from Clojure's story for parallelism. | Make data structures immutable by default, and reference them | from as few global variables as possible. The "make data | structures immutable by default" ship has already sailed, but | introducing additional immutable list/vector/map/set data | structures with first class syntax support would allow newly | written code to prepare for a more parallel future. Such | immutable data structures could then be shared between | different "ELisp web workers". The "as few global variables | story" ship has already sailed, but again ELisp authors would | start to consider reducing the number of global variables if it | would enable multi-threading. | brabel wrote: | Yeah, I think that's the way... Dart does this well with | Isolates[1]. The language is basically single-threaded but you | can start Isolates that run on different Threads but have their | own independent memory, and they can exchange messages, much | like in the Actor model. Not having to worry about real shared | memory between Threads as in C++ or Java is incredibly | liberating. As others point out, however, for extremely high | performance that's not the best solution, but for nearly all | applications, including emacs, the Isolate approach is plenty | good enough. | | [1] https://dart.dev/guides/language/concurrency | Kaze404 wrote: | I'd love to see this someday, as an Emacs user. One of my biggest | frustrations with Emacs is how it can simply just hang while | waiting for anything IO bound (like a response from LSP). It | mostly only happens when opening a new file, while in VSCode for | example the file is opened immediately and things like LSP and | syntax highlighting are loaded in the background. | SoftTalker wrote: | I use Emacs all day, every day at work for the last 20 years. | I'd like to see these changes too, but honestly it's not even | close to being on my top 10 of frequent frustrations. The | average web app is way less responsive, suffers random hangs, | HTTP 500 errors, browser freezes, etc. than I experience in | Emacs. | TacticalCoder wrote: | > ... while in VSCode for example the file is opened | immediately and things like LSP and syntax highlighting are | loaded in the background. | | I'm not saying you're not experiencing what you're describing | but I find that weird because I use Emacs with LSP and the | system is responsive while LSP loads up. And I'm using lsp- | mode, not Eglot (I should really try Eglot). I mostly use it | for Clojure: I'm using both Cider and lsp-mode and they work | fine together. And as soon as I open any Clojure source file, I | can keep using Emacs while LSP starts (which is not that slow | btw: only about three seconds I'd say). LSP is one of those | things that runs in another process, so it's one of those case, | for me at least, where Emacs acts like if it was multithreaded. | I haven't seen this lock up / freeze while waiting for some LSP | server answer. | | For example I'll typically open a Cojure file, lsp-mode shall | begin loading automatically and then I manually launch Cider: | everything happens "simultaneously" and I'm not blocked. | | I'll play more attention with other LSP servers (like the CSS | one) but nothing strikes me as slow or frozen. | | If there's one thing I could complain about is that when I'm | busy doing other things (because my Emacs ain't blocked), I see | spurious LSP messages telling me where it's at kinda | distracting me. | | Now I take you're using a native-comp Emacs? And a fast JSON | parsing lib? | | Emacs 28, native comp, lsp-mode, AMD 3700X, NVMe SSD, 16 GB of | RAM. A good machine but nothing crazy fast. | taeric wrote: | I have seen some folks that don't realize they are bypassing | the native-json parser by having debug logging turned on. So, | could be that? | NeutralForest wrote: | My biggest pet-peeve is Org freezing when I'm exporting to PDF. | OrderlyTiamat wrote: | I've had that fixed in the past by simply adding an ampersand | to org's compile command. This does make it run in the | background but makes it ring the bell a number of times. Now | when I'm editing and want to see the compiled pdf side by | side I just start a bash while loop that recompiles | continually with latexmk. | d0mine wrote: | You don't need multiple threads to perform IO asynchronously. | | And in reverse, using threads won't prevent lock-ups: the | opposite is likely. [Pre-emptive] threads compared to external | processes require much more careful coordination that is hard | to achieve if you are installing dozen of emacs packages | written by different people that manipulate the same state. | | unrelated, it is one of the arguments in favor of GIL such as | in CPython--it is easier to get right than fine-grained locks. | KMag wrote: | Agreed. Raw threads are almost always the wrong application- | level concurrency abstraction. Actors/Erlang-style | concurrency and futures are both much better abstractions for | application programmers. I'm also a big fan of threads with | compile-time proofs against data races, a la Rust, but I can | appreciate it's a lot to learn for many application | programmers. | metroholografix wrote: | That multi-threading will solve this issue, is a common | misconception. Emacs already supports asynchronous I/O and has | sentinels for exactly that. However, not everything that runs | on Emacs is taking advantage of that functionality. It is | therefore up to you, to use the proper package (or not use the | wrong one) / configure Emacs in such a way, so that this sort | of issue is avoided. I can definitely say that if you're | experiencing I/O hangs, it's either misconfiguration or bad | code in a package that you loaded. | | Finally for LSP, I always recommend Eglot over LSP Mode, as | Eglot is written by an Emacs contributor that has deep | knowledge of Emacs and Emacs Lisp. LSP Mode is written by | volunteers on Github, and the code is nowhere near as good. | | Given the (enormous amount / ever-increasing number) of Emacs | Lisp packages out there, a lot of them being substandard, being | able to make these sort of qualitative calls (and also | increasingly dive into Emacs internals) will pay off. Assuming | moderate effort, this will come with experience and time spent | using Emacs. | mdkdkdk wrote: | I've seen you post this criticism before, but the line | "volunteers on GitHub" is pure FUD. Is the Eglot guy paid for | writing Eglot, or he hosts somewhere else, so it's better? | | "The code is nowhere near as good" according to you? Give a | concrete example of where the LSP code has real deficiencies; | Eglot isn't as fully featured, is more opinionated, and its | stans are more annoying. | | Sounds to me like the LSP project is helping new hackers | learn Emacs, and Eglot is one bus accident from being | unmaintained, frankly. | Kaze404 wrote: | Wow, I had no idea! I'll give Eglot a try, thank you :) | rprospero wrote: | While I appreciate the comments on Eglot vs LSP, the number | one package that hangs my system is Gnus. It's still my | favourite e-mail client, but I'm cut off from coding for | twenty seconds every time I check my e-mail. | | Are we really ready to declare that Lars Magne Ingebrigtsen | is a substandard Emacs Lisp coder? | michaelmrose wrote: | I use mu4e so I don't know if the workflow converts but I | watch for new email outside of Emacs entirely and upon new | email run offlineimap and after sync have it run | mu4e-update-index via emacsclient. | | This means Emacs always has an up to date view of my email | within a ~30 second window of the email being received and | all I'm asking it to do is query mu which takes ms. | alex_smart wrote: | Gnus has been around since the mid 90s (and predates the | addition of asynchronous url-retrieve api to emacs). It is | unfair to compare it with packages that written in the last | couple of years. | | I don't use Gnus so I have never bothered looking at its | internals, but if it is locking your emacs for twenty | seconds checking email, it is probably not doing much | asynchronously. It is notoriously hard to convert existing | synchronous code to asynchronous without using threads. | Promises/futures/continuations/whatever-you-want-to-call- | them are a pretty all in affair. Not having the time | investment that would take to convert a 100k line codebase | to async does not make Lars Magne Ingebrigtsen a | substandard Emacs Lisp coder. | metroholografix wrote: | This. Gnus is a behemoth, has been around for decades and | is also the result of many contributions from many | different people. It will take time for it to evolve | (it's slowly happening). | | Lars is amazing by the way, his relentless Emacs work and | prolific bug killing in the last few years should be | praised to high heavens. | kwhitefoot wrote: | Not only that but he is incredibly responsive to random | people (including me in the past) reporting bugs in Gnus. | Years ago I reported something on a Friday morning and he | replied directly to me with a workaround by the | afternoon. | Athas wrote: | Joining the eglot choir. It behaves like I expect Emacs modes | to behave and hooks into other Emacs functionality (xref, | eldoc). Actually, it behaves better than that: it often works | with zero configuration, which is much better than I expect. | chrsig wrote: | This is putting a lot of blame on the user, who likely has no | clue how emacs i/o behaves. | | > if you're experiencing I/O hangs, it's either | misconfiguration or bad code in a package that you loaded | | I mean...yes. That's the issue. The issue is that it's | possible to have i/o hangs caused by misconfiguration or | elisp packages. | | The solution isn't to tell the user to do something | different, it's to make it so that elisp execution can't | cause i/o hangs. | | edit: to a be a bit more precise with language: "i/o hang" | should be interpreted as "making the UI unresponsive or | preventing other tasks from completing". | medstrom wrote: | How would you make it impossible to make the UI | unresponsive? Given that lots of packages directly want to | do stuff with UI? | chrsig wrote: | I'm not going to have a great answer for how, especially | in something with as much legacy as emacs. And I | certainly don't mean to imply that solving the problem is | easy (or possible for 100% of cases), or otherwise | detract from efforts that the community has made. | | My intent was to highlight on what a good solution looks | like from a user perspective. | | Off the top of my head, in an incredibly hand-wavey | fashion: | | A quick win would be to set a timeout on every single i/o | action, with the default timeout being quite low. That | doesn't remove the problem, but it'd probably be a good | start towards easing the user pain. Bringing an | indefinitely long hang down to 1s is a win. | | For a total solution, I'd consider looking into | implementing a concurrency model with a preemptive | scheduler, probably using erlang as inspiration. have | updates to the ui becoming a message sent to the ui | inbox, and the routine for rendering the ui just reading | from the inbox and applying the given command. | | This is without thought to how to actually implement | that, and what implications it would have on legacy | elisp, or how legacy elisp could be brought into a CSP | world without breakage. | | So just some armchair architecting on a day off for a | project I've never worked on :) | jrockway wrote: | > This is putting a lot of blame on the user | | I think you're missing the point. Emacs already contains | all the support necessary to make LSP not lock up the UI, | LSP simply doesn't use it. So if you say "LSP is a great | use case for multi-threaded Emacs", that's not correct. | | The problem with LSP specifically is that Emacs doesn't | really know what the language server is going to do, and if | it let you update the text while the language server was | also updating the text, it would have to have some way to | merge the changes that you made while the language server | was busy. There would need to be some spec for that, or | more likely, another trip to the language server to figure | out what to do. You could, of course, edit the text while | that second trip was happening, and this algorithm never | converges to a finished state. So, it locks the UI so you | can't make any edits until the text from the language | server comes back. That's the easy way out, but at least it | results in an algorithm that terminates. | | The way to fix this is to figure out where the time is | being spent. If it's on JSON marshaling/unmarshaling, speed | that up. If it's because the language server is slow, speed | that up. The only compromise right now would be to let you | edit buffers in a different project while the language | server is processing something. I don't think anyone wants | to do that; "I don't want LSP to lock up Emacs" really | means "I want my language server to perform all operations | instantly." So get out that profiler for your language | server, I think. | bitwize wrote: | > I think you're missing the point. | | I don't. "The only thing that matters in software is the | experience of the user." The Emacs user experience is | full of I/O hangs; the VSCode experience is not. This is | a problem that needs to be solved if Emacs is ever to | have a significant installed base again. | light_hue_1 wrote: | > I can definitely say that if you're experiencing I/O hangs, | it's either misconfiguration or bad code in a package that | you loaded. | | As an emacs user and package developer of 20 years I can | definitely say you are totally wrong. This is the kind of | dismissive, unhelpful, and frankly extremely discouraging | attitude that is slowly killing emacs. | | Instead of taking responsibility for the fact that emacs is | incredibly slow because of poor architectural decisions (like | an insistence to not using fast native libraries and an | incredibly slow language), the solution is apparently to | blame the people who create packages. If developers they are | creating packages that are slow, it is not their fault. It is | the fault of emacs developers in refusing to modernize the | architecture in a way that enables people to make efficient | code. | metroholografix wrote: | > This is the kind of dismissive, unhelpful, and frankly | extremely discouraging attitude that is slowly killing | emacs. | | Emacs seems to be doing just fine if not thriving. | | > Instead of taking responsibility for the fact that emacs | is incredibly slow because of poor architectural decisions | (like an insistence to not using fast native libraries and | an incredibly slow language) | | For me, Emacs is both incredibly fast and incredibly | stable. For an "Emacs user and package developer of 20 | years", you seem either too quick to jump to conclusions or | are still barely scratching the surface of what's possible | which makes me question the depth of your expertise and/or | how efficiently your time with Emacs was invested. | natrys wrote: | The presupposition that anything is killing Emacs - much | less this - requires concrete proof. Because if anything, | in my (likewise subjective) experience it's the complete | opposite. I see more forum activity from newcomers and more | high quality packages emerging each year than ever before. | | > like an insistence to not using fast native libraries | | How? Even disregarding graphics and font stack which almost | entirely leverages native libraries, my Emacs build links | against gmp, libpng, librsvg, zlib, alsa-lib, libxml2 and | so on. 27.1 introduced jansson for native json parsing over | pure elisp, from 28.1 we can basically AoT compile elisp to | native code using libgccjit, master branch (29) even | bundles sqlite these days. That is not to mention module | system had been stable for a while, and lot of packages | already use this to offload computation heavy stuff to | native code. | alex_smart wrote: | If your lsp-client code is doing anything where you need | binding with a native library or the speed of emacs lisp is | a factor, you _are_ doing it wrong. All an lsp-client needs | to do is make requests to the lsp-server, listen to the | responses and update the UI. It literally doesn 't matter | how slow emacs-lisp is. | | The only way an lsp-client could be slow is by making a | request to the server and then blocking on the response - | which is wrong and the package writer's fault because they | are not using the asynchronous api emacs provides for | communicating with a process. | gcommer wrote: | There's tons of little details and inefficiencies in | elisp that crop up such that easy things like "listen to | responses" are hard to get fast. Random example: before | native json support, large lsp responses (which can be | multiple megabytes from some servers!) would take over a | second and hitch the UI just to parse the json response. | And that was after a lot of work to get response parsing | dominated by json instead of GC time. | jhgb wrote: | > and an incredibly slow language | | Languages are not slow or fast; their implementations are. | There's absolutely nothing wrong with Emacs being | programmed in Lisp and it sure as hell isn't "a poor | architectural decision". If Emacs is slow because of its | implementation of Emacs Lisp, it's time to fix its | implementation of Emacs Lisp. | light_hue_1 wrote: | > There's absolutely nothing wrong with Emacs being | programmed in Lisp and it sure as hell isn't "a poor | architectural decision" | | I love Scheme and Lisp. I've probably written several | million lines of code in both Scheme and Lisp and I've | contributed code to several Lisp and Scheme compilers. | | But languages are absolutely slow or fast! There are fast | Schemes and Lisps and there are slow ones. Emacs has | probably the slowest one by far. For example, Emacs still | relies on dynamic binding after all of this time. That's | a performance disaster. | | There is simply no efficient implementation of Elisp | possible as it stands and as it is used today. Even with | JIT compiling Elisp performance is simply wretched. | jhgb wrote: | > I've probably written several million lines of code in | both Scheme and Lisp | | BTW you _do_ realize that this would put you at | (sustained, average) several hundred lines of code per | day ( _every_ day) over your lifetime? That sounds almost | depressingly bleak to me. How does one have a life | outside of that? | light_hue_1 wrote: | > BTW you do realize that this would put you at | (sustained, average) several hundred lines of code per | day (every day) over your lifetime? That sounds almost | depressingly bleak to me. How does one have a life | outside of that? | | Grad school sure puts you on the right track of getting | good numbers like this! :) And the answer was, not having | a life outside of grad school. | jhgb wrote: | Grad school doesn't last forty years though...or does it? | light_hue_1 wrote: | I should hope not! | | Also, 40 years? 1000000/40/52 ~> You're assuming the | average developer writes 500 lines of code per week? That | seems absurdly slow. | jhgb wrote: | Well, you _did_ say "several millions", so that would be | more like 2000 lines. And depending on the environment, | I'm aware of many people who do much less (not of their | own volition), so I have little faith in a long-term | average being _this_ high. I 'll have to take a look that | what Capers Jones wrote on this... | xxpor wrote: | I'm lucky if I write 500 lines of code a quarter these | days.... | funcDropShadow wrote: | > But languages are absolutely slow or fast! There are | fast Schemes and Lisps and there are slow ones. | | You are contradicting yourself. If languages instead of | implementations were slow or fast, then their would not | be fast and slow Schemes and Lisps. Scheme would be | either slow or fast. | | Actually, I would go even further than saying only | implementations are slow or fast, they are slow or fast | for certain use cases. | | > There is simply no efficient implementation of Elisp | possible as it stands and as it is used today. Even with | JIT compiling Elisp performance is simply wretched. | | I agree in so far as there will --- probably --- never be | an Elisp implementation which can run numeric intensive | code as fast as the best Fortran or C compiler for this | task. But it is certainly possible to improve the | performance of ELisp even more than native-comp branch | did. The question is whether there are people capable and | willing to invest the time to develop that and whether | spending that time on the language implementation is the | most useful way to spend that time. | light_hue_1 wrote: | > You are contradicting yourself. If languages instead of | implementations were slow or fast, then their would not | be fast and slow Schemes and Lisps. Scheme would be | either slow or fast. | | You are unfamiliar with the huge differences between what | counts as a "Scheme" or a "Lisp". Neither "Scheme" or | "Lisp" are a language, they're language families. The | difference between Schemes is larger than the difference | between say C and Ocaml, or Haskell and Javascript. | | Depending on what features a particular Scheme or Lisp | has, it can range from insanely fast (like, faster than | an optimizing C compiler), to mediocre (like Python), to | dirt slow, like current Elisp. It all depends on what the | language has, and how it encourages you to write code. | For example, having a type system tends to make your | language very fast. | | > Actually, I would go even further than saying only | implementations are slow or fast, they are slow or fast | for certain use cases. | | Compilers are not magic. And compiler technology has not | fundamentally advanced for decades now. There are basic | limits to what a compiler can do. Some language features | simply destroy performance, and the lack of some language | features prevent compilers from getting good performance. | And then, yes, there is also style. For example, relying | heavily on language features that are inherently slow, | will do you no favors. | | Elisp is the pinnacle of a terrible language used in a | terrible way. It lacks all features that make languages | fast. It has plenty of features to defeat optimizations | and preclude having any fast implementations. And people | write Elisp in a gory style that makes everything worse. | | > I agree in so far as there will --- probably --- never | be an Elisp implementation which can run numeric | intensive code as fast as the best Fortran or C compiler | for this task. But it is certainly possible to improve | the performance of ELisp even more than native-comp | branch did. The question is whether there are people | capable and willing to invest the time to develop that | and whether spending that time on the language | implementation is the most useful way to spend that time. | | I don't care about numerical code. I care about the fact | that emacs is dirt slow. | | It's been many decades now. Elisp performance has barely | budged. Even the native branch only marginally improved | things in some edges cases. There is zero evidence that | more effort for faster implementations will go anywhere. | | In general. More developer time doesn't meaningfully | speed up a language even on the timespan of decades; this | means like even say a huge effort, a millenium worth of | hours of developer time (100 developers full time for 10 | years), makes no serious difference to the performance of | the average app running on the JVM (a few percent), it | mostly just patches edge cases. It's the same in Haskell. | GHC 7, from 10 years ago, is marginally slower than GHC | 9.4 if you run the same large app in both. | | What makes a difference to performance is changing the | language. Adding language features that the compiler can | understand (that's why say, Haskell code is far faster | today than it was 10 years ago, it's a different | language, with different features, that we write in a | different way). | jhgb wrote: | Then the codebase needs to fully (or as much as feasible) | transition to the use of lexical bindings. It's not like | we don't know if it will work; Common Lisp supports | dynamic variables but you don't pay for them unless you | actually use them, and good implementations of CL are | fast enough. So what exactly is it that prevents the | Emacs Lisp code base from becoming fast enough by | abandoning dynamic variables wherever it can? By all | rights it should not be any slower than Common Lisp at | that point, unless some other obstacle has somehow eluded | my attention. | nicoburns wrote: | > Languages are not slow or fast; their implementations | are. | | Right, but languages have finite extant implementations. | If a language has no fast implementations then it's | reasonable to call it slow. | zdragnar wrote: | > It is therefore up to you, to use the proper package | | This is the single biggest reason I don't use emacs. I have | yet to get a stable installation with the necessary behaviors | and tools I need to make memorizing all the chords worth the | effort. | | I've tried spacemacs, doom and from scratch, and have never | been satisfied or gotten to the point where coding is as | productive as VScode for me. | yakubin wrote: | For me the most frequent source of freezes was Tramp. It led | me to ditch Emacs for VSCode (with the remote editing | extension) at least for my dayjob (I still use Emacs for my | own projects). Tramp is an official built-in package, so it's | not as if I downloaded a random package from GitHub. | [deleted] | jhoechtl wrote: | As an innocent user I tell you that LSP mode just works | whereas Eglot needs tailoring to be a joy to use. | dotancohen wrote: | I just got into emacs last year, for Org mode. Startup times | drive me crazy. | | What would be the correct way to configure my .emacs file to | e.g. check for package updates in a background process? | alex_smart wrote: | Don't check for package updates during startup? Setup a | cron job to upgrade the packages while you are asleep? | complex1314 wrote: | Use emacsclient and have a emacs server running at all | times. Super fast startup times, you can even use | emacsclient -nw (or make an alias 'e' for that) in the | terminal for fast edits with instantaneous startup. | | You could also make a script that starts emacs as a client | only if a server already is running | #!/bin/sh if [ "$#" -eq 0 ] then echo | "Starting new Emacs process ..." >&2 nohup emacs > | /dev/null 2>&1 & elif emacsclient -n "$@" 2> | /dev/null then echo "Opened $@ in Emacs | server" >&2 else echo "Opening $@ in a new | Emacs process ..." >&2 nohup emacs "$@" > /dev/null | 2>&1 & fi | | (Copied from an emacs starter kit but don't remember | which...) | massysett wrote: | This is really "just leave Emacs running all the time," | which is more of a workaround or an acceptance of "fit | your workflow around Emacs" than it is truly a solution, | which would be to reduce startup times. | tom_ wrote: | Why do you quit though? I don't quit other programs... | why is Emacs different? | massysett wrote: | I quit and restart Vim dozens of times daily. | | I'm not saying there's something wrong with leaving Emacs | running. But it's a workaround. When I used Emacs, | startup time was not a problem. But I didn't use a bunch | of packages. | joseph8th wrote: | Once it starts it does almost nothing unless you're using | it, and then it's still a lightweight document editor, | not an Electron app | NeutralForest wrote: | You should use `use-package` to manage your packages and | defer their loading to when you use them. I have over 100 | packages in my init.el and my Emacs loads in less than a | second. | kwhitefoot wrote: | Why does Emacs startup time bother people so much? It's | pretty quick for me and only happens once every few months | anyway. | BeetleB wrote: | Don't do automatic package updates. It's a sure way to | continually break things. | hierandthere wrote: | How often do you start Emacs? I do that maybe once a week. | contravariant wrote: | Using Doom emacs was the easiest way for me to get fast | loading times. It provides some sane defaults that should | be pretty fast in most cases. It might be worth checking | out. | jonpalmisc wrote: | Another vouch for Eglot here. Seems smoother and just nicer | overall compared to lsp-mode, not to mention better | integration with Emacs. I switched to Eglot a while back and | haven't looked back. | taeric wrote: | Glad to see this as the top response here. I was rushing to | click reply so that I could point out that async has been a | thing for Emacs for a long long time. Compilation mode is my | goto example for how that can work. | tgbugs wrote: | One big challenge for multi-threaded Emacs is that there are many | elisp libraries and common patterns around buffer modification | that make implicit assumptions about sequential and exclusive | execution. | | The various race conditions that would appear in a multithreaded | context would be a nightmare to debug because they would likely | only occur sporadically and would be hard to reproduce. I would | love to be wrong about this, but I see it as a major obstacle | that will likely need to be sandboxed (as was done with lexical | scoping). | | For an example of how hard these kinds of issues could be to | debug look no further than the incredible difficult that the | undo-tree author had in debugging a race condition with the | garbage collector. It took years. | | In the context of this piece, having a buffer mutex makes certain | use cases for multi-threading impossible, for example dividing | the buffer up into chunk equal to the number of cores and running | a regexp over each chunk. | melony wrote: | Note that Clojure offers multiple concurrency systems, the | default STM is not particularly performant and doesn't scale very | well. You are better off calling into Project Loom for concurrent | code. | Thaxll wrote: | Clojure is memory safe and no data races possible? | melony wrote: | Memory safe, perhaps, but data races are definitely possible. | The main issue is that their STM system doesn't scale very | well. It is good enough if you want to keep a simple CRUD GUI | in sync but don't expect to be building high performance web | servers anytime soon with Clojure atomics. You can't just | create and throw those around willy-nilly like Goroutines. | Clojure people doesn't like talking about the language's | weaknesses but I have seen quite a few Clojure projects get | rewritten because of maintenance cost and runtime | inefficiencies. Project Loom is the best option right now for | scalable Clojure concurrency/parallelism. | lilactown wrote: | STM, atomics and channels are all different things that can | be use to build different kinds of systems, so I think it's | good to disambiguate them when talking about concurrency | problems and their tradeoffs. | | Clojure' STM is basically unused. It's a suite of functions | and a container type `ref` that allows you to do transactions | in memory and keep everything consistent within the view of a | transaction. The overhead required to do the book keeping for | these transactions is often not worth it for most use cases | in practice. | | Clojure also, as an alternative, gives you `atom` which is a | type that implements a simple thread safe compare-and-swap. | This ends up being sufficient for many cases of sharing state | between threads. When combined with Clojure's immutable data | structures, one can often use them as a simple in memory | database. | | Those two things are about sharing memory, but has nothing to | do with what the article talks about: green threads. | | clojure.core.async, as the article succinctly explains, | allows you to create "goroutines" or green threads which are | then multiplexed across some number of OS threads. This can | allow you to create many more threads for computation than | you have OS threads, and combined with thread locals and | atoms can allow one to build large scale systems. | | Clojure's STM and atomics are sort of a non-sequitur from | what the article is talking about | | Now as for downsides of Clojure, there are plenty of gotchas | in practice that can lead people to issues with the three | things above: | | * STM is slow and rarely useful compared to regular atomics | | * atoms CAS assumes you are using immutable data structures | | * core.async has a lot of sharp edges, including lack of | first-class error handling and the fact that doing | synchronous I/O on a go routine can end up starving the | thread pool they are running on | | I've never built a high performance web server, but I imagine | it's possible with Clojure; it would probably require you to | probably eschew immutable data structures within the plumbing | (for performance) and use an async I/O framework along with | core.async to get competitive with a language like go. For | shared memory, you probably would end up eschewing compare- | and-swap for something more bare bones like locks, which you | have access to via Java interop. At that point, you may | wonder why you even chose Clojure in the first place instead | of using Java directly. :D | | Project Loom really only helps solve the problem that | core.async is trying to solve, and applications would still | make use of atomics like `atom` and basic Java atomic values. | My hope is that it makes it easier to do I/O, since it sounds | like along with loom fibers the project is adding first class | support for suspending and resuming on fundamental I/O | operations. Time will tell. ___________________________________________________________________ (page generated 2022-05-30 23:00 UTC)