8000 GitHub - jamescherti/compile-angel.el: Speed up Emacs: Auto Byte/Native-Compile all Elisp files (Alternative to: auto-compile)
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

jamescherti/compile-angel.el

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

compile-angel.el - Speed up Emacs by Byte-compiling and Native-compiling all Elisp files

Build Status MELPA MELPA Stable License

The compile-angel package speeds up Emacs by ensuring that all Elisp libraries are both byte-compiled and native-compiled:

  • Byte compilation reduces the overhead of loading Emacs Lisp code at runtime.
  • Native compilation improves performance by generating machine code that runs directly on the hardware, leveraging the full capabilities of the host CPU. The actual speedup varies with the characteristics of the Lisp code, but it is typically 2.5 to 5 times faster than the equivalent byte-compiled version.

This package offers:

  • (compile-angel-on-load-mode): A global mode that compiles .el files both before they are loaded via load or require, and after they are loaded, using after-load-functions.
  • (compile-angel-on-save-local-mode): A local mode that compiles .el files whenever the user saves them.

Table of Contents

Why use compile-angel?

Because you are likely running a significant amount of interpreted, slow Elisp code that Emacs did not compile automatically. Ensuring that Elisp is native-compiled significantly improves Emacs' performance. Unfortunately, functions like package-install and package-recompile-all do not compile .el files that were not installed using package.el. Since these files are not byte-compiled, the Emacs JIT compiler does not native-compile them either, as a byte-compiled file signals the JIT compiler to perform native compilation. In contrast, compile-angel modes ensure that all loaded .el files are compiled transparently, regardless of whether they are part of a package.

Before installing

It is highly recommended to set the following variables at the very beginning of your early-init.el:

;; Ensure Emacs loads the most recent byte-compiled files.
(setq load-prefer-newer t)

;; Make Emacs Native-compile .elc files asynchronously by setting
;; `native-comp-jit-compilation' to t.
(setq native-comp-jit-compilation t)
(setq native-comp-deferred-compilation native-comp-jit-compilation)  ; Deprecated

;; NOTE: You can also experiment with:
;; - Fully disabling `native-comp-jit-compilation' by setting it to nil,
;;   allowing `compile-angel' to completely replace the Emacs JIT compiler.
;; - For users who do not need byte compilation, it can be disabled by
;;   setting `compile-angel-enable-byte-compile' to nil. Disabling
;;   byte compilation has minimal impact since native compilation is the primary
;;   contributor to improved speed.

If you set native-comp-jit-compilation to nil, compile-angel will fully replace Emacs' native JIT compilation feature. It will natively compile all files that need compilation (i.e., out-of-date files or those where the .el file is more recent than the .eln file), as it will no longer depend on Emacs to perform the compilation.

Additionally, ensure that native compilation is enabled: This should return t:

(native-comp-available-p)

Installation of compile-angel

Emacs

To install compile-angel on Emacs from MELPA:

  1. If you haven't already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code at the very beginning of your init.el file, before all other packages:

(use-package compile-angel
  :ensure t
  :demand t
  :config
  ;; Set `compile-angel-verbose' to nil to disable compile-angel messages.
  ;; (When set to nil, compile-angel won't show which file is being compiled.)
  (setq compile-angel-verbose t)

  ;; For users who don't need byte compilation:
  ;; Uncomment the sexp below to disable byte compilation, so that
  ;; compile-angel performs only native compilation.
  ;; (setq compile-angel-enable-byte-compile nil)

  ;; Uncomment the line below to compile automatically when an Elisp file is saved
  ;; (add-hook 'emacs-lisp-mode-hook #'compile-angel-on-save-local-mode)

  ;; A global mode that compiles .el files before they are loaded
  ;; using `load' or `require'.
  (compile-angel-on-load-mode))

Doom Emacs

Here is how to install compile-angel on Doom Emacs:

  1. Add to the ~/.doom.d/packages.el file:
