In principle, byte compiled code should run faster (maybe 2x, 3x?) than interpreted code.
In my limited experience, the speed-up gained by byte compiling my code has been
disappointingly modest (usually < 2x); it may well be that I need to adjust my coding style
to get the most out of byte compilation. Chris Wellons has written an article
about writing faster Elisp.
In recent versions of emacs (since version 28?), byte compiled code may be further
natively compiled into (platform dependent) machine language.
I believe the method used is the one describe in
Bringing
GNU Emacs to Native Code by A. Corallo, L. Nassi, & N. Manca.
Currently this page is mostly just a place holder. But the next section is worth taking a look at.
I find this check so useful that I routinely do it, using a command like this:
(defun ph/this-file-load (compile?) "Load the file the current buffer is visiting. Runs `check-parens' first, then `load-file'. when COMPILE? given, also run `byte-compile-file'." (interactive "P") (ph/check-parens); See below, but you can simply use check-parens (minibuffer-message "Check parens okay") (if (not (buffer-file-name)) (error "Cannot load. Current buffer is not visiting a file") (and ;; and here used to control flow (buffer-modified-p) (y-or-n-p "Save buffer before loading?") (save-buffer) ) (load-file (buffer-file-name)) (when compile? (byte-compile-file (buffer-file-name)) (display-buffer "*Compile-Log*") )))
As a slight refinement I use a customized version of check-parens which ignores
and file content occuring after "#@00".
"#@00" is a documented (albeit not encouraged) way to comment out the bottom half of a file.
I find it useful to put unfinished code snippets underneath a #@00.
For example.
(defun foo () (message "hello world") ) #@00 <-- anything after this is ignored by load-file and byte-compile-file (defun turing-machine-halts? (turing-machine) (let ((Alan (car turing-machine)) (Turing (cdr turing-machine)) ) (with-temp-buffer ;; Still thinking about the right way to do this... ;; Got so confused I forgot to balance parens! )load-file and byte-compile-file will skip anything after the 4 bytes #@00, but check-parens will not. I find it convenient to define a wrapper which does.
(defun ph/check-parens () "Like `check-parens', but ignore text after a skip to rest of file sequence." (interactive) (let ((point-ori (point))) (save-excursion (save-restriction (save-match-data (goto-char (point-min)) (when (search-forward (string ?# ?@ ?0 ?0) nil t) (when (< (point) point-ori) (minibuffer-message "Elisp skip-rest-of-file-mark found above current point.") ) (narrow-to-region (point-min) (point)) ) (check-parens) )))))Seems like a lot of code just to do such a simple thing, but I find it useful.
(search-forward (string ?# ?@ ?0 ?0) nil t)instead of simply
(search-forward "#@00" nil t); Not gonna work...
docstring wider than 80 characters warning
(defun my/search-forward-for-thing () "Search forward from point for an object which could be a macro name or a variable name or maybe a function name or else a gadget name." (...) )Byte compiling this will produce a
docstring wider than 80 characters warning
; as it rightly should.
Breaking the docsting up into several lines will not only silence the warning, but usually improve readability as well.
(defun my/search-forward-for-thing () "Search forward from point for object. The object could be: - a macro name - a variable name -a function name -a gadget name " (...) )
cl-defun
or cl-defstruct
can produce a docsting wider than warningcl-defun
and cl-defstruct
can also cause this warning.(cl-defun ph/grep-buffer/aux (search-forward-function query highlight-matches? &key (new-buf-name (concat "grep:" (buffer-name) ":" query))) "Create new buffer for QUERY, grab lines matching QUERY by the criterion of SEARCH-FORWARD-FUNCTION and put them in a new buffer with the matching part highlighted." (...) )Byte compiling this produces a
docstring wider than 80 characters
warning, even though the docstings
I provides do not include any long lines.(cl-defun ph/grep-buffer/aux (search-forward-function query highlight-matches? &key (new-buf-name (concat "grep:" (buffer-name) ":" query))) ;; No docstring here, but byte compiling will stil generate a docstring wider than error. (...) )I would call this behavior a bug on the part of the byte compiler. In fact, a bug report has been filed regarding this problem and perhaps someday will be fixed.
The warning is triggered by documentation automatically generated by cl-defun
, but this is not
evident when viewed using describe-function which yields this output:
ph/grep-buffer/aux is a Lisp closure in ‘ph-grep-buffer.el’. (ph/grep-buffer/aux SEARCH-FORWARD-FUNCTION QUERY HIGHLIGHT-MATCHES\? &key (NEW-BUF-NAME (concat "grep:" (buffer-name) ":" query))) For more information see the manuals. Create new buffer for QUERY, grab lines matching QUERY by the criterion of SEARCH-FORWARD-FUNCTION and put them in a new buffer with the matching part highlighted. [back]Showing no lines longer than 80! So what’s the problem? I’m not completely sure, but the value returned by the function
documentation
gives a strong hint.
(documentation 'ph/grep-buffer/aux) ;; returns "Create new buffer for QUERY, grab lines matching QUERY by the criterion of SEARCH-FORWARD-FUNCTION and put them in a new buffer with the matching part highlighted. (fn SEARCH-FORWARD-FUNCTION QUERY HIGHLIGHT-MATCHES\\? &key (NEW-BUF-NAME (concat \"grep:\" (buffer-name) \":\" query)))"The final line is indeed longer than 80 characters.
It is a special line parsed (but not shown) by describe-function to indicate calling conventions for functions and especially macros. For more information see the elisp info pages on "Function Documentation".
byte-compile-docstring-max-column
byte-compile-docstring-max-column
to a length longer than the default of 80 characters. One could do this globally with setq
,
but this would affect all source files. I would not want to do that because overall I think this warning is useful.
(even if the default length of 80 may be a bit too strict)
A better way is to use the file local variable concept to limit the effect to just the
source file in which the problem occurs. One can use the special first line of the
file to set byte-compile-docstring-max-column
to a large enough value.
For example, in my particular case I use:
;;; ph-grep-buffer.el --- -*- lexical-binding: t; byte-compile-docstring-max-column: 115 -*-As the first line of file
ph-grep-buffer.el
.ph/grep-buffer/aux
.
This file local adjustment to byte-compile-docstring-max-column
will not affect warnings when compiling other source files,
but certainly will prevent potential warnings regarding other docstings in ph-grep-buffer.el
.
Even so, I still try to keep docsting lines within 80 character.
The command what-cursor-position (default binding C-x =
) is useful to see what column point
is on.