# Optimising Dash.el

DevFeed: [Optimising Dash.el](<https://devfeed.tech/articles/optimising-dash-el-22016.md>)

Original publisher: [Read original article](<http://www.wilfred.me.uk/blog/2017/07/29/optimising-dash-el/>)

Author: Wilfred Hughes

Published: 2017-07-29T00:00:00Z

Content type: tutorial

Language: en

Sources: [Wilfred Hughes](<https://devfeed.tech/sources/wilfred-hughes.md>)

Topics: [Emacs](<https://devfeed.tech/topics/emacs.md>), [Library](<https://devfeed.tech/topics/library.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Code](<https://devfeed.tech/topics/code.md>), [Open Source](<https://devfeed.tech/topics/open-source.md>)

Tags: [code](<https://devfeed.tech/tags/code.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [emacs](<https://devfeed.tech/tags/emacs.md>), [library](<https://devfeed.tech/tags/library.md>), [open-source](<https://devfeed.tech/tags/open-source.md>), [optimisation](<https://devfeed.tech/tags/optimisation.md>)

## AI overview

This tutorial examines performance optimization techniques in Dash.el and Emacs Lisp. It benchmarks iterative code against mapcar, compares wrapper functions, aliases, and primitives, and explains how Emacs byte compilation can improve or eliminate function calls. The article notes that the latest Dash.el version includes these improvements.

## Source excerpt

Dash.el is a lovely library, and one of the most popular on MELPA. If we can squeeze every last drop of performance out of it, everyone benefits. Let's take a look at the black art of making elisp faster. Measure First! Chris Wellons has a great optimisation blog post that discusses the performance overhead of creating lambdas with mapcar. If we look at --map, it does indeed create anonymous functions: (defmacro --map (form list) "Anaphoric form of `-map'." `(mapcar (lambda (it) ,form) ,list)) Creating anonymous functions instantiates a closure, which isn't free. Let's write an iterative equivalent: (defmacro --map-loop (form list) (declare (debug (form form))) (let ((result-sym (make-symbol "result"))) `(let (,result-sym) (dolist (it ,list) (push ,form ,result-sym)) (nreverse ,result-sym)))) List Length mapcar (seconds) dolist (seconds) 1 0.000010 0.000028 1,000 0.0027 0.0079 100,000 0.74 1.24 (Full benchmark code here.) Surprisingly, mapcar is consistently faster in this particular benchmark! Other Emacsers have observed dolist outperforming mapcar for short lists. mapcar is primitive, and primitives tend to be fast. dolist clearly isn't a speedup in all situations. Let's try something else. Matching Primitive Performance Some dash.el functions are equivalent to primitive functions. For example, -first-item is equivalent to car, -drop is equivalent to nthcdr. We could write -first-item like this: (defun -first-item (lst) (car lst)) However, this adds the overhead of an extra function call compared with calling car directly. Instead, dash.el does this: (defalias '-first-item 'car) Let's do a small benchmark, to ensure that defalias giving us the peformance we want: Approach time (seconds) wrapper function 0.1399 alias 0.0055 use car directly 0.0050 (Full benchmark code here.) For shame! Our alias still isn't as fast as using the primitive. Let's compare the disassembly using M-x disassemble. (defalias 'car-alias 'car) (defun use-car-alias (x) (car-alias x)) ;; byte