(package! compile-angel)
  1. Add to the top of ~/.doom.d/config.el:
;; Set `compile-angel-verbose' to nil to disable compile-angel messages.
;; (When set to nil, compile-angel won't show which file is being compiled.)
(setq compile-angel-verbose t)

;; For users who don't need byte compilation:
;; Uncomment the sexp below to disable byte compilation, so that
;; compile-angel performs only native compilation.
;; (setq compile-angel-enable-byte-compile nil)

;; Uncomment the line below to compile automatically when an Elisp file is saved
;; (add-hook 'emacs-lisp-mode-hook #'compile-angel-on-save-local-mode)

;; A global mode that compiles .el files before they are loaded
;; using `load' or `require'.
(compile-angel-on-load-mode)
  1. Run the doom sync command:
doom sync

Frequently Asked Questions

What are some interesting Emacs customizations to consider alongside compile-angel?

Below are a few interesting options:

;; Ensure that quitting only occurs once Emacs finishes native compiling,
;; preventing incomplete or leftover compilation files in `/tmp`.
(setq native-comp-async-query-on-exit t)
(setq confirm-kill-processes t)

;; Non-nil means to native compile packages as part of their installation.
(setq package-native-compile t)

;; -------------------------------------------------
;; Show buffer when there is a warning.
;; (NOT RECOMMENDED, except during development).
;; -------------------------------------------------
;; (setq compile-angel-verbose t)
;; (setq compile-angel-byte-compile-report-issues t)
;;
;; (setq warning-minimum-level :warning)
;; (setq byte-compile-verbose t)
;; (setq byte-compile-warnings t)
;; (setq native-comp-async-report-warnings-errors t)
;; (setq native-comp-warning-on-missing-source t)

How to exclude certain .el files from compilation in compile-angel?

You can exclude .el files from compilation by adding path suffixes to the compile-angel-excluded-files list.

For instance, the following excludes any path that ends with suffix.el (or its variations, such as /path/ANYTHINGsuffix.el.gz or ANYTHINGsuffix.el.gz) and exactly matches paths that end with /filename.el (including their variations, like /filename.el.gz or ANYTHING/filename.el.gz).

