pages_akib/blog/emacs-lisp-is-fast.html

1297 lines
36 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<!-- 2022-12-15 Thu 21:42 +06 -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Emacs Lisp is Probably Faster Than What You Think | Akib Azmain Turja</title>
<meta name="author" content="Akib Azmain Turja" />
<meta name="generator" content="Org Mode" />
<style>
#content { max-width: 60em; margin: auto; }
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #f2f2f2;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: auto;
}
pre.src:before {
display: none;
position: absolute;
top: -8px;
right: 12px;
padding: 3px;
color: #555;
background-color: #f2f2f299;
}
pre.src:hover:before { display: inline; margin-top: 14px;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-authinfo::before { content: 'Authinfo'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'Javascript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { }
</style>
<style>
body { font-size: 110%; }
#preamble { max-width: 54rem; margin-top: auto; margin-bottom: auto;
margin-left: auto; margin-right: auto; }
#content { max-width: 54rem; margin-top: auto; margin-bottom: auto;
margin-left: auto; margin-right: auto; }
.title { text-align: left; }
.subtitle { text-align: left; }
.timestamp { color: #333333; font-size: 0.9em; }
.footer { font-size: 80%; line-height: 1.5em; }
#postamble { max-width: 54rem; margin-top: auto; margin-bottom: auto;
margin-left: auto; margin-right: auto; }
</style><link rel="me" href="https://hostux.social/@akib"/>
<!-- CSS generated from `default' theme. -->
<style type="text/css">
<!--
.org-ansi-color-black {
/* ansi-color-black */
color: #000000;
background-color: #000000;
}
.org-ansi-color-blue {
/* ansi-color-blue */
color: #0000ee;
background-color: #0000ee;
}
.org-ansi-color-bold {
/* ansi-color-bold */
font-weight: bold;
}
.org-ansi-color-bright-black {
/* ansi-color-bright-black */
color: #4d4d4d;
background-color: #4d4d4d;
}
.org-ansi-color-bright-blue {
/* ansi-color-bright-blue */
color: #0000ff;
background-color: #0000ff;
}
.org-ansi-color-bright-cyan {
/* ansi-color-bright-cyan */
color: #00eeee;
background-color: #00eeee;
}
.org-ansi-color-bright-green {
/* ansi-color-bright-green */
color: #00ee00;
background-color: #00ee00;
}
.org-ansi-color-bright-magenta {
/* ansi-color-bright-magenta */
color: #ee00ee;
background-color: #ee00ee;
}
.org-ansi-color-bright-red {
/* ansi-color-bright-red */
color: #ee0000;
background-color: #ee0000;
}
.org-ansi-color-bright-white {
/* ansi-color-bright-white */
color: #ffffff;
background-color: #ffffff;
}
.org-ansi-color-bright-yellow {
/* ansi-color-bright-yellow */
color: #eeee00;
background-color: #eeee00;
}
.org-ansi-color-cyan {
/* ansi-color-cyan */
color: #00cdcd;
background-color: #00cdcd;
}
.org-ansi-color-faint {
}
.org-ansi-color-fast-blink {
}
.org-ansi-color-green {
/* ansi-color-green */
color: #00cd00;
background-color: #00cd00;
}
.org-ansi-color-inverse {
}
.org-ansi-color-italic {
/* ansi-color-italic */
font-style: italic;
}
.org-ansi-color-magenta {
/* ansi-color-magenta */
color: #cd00cd;
background-color: #cd00cd;
}
.org-ansi-color-red {
/* ansi-color-red */
color: #cd0000;
background-color: #cd0000;
}
.org-ansi-color-slow-blink {
}
.org-ansi-color-underline {
/* ansi-color-underline */
text-decoration: underline;
}
.org-ansi-color-white {
/* ansi-color-white */
color: #e5e5e5;
background-color: #e5e5e5;
}
.org-ansi-color-yellow {
/* ansi-color-yellow */
color: #cdcd00;
background-color: #cdcd00;
}
.org-bold {
/* bold */
font-weight: bold;
}
.org-bold-italic {
/* bold-italic */
font-weight: bold;
font-style: italic;
}
.org-border {
}
.org-buffer-menu-buffer {
/* buffer-menu-buffer */
font-weight: bold;
}
.org-builtin {
/* font-lock-builtin-face */
color: #483d8b;
}
.org-button {
/* button */
color: #3a5fcd;
text-decoration: underline;
}
.org-calendar-month-header {
/* calendar-month-header */
color: #0000ff;
}
.org-calendar-today {
/* calendar-today */
text-decoration: underline;
}
.org-calendar-weekday-header {
/* calendar-weekday-header */
color: #008b8b;
}
.org-calendar-weekend-header {
/* calendar-weekend-header */
color: #b22222;
}
.org-child-frame-border {
}
.org-comint-highlight-input {
/* comint-highlight-input */
font-weight: bold;
}
.org-comint-highlight-prompt {
/* comint-highlight-prompt */
color: #0000cd;
}
.org-comment {
/* font-lock-comment-face */
color: #b22222;
}
.org-comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
.org-completions-common-part {
/* completions-common-part */
color: #0000cd;
}
.org-completions-first-difference {
/* completions-first-difference */
font-weight: bold;
}
.org-completions-group-separator {
/* completions-group-separator */
color: #7f7f7f;
text-decoration: line-through;
}
.org-completions-group-title {
/* completions-group-title */
color: #7f7f7f;
font-style: italic;
}
.org-completions-highlight {
/* completions-highlight */
background-color: #b4eeb4;
}
.org-confusingly-reordered {
/* confusingly-reordered */
text-decoration: underline;
}
.org-constant {
/* font-lock-constant-face */
color: #008b8b;
}
.org-cursor {
/* cursor */
background-color: #000000;
}
.org-default {
/* default */
color: #000000;
background-color: #ffffff;
}
.org-diary {
/* diary */
color: #ff0000;
}
.org-doc {
/* font-lock-doc-face */
color: #8b2252;
}
.org-doc-markup {
/* font-lock-doc-markup-face */
color: #008b8b;
}
.org-eldoc-highlight-function-argument {
/* eldoc-highlight-function-argument */
font-weight: bold;
}
.org-elisp-shorthand-font-lock {
/* elisp-shorthand-font-lock-face */
color: #00ffff;
}
.org-error {
/* error */
color: #ff0000;
font-weight: bold;
}
.org-escape-glyph {
/* escape-glyph */
color: #a52a2a;
}
.org-file-name-shadow {
/* file-name-shadow */
color: #7f7f7f;
}
.org-fill-column-indicator {
/* fill-column-indicator */
color: #7f7f7f;
}
.org-fixed-pitch {
}
.org-fixed-pitch-serif {
}
.org-fringe {
/* fringe */
background-color: #f2f2f2;
}
.org-function-name {
/* font-lock-function-name-face */
color: #0000ff;
}
.org-glyphless-char {
/* glyphless-char */
font-size: 60%;
}
.org-header-line {
/* header-line */
color: #333333;
background-color: #e5e5e5;
}
.org-header-line-highlight {
}
.org-help-argument-name {
/* help-argument-name */
font-style: italic;
}
.org-help-for-help-header {
/* help-for-help-header */
font-size: 126%;
}
.org-help-key-binding {
/* help-key-binding */
color: #00008b;
background-color: #f5f5f5;
}
.org-highlight {
/* highlight */
background-color: #b4eeb4;
}
.org-holiday {
/* holiday */
background-color: #ffc0cb;
}
.org-homoglyph {
/* homoglyph */
color: #a52a2a;
}
.org-icon {
}
.org-icon-button {
/* icon-button */
color: #000000;
background-color: #808080;
}
.org-internal-border {
}
.org-isearch {
/* isearch */
color: #b0e2ff;
background-color: #cd00cd;
}
.org-isearch-fail {
/* isearch-fail */
background-color: #ffc1c1;
}
.org-isearch-group-1 {
/* isearch-group-1 */
color: #b0e2ff;
background-color: #f000f0;
}
.org-isearch-group-2 {
/* isearch-group-2 */
color: #b0e2ff;
background-color: #a000a0;
}
.org-italic {
/* italic */
font-style: italic;
}
.org-keyword {
/* font-lock-keyword-face */
color: #a020f0;
}
.org-lazy-highlight {
/* lazy-highlight */
background-color: #afeeee;
}
.org-line-number-current-line {
/* line-number-current-line */
color: #7f7f7f;
background-color: #ffffff;
}
.org-line-number-major-tick {
/* line-number-major-tick */
background-color: #d9d9d9;
font-weight: bold;
}
.org-line-number-minor-tick {
/* line-number-minor-tick */
background-color: #f2f2f2;
font-weight: bold;
}
.org-link {
/* link */
color: #3a5fcd;
text-decoration: underline;
}
.org-link-visited {
/* link-visited */
color: #8b008b;
text-decoration: underline;
}
.org-match {
/* match */
background-color: #fff68f;
}
.org-menu {
}
.org-minibuffer-prompt {
/* minibuffer-prompt */
color: #0000cd;
}
.org-mode-line {
/* mode-line */
color: #000000;
background-color: #bfbfbf;
}
.org-mode-line-active {
/* mode-line-active */
color: #000000;
background-color: #bfbfbf;
}
.org-mode-line-buffer-id {
/* mode-line-buffer-id */
font-weight: bold;
}
.org-mode-line-emphasis {
/* mode-line-emphasis */
font-weight: bold;
}
.org-mode-line-highlight {
}
.org-mode-line-inactive {
/* mode-line-inactive */
color: #333333;
background-color: #e5e5e5;
}
.org-mouse {
}
.org-mouse-drag-and-drop-region {
/* mouse-drag-and-drop-region */
background-color: #eedc82;
}
.org-negation-char {
}
.org-next-error {
/* next-error */
background-color: #eedc82;
}
.org-next-error-message {
/* next-error-message */
background-color: #b4eeb4;
}
.org-nobreak-hyphen {
/* nobreak-hyphen */
color: #a52a2a;
}
.org-nobreak-space {
/* nobreak-space */
color: #a52a2a;
text-decoration: underline;
}
.org-org-agenda-calendar-event {
/* org-agenda-calendar-event */
color: #000000;
background-color: #ffffff;
}
.org-org-agenda-calendar-sexp {
/* org-agenda-calendar-sexp */
color: #000000;
background-color: #ffffff;
}
.org-org-agenda-clocking {
/* org-agenda-clocking */
background-color: #ffff00;
}
.org-org-agenda-column-dateline {
/* org-agenda-column-dateline */
background-color: #e5e5e5;
}
.org-org-agenda-current-time {
/* org-agenda-current-time */
color: #b8860b;
}
.org-org-agenda-date {
/* org-agenda-date */
color: #0000ff;
}
.org-org-agenda-date-today {
/* org-agenda-date-today */
color: #0000ff;
font-weight: bold;
font-style: italic;
}
.org-org-agenda-date-weekend {
/* org-agenda-date-weekend */
color: #0000ff;
font-weight: bold;
}
.org-org-agenda-date-weekend-today {
/* org-agenda-date-weekend-today */
color: #0000ff;
font-weight: bold;
font-style: italic;
}
.org-org-agenda-diary {
/* org-agenda-diary */
color: #000000;
background-color: #ffffff;
}
.org-org-agenda-dimmed-todo {
/* org-agenda-dimmed-todo-face */
color: #7f7f7f;
}
.org-org-agenda-done {
/* org-agenda-done */
color: #228b22;
}
.org-org-agenda-filter-category {
/* org-agenda-filter-category */
color: #000000;
background-color: #bfbfbf;
}
.org-org-agenda-filter-effort {
/* org-agenda-filter-effort */
color: #000000;
background-color: #bfbfbf;
}
.org-org-agenda-filter-regexp {
/* org-agenda-filter-regexp */
color: #000000;
background-color: #bfbfbf;
}
.org-org-agenda-filter-tags {
/* org-agenda-filter-tags */
color: #000000;
background-color: #bfbfbf;
}
.org-org-agenda-restriction-lock {
/* org-agenda-restriction-lock */
background-color: #eeeeee;
}
.org-org-agenda-structure {
/* org-agenda-structure */
color: #0000ff;
}
.org-org-agenda-structure-secondary {
/* org-agenda-structure-secondary */
color: #0000ff;
}
.org-org-archived {
/* org-archived */
color: #7f7f7f;
}
.org-org-block {
/* org-block */
color: #7f7f7f;
}
.org-org-block-begin-line {
/* org-block-begin-line */
color: #b22222;
}
.org-org-block-end-line {
/* org-block-end-line */
color: #b22222;
}
.org-org-checkbox {
/* org-checkbox */
font-weight: bold;
}
.org-org-checkbox-statistics-done {
/* org-checkbox-statistics-done */
color: #228b22;
font-weight: bold;
}
.org-org-checkbox-statistics-todo {
/* org-checkbox-statistics-todo */
color: #ff0000;
font-weight: bold;
}
.org-org-cite {
/* org-cite */
color: #3a5fcd;
text-decoration: underline;
}
.org-org-cite-key {
/* org-cite-key */
color: #3a5fcd;
text-decoration: underline;
}
.org-org-clock-overlay {
/* org-clock-overlay */
color: #000000;
background-color: #d3d3d3;
}
.org-org-code {
/* org-code */
color: #7f7f7f;
}
.org-org-column {
/* org-column */
background-color: #e5e5e5;
}
.org-org-column-title {
/* org-column-title */
background-color: #e5e5e5;
font-weight: bold;
text-decoration: underline;
}
.org-org-date {
/* org-date */
color: #a020f0;
text-decoration: underline;
}
.org-org-date-selected {
/* org-date-selected */
color: #ff0000;
}
.org-org-default {
/* org-default */
color: #000000;
background-color: #ffffff;
}
.org-org-dispatcher-highlight {
/* org-dispatcher-highlight */
color: #00008b;
background-color: #c6e2ff;
font-weight: bold;
}
.org-org-document-info {
/* org-document-info */
color: #191970;
}
.org-org-document-info-keyword {
/* org-document-info-keyword */
color: #7f7f7f;
}
.org-org-document-title {
/* org-document-title */
color: #191970;
font-weight: bold;
}
.org-org-done {
/* org-done */
color: #228b22;
font-weight: bold;
}
.org-org-drawer {
/* org-drawer */
color: #0000ff;
}
.org-org-ellipsis {
/* org-ellipsis */
color: #b8860b;
text-decoration: underline;
}
.org-org-footnote {
/* org-footnote */
color: #a020f0;
text-decoration: underline;
}
.org-org-formula {
/* org-formula */
color: #b22222;
}
.org-org-headline-done {
/* org-headline-done */
color: #bc8f8f;
}
.org-org-headline-todo {
/* org-headline-todo */
color: #8b0000;
}
.org-org-hide {
/* org-hide */
color: #ffffff;
}
.org-org-imminent-deadline {
/* org-imminent-deadline */
color: #ff0000;
font-weight: bold;
}
.org-org-latex-and-related {
/* org-latex-and-related */
color: #8b4513;
}
.org-org-level-1 {
/* org-level-1 */
color: #0000ff;
}
.org-org-level-2 {
/* org-level-2 */
color: #a0522d;
}
.org-org-level-3 {
/* org-level-3 */
color: #a020f0;
}
.org-org-level-4 {
/* org-level-4 */
color: #b22222;
}
.org-org-level-5 {
/* org-level-5 */
color: #228b22;
}
.org-org-level-6 {
/* org-level-6 */
color: #008b8b;
}
.org-org-level-7 {
/* org-level-7 */
color: #483d8b;
}
.org-org-level-8 {
/* org-level-8 */
color: #8b2252;
}
.org-org-link {
/* org-link */
color: #3a5fcd;
text-decoration: underline;
}
.org-org-list-dt {
/* org-list-dt */
font-weight: bold;
}
.org-org-macro {
/* org-macro */
color: #8b4513;
}
.org-org-meta-line {
/* org-meta-line */
color: #b22222;
}
.org-org-mode-line-clock {
/* org-mode-line-clock */
color: #000000;
background-color: #bfbfbf;
}
.org-org-mode-line-clock-overrun {
/* org-mode-line-clock-overrun */
color: #000000;
background-color: #ff0000;
}
.org-org-priority {
/* org-priority */
color: #a020f0;
}
.org-org-property-value {
}
.org-org-quote {
/* org-quote */
color: #7f7f7f;
}
.org-org-scheduled {
/* org-scheduled */
color: #006400;
}
.org-org-scheduled-previously {
/* org-scheduled-previously */
color: #b22222;
}
.org-org-scheduled-today {
/* org-scheduled-today */
color: #006400;
}
.org-org-sexp-date {
/* org-sexp-date */
color: #a020f0;
}
.org-org-special-keyword {
/* org-special-keyword */
color: #a020f0;
}
.org-org-table {
/* org-table */
color: #0000ff;
}
.org-org-table-header {
/* org-table-header */
color: #000000;
background-color: #d3d3d3;
}
.org-org-tag {
/* org-tag */
font-weight: bold;
}
.org-org-tag-group {
/* org-tag-group */
font-weight: bold;
}
.org-org-target {
/* org-target */
text-decoration: underline;
}
.org-org-time-grid {
/* org-time-grid */
color: #b8860b;
}
.org-org-todo {
/* org-todo */
color: #ff0000;
font-weight: bold;
}
.org-org-upcoming-deadline {
/* org-upcoming-deadline */
color: #b22222;
}
.org-org-upcoming-distant-deadline {
/* org-upcoming-distant-deadline */
color: #000000;
background-color: #ffffff;
}
.org-org-verbatim {
/* org-verbatim */
color: #7f7f7f;
}
.org-org-verse {
/* org-verse */
color: #7f7f7f;
}
.org-org-warning {
/* org-warning */
color: #ff0000;
font-weight: bold;
}
.org-outline-1 {
/* outline-1 */
color: #0000ff;
}
.org-outline-2 {
/* outline-2 */
color: #a0522d;
}
.org-outline-3 {
/* outline-3 */
color: #a020f0;
}
.org-outline-4 {
/* outline-4 */
color: #b22222;
}
.org-outline-5 {
/* outline-5 */
color: #228b22;
}
.org-outline-6 {
/* outline-6 */
color: #008b8b;
}
.org-outline-7 {
/* outline-7 */
color: #483d8b;
}
.org-outline-8 {
/* outline-8 */
color: #8b2252;
}
.org-preprocessor {
/* font-lock-preprocessor-face */
color: #483d8b;
}
.org-query-replace {
/* query-replace */
color: #b0e2ff;
background-color: #cd00cd;
}
.org-regexp-grouping-backslash {
/* font-lock-regexp-grouping-backslash */
font-weight: bold;
}
.org-regexp-grouping-construct {
/* font-lock-regexp-grouping-construct */
font-weight: bold;
}
.org-region {
/* region */
background-color: #eedc82;
}
.org-scroll-bar {
}
.org-secondary-selection {
/* secondary-selection */
background-color: #ffff00;
}
.org-separator-line {
/* separator-line */
background-color: #a0a0a0;
font-size: 10%;
}
.org-shadow {
/* shadow */
color: #7f7f7f;
}
.org-show-paren-match {
/* show-paren-match */
background-color: #40e0d0;
}
.org-show-paren-match-expression {
/* show-paren-match-expression */
background-color: #40e0d0;
}
.org-show-paren-mismatch {
/* show-paren-mismatch */
color: #ffffff;
background-color: #a020f0;
}
.org-string {
/* font-lock-string-face */
color: #8b2252;
}
.org-success {
/* success */
color: #228b22;
font-weight: bold;
}
.org-tab-bar {
/* tab-bar */
color: #000000;
background-color: #d9d9d9;
}
.org-tab-bar-tab {
/* tab-bar-tab */
color: #000000;
background-color: #d9d9d9;
}
.org-tab-bar-tab-group-current {
/* tab-bar-tab-group-current */
color: #000000;
background-color: #d9d9d9;
font-weight: bold;
}
.org-tab-bar-tab-inactive {
/* tab-bar-tab-inactive */
color: #000000;
background-color: #bfbfbf;
}
.org-tab-line {
/* tab-line */
color: #000000;
background-color: #d9d9d9;
font-size: 90%;
}
.org-table-cell {
/* table-cell */
color: #e5e5e5;
background-color: #0000ff;
}
.org-tabulated-list-fake-header {
/* tabulated-list-fake-header */
font-weight: bold;
text-decoration: underline;
text-decoration: overline;
}
.org-tool-bar {
/* tool-bar */
color: #000000;
background-color: #bfbfbf;
}
.org-tooltip {
/* tooltip */
color: #000000;
background-color: #ffffe0;
}
.org-trailing-whitespace {
/* trailing-whitespace */
background-color: #ff0000;
}
.org-tty-menu-disabled {
/* tty-menu-disabled-face */
color: #d3d3d3;
background-color: #0000ff;
}
.org-tty-menu-enabled {
/* tty-menu-enabled-face */
color: #ffff00;
background-color: #0000ff;
font-weight: bold;
}
.org-tty-menu-selected {
/* tty-menu-selected-face */
background-color: #ff0000;
}
.org-type {
/* font-lock-type-face */
color: #228b22;
}
.org-underline {
/* underline */
text-decoration: underline;
}
.org-variable-name {
/* font-lock-variable-name-face */
color: #a0522d;
}
.org-variable-pitch {
}
.org-variable-pitch-text {
/* variable-pitch-text */
font-size: 110%;
}
.org-vc-conflict-state {
}
.org-vc-edited-state {
}
.org-vc-locally-added-state {
}
.org-vc-locked-state {
}
.org-vc-missing-state {
}
.org-vc-needs-update-state {
}
.org-vc-removed-state {
}
.org-vc-state-base {
}
.org-vc-up-to-date-state {
}
.org-vertical-border {
}
.org-warning {
/* font-lock-warning-face */
color: #ff0000;
font-weight: bold;
}
.org-warning-1 {
/* warning */
color: #ff8c00;
font-weight: bold;
}
.org-window-divider {
/* window-divider */
color: #999999;
}
.org-window-divider-first-pixel {
/* window-divider-first-pixel */
color: #cccccc;
}
.org-window-divider-last-pixel {
/* window-divider-last-pixel */
color: #666666;
}
-->
</style>
</head>
<body>
<header id="preamble" class="status">
<div class='navigation'>
<a href="/index.html">Home</a>
- <a href="/about.html">About</a>
- <a href="/blog.html">Blog</a>
- <a href="/contact.html">Contact</a>
</div>
</header>
<main id="content" class="content">
<header>
<h1 class="title">Emacs Lisp is Probably Faster Than What You Think</h1>
<p class="subtitle" role="doc-subtitle">December 15, 2022</p>
</header><p>
Emacs Lisp is the native language of GNU <a href="https://gnu.org/software/emacs">Emacs</a>, an interpreted
language. We are used to think that interpreted language are slow.
Yes, they are indeed slower than compiled languages like C and
Assembly. But with the latest additions like JIT, native-compilation
and various optimizations, they are catching up with compiled
languages.
</p>
<p>
I got the first surprise when I tested <a href="https://gnu.org/software/guile">GNU Guile</a>. It is really fast,
as fast as C in many cases, when JIT is enabled. However, Emacs Lisp
is not so fast, but it's OK for most use cases.
</p>
<p>
But two weeks ago, I got a surprise with Emacs Lisp. I was
implementing multi-column character support in <a href="https://codeberg.org/akib/emacs-eat">Eat</a>. I found an
efficient way implement this while not breaking existing code. But it
had one problem, as you might have already guessed, I needed to find
all multi-column and zero column (yes, there are some) characters in
the output. At first, I used a binary search-like algorithm using
<code>string-width</code>, as I thought C code is fast. Not only it produced too
much garbage, it also didn't work for obvious reason. Understanding
the problem, I decided to use <code>char-width</code>. After the initial
implementation, I thought it was going to make Eat much slow, since it
needs to check every character of the output string. But to my utter
surprise, it didn't slow down Eat more than 3-4%. So I happily
<a href="https://codeberg.org/akib/emacs-eat/commit/9d14bbeaa5c7f5499dcde485ef3a539f8590088e">committed and published it</a>.
</p>
<p>
Two days ago, learning from the previous incident, I thought to try
replacing the regular expressions based output parser with a parses
output one character at a time. After implementing it, I tested it.
But it was not measurably faster than the old code, so I decided to
abandon the ready to commit change, out of the fear of breaking
programs.
</p>
<p>
But today, I thought to give it another change. My browser was open
when I tested back then. The browser usually takes up all my memory,
slowing down everything on my 4 GB RAM computer. But this time the
browser was not running. After testing, I found that it is actually
about 5% faster when Eat is native-compiled, which was more than I
expected. That means the Emacs Lisp based parser is faster than thea
simple regular expression based parser, despite regular expressions
are implemented in C. As a bonus, the change didn't make the code
more complicated (I think it simplified the code instead). Being
happy with it, I decided to <a href="https://codeberg.org/akib/emacs-eat/commit/61695d9671368cf216587a28ee2ea9d90ccf4b1a">commit and publish it</a>.
</p>
<p>
So the conclusion is that Emacs Lisp can be faster than C when the
code is efficient and optimized enough. So before you blame Emacs for
your slow Emacs Lisp code, first check what you wrote!
</p>
</main>
<footer id="postamble" class="status">
<hr/><div>
Comments can be send to my email address <a href='mailto:<a href="mailto:akib@disroot.org">akib@disroot.org</a>'><a href="mailto:akib@disroot.org">akib@disroot.org</a></a>.
</div><br/>
<div class='footer'>
<div>Last updated on 2022-12-15 Thu 21:42 +06.<br/>
Copyright © 2022 Akib Azmain Turja.<br/>
</div><br/>
<div>
Unless otherwise stated, contents are licensed under the terms of the
CC-BY-SA-4.0 and code samples are licensed under the terms of the GNU
General Public License as published by the Free Software Foundation;
either version 3, or (at your option) any later version.
</div><br/>
<div class='footer-generator'>
Made with
<a href="https://gnu.org/software/emacs/">GNU Emacs</a> 29.0.50
(<a href="https://orgmode.org">Org</a> mode 9.5.5) on
<a href="https://gnu.org/">GNU</a>.
</div></div>
</footer>
</body>
</html>