unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Hi-Angel <hiangel999@gmail.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: help-gnu-emacs@gnu.org
Subject: Re: Lexical binding doesn't seem to be faster?
Date: Fri, 8 Mar 2019 16:33:50 +0300	[thread overview]
Message-ID: <CAHGDjgCXC01U7ewG9D=bx8BDtErvzR2yRAjKrUgG+UJ-iHyQRA@mail.gmail.com> (raw)
In-Reply-To: <jwvlg1q3qal.fsf-monnier+emacs@gnu.org>

On Fri, 8 Mar 2019 at 08:39, Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>
> > 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.  ]

Yeah, it's a ≈month old version from git, so it's pretty recent.

> > So, I took someone's function `with-timer` for benchmarking¹
>
> Any reason why you didn't use `benchmark(-run(-compiled))`?

Ah, thanks! Previously I only found `benchmark` function, but running

     (benchmark 10 (c-font-lock-fontify-region 0 (point-max)))

results in error "void-function jit-lock-bounds".

However the versions `benchmark-run` and `benchmark-run-compiled` works for me.

>
> >     ;;; -*- lexical-binding: t -*-   | 1.174s, 1.144s, 1.177ą;s, 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).

FTR: I re-benchmarked as `(benchmark-run-compiled 10
(c-font-lock-fontify-region 0 (point-max)))`, and also with `emacs -Q`
to make sure that none of addons can interfere (I'm using
color-identifiers which may add an overhead to fontification). For the
same reason I disabled GC (locally I too have it only enabled to run
at "idle time").

It's interesting that the difference almost disappeared:

    nil: (7.463936164 0 0.0) (7.520960622 0 0.0) (7.526411695999999 0
0.0) (7.537842362999999 0 0.0)
    t:   (7.617106151000001 0 0.0) (7.635044875 0 0.0)
(7.6383228789999995 0 0.0) (7.598431915 0 0.0)

"nil" still seems to be faster, but it may as well be a statistical variation.

----

Either way, I'm happy, as you suggested, to look at per-function
overhead to see if there's any difference. Do you think it's still
worth it? And how do I do it though? Shall I do (profiler-start), and
then evaluate the benchmark?



  parent reply	other threads:[~2019-03-08 13:33 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-06 23:36 Lexical binding doesn't seem to be faster? Hi-Angel
2019-03-08  5:39 ` Stefan Monnier
2019-03-08  8:30   ` tomas
2019-03-08 13:53     ` Stefan Monnier
2019-03-09  8:21       ` tomas
2019-03-08 13:33   ` Hi-Angel [this message]
2019-03-09 15:06     ` Stefan Monnier
2019-03-10 15:16       ` Hi-Angel
2019-03-10 16:14         ` Hi-Angel
2019-03-10 18:07         ` Stefan Monnier
2019-03-10 18:47           ` Hi-Angel
2019-03-10 18:59             ` Stefan Monnier
2019-03-10 19:53               ` Hi-Angel
2019-03-10 20:48                 ` Stefan Monnier
2019-03-10 21:22                   ` Hi-Angel
2019-03-11 19:16                     ` Hi-Angel
2019-03-11 19:26                       ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAHGDjgCXC01U7ewG9D=bx8BDtErvzR2yRAjKrUgG+UJ-iHyQRA@mail.gmail.com' \
    --to=hiangel999@gmail.com \
    --cc=help-gnu-emacs@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).