;; Run the following before enabling `compile-angel-on-load-mode'
(push "suffix.el" compile-angel-excluded-files)
(push "/filename.el" compile-angel-excluded-files)

;; Run here: (compile-angel-on-load-mode)

If a path suffix in compile-angel-excluded-files ends with .el, compile-angel will automatically exclude the .el.gz variant of that file. For instance, specifying suffix.el will also exclude suffix.el.gz.

How to exclude custom-file, recentf, savehist files?

You can exclude the custom-file, recentf, and savehist files using the following code snippet:

;; Exclude the custom-file, recentf, and savehist files
;;
;; Ensure that compile-angel is loaded using `require`, `use-package`, or
;; another package manager, as compile-angel-excluded-files is declared after
;; the package is loaded.

;; Ensure that the value of `savehist-file` is updated before proceeding
(with-eval-after-load "savehist"
  (push (concat "/" (file-name-nondirectory savehist-file))
        compile-angel-excluded-files))

;; Ensure that the value of `recentf-save-file` is updated before proceeding
(with-eval-after-load "recentf"
  (push (concat "/" (file-name-nondirectory recentf-save-file))
        compile-angel-excluded-files))

;; Ensure that the value of `custom-file` is updated before proceeding
(with-eval-after-load "cus-edit"
  (when (stringp custom-file)
    (push (concat "/" (file-name-nondirectory custom-file))
          compile-angel-excluded-files)))

;; Enable the (compile-angel-on-load-mode) mode after the above

How to enable or disable byte compilation and native compilation?

You can control whether compile-angel performs byte compilation or native compilation of your .el files by setting the following variables in your configuration:

  • compile-angel-enable-byte-compile: Set this variable to t to enable byte compilation. When enabled, compile-angel will generate .elc files for your .el files, making them load faster by converting them into bytecode. Set it to nil to disable byte compilation.
  • compile-angel-enable-native-compile: Set this variable to t to enable native compilation, which generates machine code for supported systems, further improving performance. Set it to nil to disable native compilation.

Example configuration:

;; Enable both byte compilation and native compilation (default)
(setq compile-angel-enable-byte-compile t)
(setq compile-angel-enable-native-compile t)

What's the point of using compile-angel? My Emacs compiles packages automatically anyway!

Emacs often skips the compilation of certain Elisp files. To verify this:

  • Install compile-angel,
  • Enable verbose mode: (setq compile-angel-verbose t)
  • Enable the mode: (compile-angel-on-load-mode)

Observe whether compile-angel compiles any Elisp files (you will see "Wrote" .elc files in the *Messages* buffer). If it does, this indicates that Emacs missed compiling those files and that compile-angel can help improve the performance of your Emacs.

You can also run M-x compile-angel-report to display features that were not native compiled by the Emacs JIT compiler.

Could compiling all Elisp files not be accomplished with a script? (e.g., a GNU Parallel along with Emacs's -batch mode.)

Compiling a large number of Emacs Lisp files regardless of their actual usage is inefficient.

One of the advantages of compile-angel is that it compiles files just before they are loaded, restricting the compilation process to only what is necessary and as a result significantly reducing compilation time.

Moreover, compile-angel guarantees that all relevant files are transparently both byte-compiled and native-compiled without requiring the user to invoke any scripts manually, which simplifies maintenance and reduces the risk of outdated files.

(If you are interested in compiling all Emacs Lisp files regardless of their actual usage, the author recommends trying elispcomp, which performs precisely that task. However, compile-angel offers greater efficiency.)

Why not just use the package-recompile-all function?

The package-recompile-all function is effective for recompiling files within packages, but it misses other files that are not part of a package.

In the compile-angel author's configuration, for example, package-recompile-all skipped most of the local packages loaded using use-package with :ensure nil or require. Additionally, package-recompile-all does not compile transparently; the user must manually run it and wait for it to complete.

The compile-angel package, on the other hand, transparently compiles all packages without any user intervention. The user simply needs to enable (compile-angel-on-load-mode).

What is the impact on Emacs startup?

Compile-angel is optimized. It is fast enough that it is nearly imperceptible to the user. The author of compile-angel reports an Emacs startup time of 0.25 seconds with compile-angel enabled and 0.23 seconds without it. Feel free to share your own benchmarks.

What's the difference between native and byte compiled?

Byte compilation translates Elisp code into an intermediate bytecode .elc that is faster to load than .el files.

Native compilation goes a step further by converting this bytecode into machine code, which is directly executed by the CPU without the need for an interpreter. Native compilation significantly improves performance.

What are some use-cases of compile-angel?

Emacs often misses the compilation of certain Elisp files.

One of the author's primary use cases involves maintaining numerous Emacs packages, which are synchronized into ~/.emacs.d using automation scripts and rsync for testing during development. The author appreciates how compile-angel automatically compiles the files synchronized to the ~/.emacs.d directory while working on these packages.

There are many other use cases as well. For example, some Emacs users prefer storing packages locally or in GitHub repositories, periodically updating them using git pull. This approach is often adopted for packages that are no longer actively maintained, enabling users to manage them independently. In such cases, compile-angel can seamlessly handle both byte-compiling and native-compiling these packages whenever local modifications are made.

What is the difference between auto-compile and compile-angel?

Compile-angel offers more features and is more optimized than auto-compile (see details below).

The compile-angel author was previously an auto-compile user but encountered an issue where several Elisp files were not being compiled by auto-compile (see the explanation below), resulting in Emacs performance degradation due to the lack of native compilation.

The author of auto-compile has made some decisions that prevent it from guaranteeing that all .el packages are byte-compiled and native-compiled. For example, if the user deletes all the .elc files or if the .el files have never been compiled before, auto-compile won't recompile them. Here is a quote from Jonas Bernouli, aka u/tarsius_, the auto-compile author (from this discussion):

Both [autocompile] modes only ever re-compile a source file when the respective byte code file already exists but is outdated. Otherwise they do not compile the source file. By "otherwise" I mean if:

  • The *.elc exists but is newer than the corresponding *.el, OR
  • The *.elc does not exist. In both cases the source file is not compiled, by design.

Here are additional features provided by compile-angel that are not available in auto-compile:

  • Compile-angel ensures that even when when the .elc file doesn't exist, the .el source file is compiled. Auto-compile, on the other hand, requires (by design, as explained above) an existing .elc file in order to compile.
  • Compile-angel ensures that files are compiled before and after they are loaded, In addition to compiling the .el files loaded using load and require, also handles files that auto-compile misses, using the after-load-functions hook. This ensures that all files are byte-compiled and native-compiled.
  • Compile-angel can exclude files from compilation using regular expressions in compile-angel-excluded-files-regexps.
  • compile-angel can exclude files from compilation based on path suffixes listed in compile-angel-excluded-files. This list contains path suffixes such as ("loaddefs.el" "/cus-load.el" "/charprop.el"), which excludes any path ending with loaddefs.el (or its variations, such as loaddefs.el.gz) and exactly matches paths ending with /cus-load.el and /charprop.el (including their variations, like /cus-load.el.gz and /charprop.el.gz). If a path in compile-angel-excluded-files ends with .el, it will automatically exclude the corresponding .el.gz variant when Emacs is configured to load .el.gz files.
  • Compile-angel provides options to allow enabling and disabling specific functions that should be advised (load, require, etc.).
  • Compile-angel allows enabling debug mode, which allows knowing exactly what compile-angel does. Additionally, compiled files and features are stored in variables that help identify what was compiled.
  • compile-angel-on-save-mode supports compiling indirect buffers (clones).
  • compile-angel-on-load-mode compiles features that have already been loaded to make sure that they are compiled.
  • Compile-Angel can use caching to enhance performance when locating the .el file corresponding to a given feature. Auto-compile does not compile features.
  • Supports both Vani 9C2C lla Emacs and Doom Emacs. For Doom Emacs, compile-angel ensures that the Doom Emacs user directory, Emacs directory, and modules directory are excluded from compilation. This is essential because .el files in these directories must not be compiled, or Doom may fail to load them correctly.
  • compile-angel-on-load-mode performs native compilation only when Emacs fails to do so. Explanation: When JIT compilation is enabled, loading a .elc file automatically triggers native compilation, making Emacs load the native-compiled version asynchronously and replacing the auto-compiled functions. (However, auto-compile disables native compilation by default, causing Emacs to skip native-compiling some files, even in save mode. When enabled, auto-compile compiles files before loading, but Emacs will still recompile them after loading the .elc file.)
  • Compile-Angel checks for unbalanced parentheses before compiling a file in save mode, without altering the cursor position, making it less intrusive than the default check-parens used by auto-compile.
  • Compile-Angel double-checks after packages are loaded to ensure that Emacs properly performs native compilation when JIT is enabled, as Emacs sometimes skips native-compiling .elc files that should be JIT compiled.
  • Prevent byte-compile-file from displaying Wrote messages in the Messages buffer unless compile-angel-verbose customization is set to t.
  • It has the ability to skip compiling features provided by Emacs core without associated Elisp files (e.g., pgtk, w32, lcms2, kqueue, emacs, mps, etc.). This includes features provided directly by C code as well as features provided by core Elisp that don't have their own .el files. These features are excluded from compilation attempts since they have no source files to compile.

Comments from users

Author and License

The compile-angel Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024-2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

About

Speed up Emacs: Auto Byte/Native-Compile all Elisp files (Alternative to: auto-compile)

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Contributors 3

  •  
  •  
  •  
0