help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Lexical binding doesn't seem to be faster?


From: Stefan Monnier
Subject: Re: Lexical binding doesn't seem to be faster?
Date: Fri, 08 Mar 2019 00:39:09 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

> I've stumbled upon a discussion about converting Emacs code to a
> faster lexical-binding and that help needed.

While the semantics of lexical-binding does offer more opportunities for
optimization, the current Elisp implementation does not make much effort
to take advantage of it, so compiling with lexical-binding may generate
code that goes marginally faster sometimes and marginally slower at
other times simply because the code generated is a bit different, but in
my experience there's rarely much difference either way.

> The first bad sign happened to be sizes of cc-mode.elc:
>
>     ;;; -*- lexical-binding: t -*-   | 217581
>     ;;; -*- lexical-binding: nil -*- | 212542
>
> Lexical-binding bloats byte-code by 5KB. Odd.

Indeed, in my experience lexical-binding tends to generate slightly
larger .elc files.  Not sure why, actually: I never bothered
to investigate.  Intuitively, I can't think of a good reason why that
should be the case, so it may be a simple performance bug.

[ BTW, a performance problem with lexical-binding was found during
  Emacs-24 which got fixed in Emacs-25, so I assume you're using
  a recent enough version which is not affected by this problem.  ]

> So, I took someone's function `with-timer` for benchmarking┬╣;

Any reason why you didn't use `benchmark(-run(-compiled))`?

>     ;;; -*- lexical-binding: t -*-   | 1.174s, 1.144s, 1.177s, 1.125s, 1.177s
>     ;;; -*- lexical-binding: nil -*- | 1.037s, 1.061s, 1.037s, 1.037s, 0.991s

Hmmm... ~13% slowdown isn't terribly bad, but it's indeed
rather disappointing.  It'd be nice to try and compare the profiles
in those two cases to try and see if the slowdown is just evenly spread
(which would suck) or is neatly limited to a specific spot (which would
be great).

FWIW, the usual case where lexical-binding leads to bigger&slower code
is when you pass a lambda-expression to another function and that
lambda-expression has free variables (in the lexical-binding case, it
requires building a closure which is rather costly currently, whereas in
the dynamic-binding case it relies on the dynamic-scoping instead).

So, for example, calls to `mapcar` where you pass a (lambda ...) that
refers to variables from the context tend to be a bit more expensive
(tho each iteration may be very slightly faster because the references
to those variables can be slightly cheaper, so the overall impact may
depend on the number of elements in the list).


        Stefan




reply via email to

[Prev in Thread] Current Thread [Next in Thread]