A new Emacs version was declared stable yesterday, the last major revision was released in 2012 so it's quite the occasion.
A few years ago I've started building it from source instead to depend on binary packages, mostly because I couldn't find a recent version on the Debian repositories. All things considered the process was less tedious than I feared.
The following is more of a personal note on what I need to remember the next time I decide do install a new version or minor release, but it can convince the reader that is not so scary.
To ensure I have a suitable build environment, I install the "dev" dependencies reported in the Debian packages, usually this is enough unless a new feature is integrated, for example the new release has support for Cairo drawing or Xwidgets. For sure all the required info can be found in the release notes. Once downloaded the sources and applied eventual patches, it's the usual configure; make; make install
if extracted from a tar archive, autogen.sh
should be required only when pulling directly from the git repository:
$ ./autogen.sh
$ ./configure --prefix=/opt/emacs25.1
$ make
$ sudo make install
Now the install part of the makefile should ask to set movemail as setuid root; I don't use Emacs to read email, but I usually run the command when prompted.
The last thing I do is creating a symbolic link for emacs and emacsclient in /usr/local/bin
and checking that the path in my emacs.desktop
and emacsclient.desktop
files in ~/.local/share/applications
are pointing to the correct executable.
Done.
I wanted to streamline my Emacs configuration, so after a little of yak shaving, all the Emacs packages that I'm using are now configured to be lazy-loaded on demand. Basically I removed all the "require" instances, if we don't count the library that manages the packages.
This also took care of sensibly reducing the start-up time. I couldn't find my notes, but I think it went from around 2 seconds to probably 1.5 seconds, using emacs-init-time as reference.
I wasn't surprised to find available libraries to benchmark or trace Emacs' functions and ready made solutions to profile the start-up sequence like the The Emacs Startup Profiler (ESUP) or ProfileDotEmacs. So after using ProfileDotEmacs I've found out that, in my case, packages initialization is the most expensive operation with a combined 0.49 seconds or 64% of the total time, while my customization need 0.18 seconds to complete, 23% in percentage. This means that further tweaking the customization can give small gains.
Recently I found a couple of suggestions to speed up the start-up sequence. One is to temporarily increase the activation threshold of the garbage collector, the other is to temporarily disable the handling of the magic file names when starting up.
The first one can be implemented like this:
;; temporarily increasing GC to speedup startup time
(setq gc-cons-threshold-default gc-cons-threshold)
(setq gc-cons-threshold (* 100 1024 1024))
(run-with-idle-timer
2 nil
(lambda ()
;; restore default GC value
(setq gc-cons-threshold gc-cons-threshold-default)
;; clean up minibuffer
(message nil)))
The value is increased from 800 KB to 100 MB and restored after a couple of seconds1. With this change I measured a reduction of around 0.3 seconds.
The second suggestion consists in wrapping the init.el
file like this:
;; temporarily disable file name check to speedup startup time
(let ((file-name-handler-alist nil))
...
the init file content
...
)
In my case this one removes about 0.1 seconds, the gain is quite modest but it doesn't clutter too much the init.el
file so I decided to left it there.
In the end, according to emacs-init-time the start-up needs 1.1~1.2 seconds.
After seeing that the biggest part of the start-up is spent enabling packages, I tried to include the package.el
library in the dumped binary, but without success. Probably the reader is not aware how the Emacs executable is created, so in few words, during the build process a bare-bone Emacs instance called Temacs evaluate a file called loadup.el
that loads the required elisp libraries and at the end the working environment is dumped in a file. This file is the executable that is run when Emacs is invoked.
After the little digression, package.el
depends on cl-lib.el
but this one fails on load with the error "Wrong type argument: stringp, 0". The problem is I'm not able to activate the Temacs' debugger, I'm surely doing something wrong because trying temacs -q
doesn't drop me in the editor but insists always to evaluate the loadup.el
file that triggers the error.
I'll look at it again another time, for the moment I'll stick with emacsclient.
plenty of time to complete the start-up. ↩
The Z shell, usually called zsh, is a command interpreter with a big legacy and packed with features. The documentation is definitely ponderous and I'm always surprised to find little known features.
I have a little suggestion for the people that like me use to put in their prompt an indicator with the battery level, adding a couple of lines will keep the values always updated instead of only when executing a command:
# update prompt every 60 sec
function update-prompt-and-resched() {
# find existing scheduled event and remove it
integer i=${"${(@)zsh_scheduled_events#*:*:}"[(I)update-prompt-and-resched]}
(( i )) && sched -$i
sched +60 update-prompt-and-resched
zle && zle reset-prompt
return 0
}
To avoid terminal redraws when I'm looking at the scrollback buffer and the prompt is updated by the scheduler, I disabled the option "Scroll on output" in my terminal.
All the open shells now have the correct battery value, otherwise one can use Tmux and put the indicators in the status line.