-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimizing for speed: do's and don'ts #502
Comments
No, I remember you :D
There are two main issues:
The first issues is probably more severe. To improve speed
The second issue is a bit more tricky. I already rewrote prefix handling to be faster in the prototype I mention in that issue, but that doesn't help anyone until the rewrite is actually complete (or has a minimal feature set). I would address the first issue and then see if Emacs loading is still too slow for you. If you are mainly using Emacs for magit, then not many general forms should need to run on startup anyway, so the prefix issue might not be a problem. Doom emacs has rewritten some sort of similar prefix handling as a workaround to general's being slow. For now, you could look into copying that code if there is still a problem. You could also look into using the dumper if speed is really that much of an issue still. Let me know if further clarification is needed. Action items
|
I looked at my previous notes. The reason :non-normal-prefix and :global-prefix are slow:
There is actually a simple fix you can do since you are already using
;; this will bind the prefixes to the prefix map
(general-define-key
:states '(emacs normal visual insert)
:prefix-map 'my-prefix-map
:global-prefix "C-c"
:non-normal-prefix "M-SPC"
:prefix "SPC")
(general-create-definer my-map
:keymaps 'my-prefix-map)
(defalias 'use-package-normalize/:general-config #'use-package-normalize/:general)
(defalias 'use-package-handler/:general-config #'use-package-handler/:general)
;; add :general-config to `use-package-keywords` after :config
(setq use-package-keywords '(.... :config :general-config ...)) |
Thank you so much for the wealth of information, I really appreciate your time! I'll give this a shot when I get a chance and report back. |
So I had a chance to apply some the ideas you gave me, hopefully correctly. I'm sure with the change to globally defer packages in Overall your changes have indeed yielded noticeable results and I've been able to arrive at my goal config consisting of basic utilities, evil, and primarily magit—at least the first pass which I can continue refining/pruning from there. The Thank you so much for your work on Certainly feel free to close this if you wish, or use it as an ongoing performance-addressing issue, up to you! Either way, if others are pursuing something similar, they may benefit from the information you provided so thanks again for that. If anyone else comes here and is curious what I did, you can find the relevant commits (and extra ones as well, as I was doing general cleaning) in this commit range. Feel free to let me know if you spot glaring issues! What I primarily did was as @noctuid mentioned:
I don't have cold hard numbers unfortunately. I felt I didn't need numbers since this wasn't about shaving away extra milliseconds, but rather a very very noticeable, night and day difference of +5 maybe even +8 seconds compared to now maybe < 2 seconds which is more tolerable. Admittedly either one is "tolerable" and is why I never bothered to really optimize, since I open emacs for what I intend to be long sessions, but more and more lately I find myself opening it for quick sessions almost exclusively limited to |
I will add
Yes, it will scale. It's fine to still use It may not save a significant amount of time, but you can keep If it's not immediately obvious how to defer a package, you can always look at how doom does it. I plan on adding more equivalents for doom helpers related to autoloading packages to general at some point. Some functionality already exists in general.el (like run-once hook functions). The more general startup time optimizations may also be worth taking a look at. At some point, you'll only be improving startup time by a small amount, but some of the optimizations are very simple to implement (e.g. disabling garbage collection during init, moving some configuration to the early init file, etc.). For example, see here and here. Just moving where I disabled the tool and menu bar saved me 0.2s. Even though I mostly use the daemon, I prefer to keep my
A |
Wow thanks for all that information! I'll certainly give it a shot next time I get a chance, of course don't let that get in the way of closing this issue whenever. Thanks again! |
If you get a chance, can you look at the new documentation I've added in the open PR and let me know if it is confusing or if I need to add more information? |
Will do! I also tried out some of the changes you mentioned such as adding early-init and disabling gc during init and it definitely does seem to have helped further! Thank you so much! |
…in which-key For some reason when binding keys for a specific keymap using general, the :which-key keyword doesn't work (My guess is it has something to do with noctuid/general.el#502). (<description> . <command>) is a supported definition (see the docstring of define-key) and it works.
See here also. Straight has an autoload concatenation feature builtin, but I didn't find it made a significant difference for me. |
Finally fixed thanks to the information in this issue: noctuid/general.el#502 Binding our prefix keys to a keymap leads to a significant improvement in start up time. This also eliminates the slowdown when loading evil after general.
Finally fixed thanks to the information in this issue: noctuid/general.el#502 Binding our prefix keys to a keymap leads to a significant improvement in start up time. This also eliminates the slowdown when loading evil after general.
Hey @noctuid, doubt you remember me but I was a somewhat early adopter (I think?) of your awesome package!
Sorry for the wall of text. I decided to spin this off of #497 because I didn't want to derail your thread.
Lately I've used Emacs less and less for general tasks and increasingly mostly for Magit, so I was going around pruning my configuration of slow/unnecessary packages as much as possible in an effort to make it load as fast as possible with the bare minimum (utils like general.el, evil, magit).
I wasn't planning on getting rid of general.el (and still am not) as I saw it as a crucial bare necessity, but after much trial and error/bisecting I realized that indeed as you say, the mere act of having
:general
clauses in myuse-package
definitions, was causingevil
to load very substantially slower. (I realize technically that's not necessarily what's causing the slow-down, I'm saying it from a user perspective).I'd appreciate any help whatsoever that you can provide here short of your rewrite that would allow me to salvage the use of general.el in some form. In general would you be kind enough to explain to us as users in slightly more detail, what exactly are the cases that lead to this degenerate slow behavior, in the hopes that I can avoid them while retaining use of general.el? Or phrased another way: could you maybe share do's/don'ts if we're interested in performance? For example it seems you're saying we should probably avoid ":global-prefix, :non-normal-prefix, and :prefix".
For what it's worth: it really is very noticeably slower for my particular configuration because I have lots of bindings defined. Previously I didn't care since I figure, even if it's slow to start emacs, I'll keep it around and make use of it for a while. Now since my use case has changed, it just feels wrong to me that it take that long to open emacs for a quick Magit session, so I'm interested in cracking down on that if at all possible.
If you like, feel free to respond in a generalized form in the readme and then link me there!
My custom map is defined here:
https://github.com/blaenk/dots/blob/d0389c15ab5fb377ed59b868e64a06ae18def195/emacs/.emacs.d/inits/conf/common.el#L32-L36
Some questions:
Is there something about that definition in particular that subjects me to increased slowness? I guess I have the trifecta of things you're saying cause slowness like
:global-prefix
. Can you share what makes that slow? If I were to get rid of these settings then I guess it would simply cause the bindings to no longer be "root" level bindings so to speak (I think of the bindings as a DAG), so I'd have to specify the "root" keymaps to attach to?Can you expand on:
Are you saying that I could instead not set a
:general
clause on use-package and move those(my-map …)
calls to the:config
section. So what I'll lose there is that I will no longer auto-load the package when I press the keys that I define, and instead those keys won't "work" until I cause the package to load in some other way so that the keymap exists?Can the same be accomplished by disabling autoloaded keymaps (assuming that is what's slow to do), so I set
general-use-package-emit-autoloads
off and then I can keep the:general
clauses but they simply won't work until the keymap exists, or is it the case that since the keymap doesn't exist at the point of evaluation then those keybinds won't work even after the keymap exists, since the binding code won't have run again?If that's the case, if I'm understanding correctly, do you think a possible compromise to both keeping the top-level
:general
clauses (there's just something nice about seeing them upfront, it feels self-documenting in a way, but I can live without them if this isn't possible!) while ensuring that the keymaps will work once the package/keymap eventually exists, would be to add a new:on-config t
style keyword similar to how you have:no-autoload t
mentioned here? Its behavior would basically cause the forms in that section to be evaluated only after:config
. I guess at that point it may seem, why even bother, why not just move everything to:config
. I just feel like it's super clean to have binds upfront in a self-documenting way, distinct from actual configuration behavior, even if it is a form of configuration, this way it doesn't make the config section too noisy. But if it's too much trouble no worries at all, I'll live!I guess at that point if I'm doing it everywhere, I would set
general-use-package-emit-autoloads
and whatever new global flag you'd create for this.EDIT: I realize now that this is probably what you meant by a
:general-config
section inuse-package
. That works too, whichever is easiest, if you can do it, it would be immensely appreciated!!More succinctly: what could I do, even if it heavily reduces ergonomics (e.g. it becomes more verbose/explicit), to recover the speed cost? How should I go about making bindings if I got rid of the prefix settings instead?
The text was updated successfully, but these errors were encountered: