How can I make Emacs start-up faster?
Asked Answered
M

17

78

I use Emacs v. 22 (the console version, either remotely with PuTTY or locally with Konsole) as my primary text editor on Linux. It takes a while to load up each time I start it though, probably almost a second, although I never timed it. I tend to open and close Emacs a lot, because I'm more comfortable using the Bash command-line for file/directory manipulation and compiling.

How can I speed up the start-up time?

Motley answered 22/4, 2009 at 19:12 Comment(5)
I've had the same problem on Ubuntu. There seem to be a lot of Emacs packages that are auto-loaded on startup by the default package configuration and I can't figure out how to block the ones I don't want/need.Elsworth
@Chris, try staring Emacs with --no-site-file, it's possible that the installation has undesired packages loaded there.Brach
We massively decreased (load times down by ~80%) the load times of emacs where I work by removing some of the colour information being sent back and forth between the client and the server.Fadeout
Profile your .emacs. I've posted a link that explains how to do that in my answer below.Chickaree
You don't have to close Emacs completely, you can just suspend it by typing C-z. Then, in bash, type the command fg to continue it in the foreground. Other than that, try M-x term in Emacs to have a shell inside emacs (inside your shell :-)). That way, you never actually have to leave Emacs, you just have another bash shell available in a buffer.Mcpeak
I
43

In addition to Adam Rosenfield's solution, I recommend to use Emacs in server mode. You may add (server-start) to your dotemacs, and run emacsclient instead of emacs whenever you want to open file in Emacs. That way you have to pay the loading cost of Emacs only once, after then clients pop up immediately.

Edit

You're right, v22 does not create a new frame. Create a shell script that do the trick:

#!/bin/bash
# Argument: filename to open in new Emacs frame
/usr/bin/emacsclient -e '(let ((default-directory "`pwd`/")) (select-frame (make-frame)) (find-file "'$1'"))'

Edit 2

In v24+, you can do emacsclient -c to create a new frame.

Isallobar answered 22/4, 2009 at 19:38 Comment(5)
I'm struggling with this solution - I have the server started up, but I can't seem to get emacsclient to start a new frame. Apparently my version of emacs doesn't support the "-c" or "-t" options. Any suggestions?Motley
emacs --daemon is only supported in v23 and beyond. Plus it doesn't start correctly if it finds errors with your ~/.emacs which it may find when you move to this new version for the first time :)Partan
if you run emacs in server mode which is a pretty faster way. these shortcuts might come handy.... 1. to start the server emacs --daemon this will cause it to run the server and return the control to the terminal. 2. then to edit files. emacsclient <filename> 3. to stop the daemon emacsclient -e "(kill-emacs)"Deoxyribose
I am having following error: *ERROR*: Unknown terminal typeAnselmo
@Anselmo see if this helps: unix.stackexchange.com/questions/119871/…Isallobar
B
61

Others have covered using gnuserve and emacsclient, and I'd suggest compiling within emacs (being able to jump to compilation errors is a win).

But, specifically speeding up the .emacs can be done by:

  1. Byte compiling the .emacs file, which you can do automatically by using this snippet of code

  2. Replacing as many of the (require 'package) statements with autoloaded functionality. This will delay loading of lisp until it's actually required. Using this technique allowed me to speed up my startup from >6 seconds to <1. This takes a little bit of work because not all libraries come properly marked autoload.

  3. Removing code/functionality you no longer use.

  4. Try running emacs with the option --no-site-file to avoid loading unnecessary packages in the site installation site-start.el.

  5. If you are really serious, you can roll your own emacs with your favorite functionality already loaded. This, of course, means it's more involved to make changes to what you have in your .emacs because it's a part of the binary. Follow the link for information on how to use dump-emacs.

  6. Buy a faster computer and/or faster disk.

How to determine what your .emacs loads

Now, how do you find out what your .emacs loads? With the goal to remove the functionality, or to delay it? Check your *Messages* buffer, which contains lines like:

Loading /home/tjackson/.emacs.tjackson.el (source)...
Loading /home/tjackson/installed/emacs/lisp/loaddefs.el (source)...done
Loading /user/tjackson/.elisp/source/loaddefs.el (source)...done
Loading autorevert...done
Loading /home/tjackson/.emacs.tjackson.el (source)...done

If you'll notice, the Loading statements can nest: the first .emacs.tjackson.el ends with ... and the last line shows the .emacs.tjackson.el load is ...done. All those other files are loaded from inside my .emacs.tjackson.el file. All the other loads are atomic.

Note: If you have a large .emacs, it's possible that the *Messages* buffer will lose some of the messages because it only keeps a fixed amount of information. You can add this setting early on to your .emacs to keep all the messages around:

(setq message-log-max t)

Note: It the 'load command will suppress the messages if its fourth argument nomessage is non-nil, so remove any such invocations (or, advise 'load and force the fourth argument to be nil).

Brach answered 22/4, 2009 at 20:44 Comment(3)
Could you elaborate on the second advice? I don't understand how to replace my require-calls with autoload, as autoload seems to require a docstring parameter.Cornstarch
@Micha90 Well, click on the link for autoload for full detail, but if you can't (or don't want to) modify the source code to insert the ;;;###autoload lines, you can manually add lines like (autoload 'tcl-mode "tcl-mode") in your .emacs to enable auto loading (for tcl-mode in this case).Brach
Can I apply --no-site-file for the emacsclient as well?Anselmo
I
43

In addition to Adam Rosenfield's solution, I recommend to use Emacs in server mode. You may add (server-start) to your dotemacs, and run emacsclient instead of emacs whenever you want to open file in Emacs. That way you have to pay the loading cost of Emacs only once, after then clients pop up immediately.

Edit

You're right, v22 does not create a new frame. Create a shell script that do the trick:

#!/bin/bash
# Argument: filename to open in new Emacs frame
/usr/bin/emacsclient -e '(let ((default-directory "`pwd`/")) (select-frame (make-frame)) (find-file "'$1'"))'

Edit 2

In v24+, you can do emacsclient -c to create a new frame.

Isallobar answered 22/4, 2009 at 19:38 Comment(5)
I'm struggling with this solution - I have the server started up, but I can't seem to get emacsclient to start a new frame. Apparently my version of emacs doesn't support the "-c" or "-t" options. Any suggestions?Motley
emacs --daemon is only supported in v23 and beyond. Plus it doesn't start correctly if it finds errors with your ~/.emacs which it may find when you move to this new version for the first time :)Partan
if you run emacs in server mode which is a pretty faster way. these shortcuts might come handy.... 1. to start the server emacs --daemon this will cause it to run the server and return the control to the terminal. 2. then to edit files. emacsclient <filename> 3. to stop the daemon emacsclient -e "(kill-emacs)"Deoxyribose
I am having following error: *ERROR*: Unknown terminal typeAnselmo
@Anselmo see if this helps: unix.stackexchange.com/questions/119871/…Isallobar
A
30

Don't close Emacs every time you want to use the shell. Use Ctrl-Z to move Emacs to the background and the fg command in Bash to move it back to the foreground.

Absolution answered 22/4, 2009 at 19:22 Comment(3)
+1 Nice attempt to avoid the problem. You might add starting another putty session and/or running screen to your answer. Chris Conway's M-x shell answer is also in this spirit.Reprove
Just correct the link to the official autoload link: it's gnu.org/software/emacs/manual/html_node/elisp/Autoload.htmlPop
never thought of that! surely am going to try it! (y)Deoxyribose
V
22

