[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)