A couple of tips:

  1. Use autoloads

    Using autoload saves you from loading libraries until you use them. For example:

    (if (locate-library "ediff-trees")
        (autoload 'ediff-trees "ediff-trees" "Start an tree ediff" t))
    
  2. Compile your .emacs

    Gives you a slight speed increase although there are pitfalls if you work with version control and your .emacs is newer than .emacs.elc. One common trick is:

    (defun autocompile nil
      "compile itself if ~/.emacs"
      (interactive)
      (require 'bytecomp)
      (let ((dotemacs (file-truename user-init-file)))
        (if (string= (buffer-file-name) (file-chase-links dotemacs))
          (byte-compile-file dotemacs))))
    
    (add-hook 'after-save-hook 'autocompile)
    
  3. Learn to love emacs server.

    Running emacs as a server means never having to close it down. However I note your still using emacs22. emacs23 supports multi-tty which makes it a lot easier to run emacs in one screen session and then bring up new windows in another terminal. I use emacs to edit mail for my mail client (mutt) and emacsclient is fantastic for these sort of quick edits.

Virtuosic answered 23/4, 2009 at 8:1 Comment(1)
Can I use (add-hook 'after-save-hook 'autocompile) approach in gccemacs(emacswiki.org/emacs/GccEmacs)?Anselmo
E
19

One of

M-x shell
M-x eshell
M-x term
M-x ansi-term

should meet your command-line needs from within Emacs.

You can also use M-! (aka M-x shell-command) to execute a one-liner without dropping to the shell.

Elsworth answered 22/4, 2009 at 20:46 Comment(0)
U
16

Check your .emacs file to see if you're loading unnecessary packages. Loading packages can take a significant amount of time. For example, you might only want to load the php-mode package if you're editing a PHP file. You can do that by installing a hook procedure, although I'm not certain of the details.

Also make sure that any packages you're loading are compiled (.elc files). You can compile an elisp file by running

emacs -batch -f batch-byte-compile thefile.el

Compiled packages load much faster than uncompiled packages.

Urolith answered 22/4, 2009 at 19:19 Comment(1)
How can I load from compiled files (.elc)?Anselmo
T
14

"I tend to open and close emacs a lot, because I'm more comfortable using the bash command line for file/directory manipulation and compiling."

You're describing the way an editor like vim is used like. Shoot in&out. Emacs is usually kept open, and mostly all is done from "within it". hiena already answered what would be the correct approach here.

Tomfoolery answered 22/4, 2009 at 19:33 Comment(2)
Instead of quitting emacs, you could just suspend it, with C-z, then wake it back with fg…Isoelectronic
@Damien Pollet - (confused), ... uhmm, yes, I'm aware of that. I didn't feel repeating what's already been said, so I just pointed to hiena's post.Tomfoolery
C
14

The fastest way is to profile your .emacs. I cut down my load time from >3s to 1s in 5 minutes after I found that 4 particular lines in my .emacs were taking up more than 80% of the load time.

Chickaree answered 5/11, 2011 at 20:28 Comment(2)
The profile-dotemacs package does not seem actively maintained (the "Download" section of the Emacswiki page linked in this answer refers to an archived internet page). Instead Emacs Start Up Profiler (ESUP) seems more up-to-date.Gotama
Which 4 lines did you find?Anselmo
O
11

One thing that helped me reduce the load time of my .emacs, in addition to autoload (as others have suggested), is eval-after-load. In the following example, delaying the call to sql-set-product saves you from having to load sql in your .emacs, making the exisiting sql autoloads more effective.

(eval-after-load "sql"
  '(progn
     (sql-set-product 'mysql)
     (setq sql-mysql-options '("-C" "-t" "-f" "-n"))
     (setq sql-sqlite-program "sqlite3")
     ))

Of course, for some packages there will be a hook available that you can do the same thing, but sometimes there isn't, or else this way just proves easier to think about.

Omaromara answered 28/4, 2009 at 17:17 Comment(1)
One downside of using eval-after-load is that it prevents compile-time checks on the code, which can be quite useful when the customizations become complex. My standard method for such cases is e.g. (eval-after-load "org" (require 'my-org-customization)), i.e. moving the customizations into a separate (compiled) file.Nascent
K
8

Emacs is designed to run "all the time" (or at least for long periods of time), thus starting and stopping Emacs several times during a day is not recommended.

I would suggest using screen. Screen is a terminal multiplexer, giving you an unlimited virtual terminals in one terminal.

After installing simply write "screen emacs" in your terminal. Emacs will start as usual, but pressing "c-a c" (that is press ctrl-a and then c) will open a new virtual terminal. You can get back to emacs by pressing "c-a c-a" (that's two times ctrl-a).

You can even detach from the running screen session, the key sequence is "c-a d".

Re-attach to the session by issuing "screen -R" and you will be back where you left. This enables you to start an emacs session at work, detach, go home, and re-attach from home.

I've been running Emacs like this for months in a row.

Here's the official web site: http://www.gnu.org/software/screen/ but try googling for screen tutorials and howtos

Killam answered 22/4, 2009 at 19:44 Comment(0)
R
6

You can use benchmark-init to profile your Emacs startup. It will keep track of what modules are being loaded and how much time is spent on each. The results can be presented either in a tabulated form or as a tree. The tree makes it easier to track who loads what, which can be helpful when you load a package with a lot of dependencies, and the tabulated form helps you quickly find where most of the time is being spent.

Once you have these results try to figure out if all of the modules have to be loaded all the time or if you can perhaps load some of them on-demand. For instance, in my configuration I only load Emacs extensions that are specific to certain modes when that mode is actually activated since most of the time I only use a small subset of them in a session. eval-after-load and mode hooks will be your friends here.

By applying this method my Emacs starts in 3-4 seconds and I have close to 200 extensions installed. Most of the time is spent loading Helm, which I always load since it replaces find-file and other core functions that are always needed, and CEDET, since I use the latest version and it has to be loaded before Emacs tries to load the older built-in version.

Robey answered 2/5, 2014 at 11:5 Comment(0)
V
5

Try using the https://github.com/jwiegley/use-package macro to define your package loads and customizations. It handles deferred loading of packages for you, making it relatively easy to get good startup times even in the presence of large numbers of configured packages. I have almost 100 packages referenced in my .emacs, but my startup time is under 2 seconds on Linux, and 2.2s on the Mac.

Valora answered 16/3, 2015 at 21:22 Comment(0)
W
4

One thing that others haven't mentioned is to include the elisp libraries you use as part of the dumped Emacs to move the library loading time from Emacs startup to Emacs build. It is not for the faint-hearted, but if you load several libraries in .emacs it could win you a few seconds of startup time.

Walton answered 23/4, 2009 at 9:26 Comment(0)
E
4

I had around 120sec start time. I was able to find the fix installing this:

https://github.com/dholm/benchmark-init-el put on top of your init.el

(let ((benchmark-init.el "~/.emacs.d/el-get/benchmark-init/benchmark-init.el"))
  (when (file-exists-p benchmark-init.el)
    (load benchmark-init.el)))

then once your emacs started, run:

M-x benchmark-init/show-durations-tree

On my side the problem was 127 secs in tramp-loaddefs

I fixed it by adding

127.0.0.1  host.does.not.exist

to /etc/hosts and that made my startup fast

see more here: https://github.com/emacs-helm/helm/issues/1045

another thing that maybe helpful to you: https://www.emacswiki.org/emacs/ProfileDotEmacs

Estienne answered 3/4, 2016 at 0:26 Comment(1)
You saved my sanity. My init file was taking like 2 minutes because of that. Thanks!Bilection
R
3

This doesn't answer the question, but is kind of relevant

I don't know how to make it start faster, but there are a few things I could suggest:

  • for most things you do on the command line, you can do them in emacs:

    • compile: M-x compile, then type the command you use
    • my experience is only with C++, but with g++ you can press C-x ` to jump to lines that the compiler complains about
    • run shell commands: M-!, dumps output into a buffer
    • interactive shell: M-x shell
  • alternatively, you could run emacs like this:

    • emacs file.ext &
    • which opens emacs in the background so you can still use the shell ( this works best with putty and X forwarding with something like Xming)
Rurik answered 22/4, 2009 at 19:21 Comment(0)
I
2

I was trying to solve the same problem, when I came across this question here. I just wanted to add that the problem for me was not because of the load time of emacs lisp packages, but the fact that the host did not have a fully resolved hostname

To check your package load time do

M-x emacs-init-time

For me it was 0.3 seconds, and yet the load time was extremely high. After changing my hostname correctly, it fixed the problem.

To configure your fully resolved hostname edit /etc/hostname, and /etc/hostsfile with:

127.0.0.1       localhost localhost.localdomain
192.168.0.2   hostname hostname.domain
Interlaminate answered 22/10, 2014 at 15:4 Comment(0)
U
1

I would have to check my customization, but there is a package called gnuserve or emacsclient. It migrates a lot so you will have to google for it.

It runs one emacs session in the background. Any further sessions of emacs are essentially just new frames of that session. One advatage is quick startup times for your later sessions.

Unpolled answered 22/4, 2009 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.