On elisp running native

classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

On elisp running native

Andrea Corallo
Hi all.  I'd like share the investigation I've been working on to give
Emacs the ability to compile and run elisp as native code.

Despite being in very early stage it's functional and shows some quite
interesting potential in terms of performance benefit.  I then thought
was at a good stage to be shared and discussed.

I wrote a small page to describe what I did and how it works plus the
current status not to have the information spread in various mails.

http://akrl.sdf.org/gccemacs.html

The repository is hosted at the following link and the current patch
is attached.

https://gitlab.com/koral/gccemacs

In case this is of interest I'd love to see it as feature branch to
better collect feedback and work on its evolution.

Best Regards

  Andrea
 
--
[hidden email]

gccemacs.patch (222K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Óscar Fuentes
Andrea Corallo <[hidden email]> writes:

> Hi all.  I'd like share the investigation I've been working on to give
> Emacs the ability to compile and run elisp as native code.
>
> Despite being in very early stage it's functional and shows some quite
> interesting potential in terms of performance benefit.  I then thought
> was at a good stage to be shared and discussed.
>
> I wrote a small page to describe what I did and how it works plus the
> current status not to have the information spread in various mails.
>
> http://akrl.sdf.org/gccemacs.html

   nbody is ~3.5x faster with

No, it is ~4.6 faster :-)

Please consider using factors instead of % for indicating the speed
boost on the table. Percentages are confusing.

One interesting topic is how your approach affects the features that
characterizes Emacs, such as the ability to redefine almost anything at
runtime, instrospection, debugging, etc.


Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Lars Ingebrigtsen
In reply to this post by Andrea Corallo
Andrea Corallo <[hidden email]> writes:

> I wrote a small page to describe what I did and how it works plus the
> current status not to have the information spread in various mails.
>
> http://akrl.sdf.org/gccemacs.html

Wow, that's exciting!

A couple of questions:

> * Native compiler is not re-entrant:
>
>  Just top level functions are native compiled, the others (lambda
>  included) are still kept as byte-code.

Is that a fundamental limitation, or have you just not gotten around to
it yet?

Also, I'm wondering about debugging: I spend a lot of time in Emacs just
edebugging or in the *Backtrace* buffer.  Does the natively compiled
code mean that all that has to happen in gdb now?

--
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Andrea Corallo
In reply to this post by Óscar Fuentes
Óscar Fuentes <[hidden email]> writes:

> Andrea Corallo <[hidden email]> writes:
>
>> Hi all.  I'd like share the investigation I've been working on to give
>> Emacs the ability to compile and run elisp as native code.
>>
>> Despite being in very early stage it's functional and shows some quite
>> interesting potential in terms of performance benefit.  I then thought
>> was at a good stage to be shared and discussed.
>>
>> I wrote a small page to describe what I did and how it works plus the
>> current status not to have the information spread in various mails.
>>
>> http://akrl.sdf.org/gccemacs.html
>
>    nbody is ~3.5x faster with
>
> No, it is ~4.6 faster :-)
>
> Please consider using factors instead of % for indicating the speed
> boost on the table. Percentages are confusing.

Ops... Apparently this was sufficently confusing to confuse my self :)

Should be fixed by now.

>
> One interesting topic is how your approach affects the features that
> characterizes Emacs, such as the ability to redefine almost anything at
> runtime, instrospection, debugging, etc.
>

Good points:

* Debuggability

  What you get from native compiled code should be more or less what
  you get from the byte-compiled one.

  The caveat is that at speed >= 2 currently I'm optimizing out the
  funcall trampoline for calling primitive C functions.  This should
  impact the back-trace accuracy.

  A possible solution would be to emit some native code to record that
  before each call.  Another one is not to perform this optimization
  at all.  This is a trade-off.

* Introspection

  As for the previous point this should be the same of what you get with
  the byte-compiled code (once I get the doc working).

* Ability redefine to functions at run-time

  Nothing should change up to speed 2 here.  At speed 3 the compiler
  can in-line within the compilation unit so you have to recompile it
  all.

  I see speed 3 like the setting where you allow a bit more extreme
  optimizations to be performed.  Something to be used not often and
  with extreme care.

Andrea

--
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Stefan Monnier
In reply to this post by Andrea Corallo
> Hi all.  I'd like share the investigation I've been working on to give
> Emacs the ability to compile and run elisp as native code.

This looks great, thanks.

[ I wasn't able to follow all the explanations at
  http://akrl.sdf.org/gccemacs.html, such as the one around "function
  frames", with which I'm not familiar.  Are these like activation
  frames? ]

A few questions:

- How did you get there?  I see some "we" in the web page, which makes
  it sound like you weren't completely alone.
 
- AFAICT most of the new compilation code is in comp.el and comp.c focuses
  on "code generation", right?  Can you say something about the time it
  takes to compile files?
  What does the time break down looks like (i.e. percentage spent in
  bytecompiler, comp.el, comp.c, libgccjit)?

- Have you tried to use the compiler as benchmark (i.e. how much faster
  can Emacs compile (either byte-compile or native-compile)) if the
  compiler code is native-compiled (since it's all using
  lexical-binding already)?
 

-- Stefan


Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Andrea Corallo
Stefan Monnier <[hidden email]> writes:

>> Hi all.  I'd like share the investigation I've been working on to give
>> Emacs the ability to compile and run elisp as native code.
>
> This looks great, thanks.
>
> [ I wasn't able to follow all the explanations at
>   http://akrl.sdf.org/gccemacs.html, such as the one around "function
>   frames", with which I'm not familiar.  Are these like activation
>   frames? ]

Yes I think we both mean the same.  In this case basically where we store
automatic variables and data related to the single activated function.

> A few questions:
>
> - How did you get there?  I see some "we" in the web page, which makes
>   it sound like you weren't completely alone.

Sorry for that I'm not much into using 'I'.  I actually did the design
and all the coding my self, but I've been helped with moral support and
with the testing by two brave colleagues (one contributed to the elisp
benchmarks too porting dhrystone).

> - AFAICT most of the new compilation code is in comp.el and comp.c focuses
>   on "code generation", right?  Can you say something about the time it
>   takes to compile files?
>   What does the time break down looks like (i.e. percentage spent in
>   bytecompiler, comp.el, comp.c, libgccjit)?

All measurable time is spent in gcc from my early measures.  The time
spent in comp.el seems really a rounding error.

> - Have you tried to use the compiler as benchmark (i.e. how much faster
>   can Emacs compile (either byte-compile or native-compile)) if the
>   compiler code is native-compiled (since it's all using
>   lexical-binding already)?

I use the compiler native compiled but because of the previous point I
think is hard to measure the difference.

Talking about compile time in general I think we are looking at
something like few minutes to compile the whole Emacs at speed 0.  The
time goes up to say ~4 hours with 4 cores for the same job at speed 2.

I think it will be interesting to look into the gcc compilation pipe to
see where we are losing so much time, my guess is that there's one or
few passes that go a little nuts with all the moves we do.  I had no
time to look into it but my guess is that once understood the problem we
can probably dime it down.

Andrea

--
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Andrea Corallo
In reply to this post by Lars Ingebrigtsen
Lars Ingebrigtsen <[hidden email]> writes:

> Andrea Corallo <[hidden email]> writes:
>
>> I wrote a small page to describe what I did and how it works plus the
>> current status not to have the information spread in various mails.
>>
>> http://akrl.sdf.org/gccemacs.html
>
> Wow, that's exciting!
>
> A couple of questions:
>
>> * Native compiler is not re-entrant:
>>
>>  Just top level functions are native compiled, the others (lambda
>>  included) are still kept as byte-code.
>
> Is that a fundamental limitation, or have you just not gotten around to
> it yet?

I do not see any design limitation for that.  Just had no time to work
on it.

> Also, I'm wondering about debugging: I spend a lot of time in Emacs just
> edebugging or in the *Backtrace* buffer.  Does the natively compiled
> code mean that all that has to happen in gdb now?

No, you can trap into native compiled code with a gdb as you can do it
for any piece of the C core, but I would do that just for debugging the
internals or the functionality of the generated code.  Should be
something not routinely done for writing lisp.

Andrea

--
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Stefan Monnier
In reply to this post by Andrea Corallo
>> [ I wasn't able to follow all the explanations at
>>   http://akrl.sdf.org/gccemacs.html, such as the one around "function
>>   frames", with which I'm not familiar.  Are these like activation
>>   frames? ]
> Yes I think we both mean the same.  In this case basically where we store
> automatic variables and data related to the single activated function.

OK, thanks.  I think "activation frame" is the standard term (of which
there can be several on the stack at the same time in case of recursion).

>> - How did you get there?  I see some "we" in the web page, which makes
>>   it sound like you weren't completely alone.
> Sorry for that I'm not much into using 'I'.

That's OK, but I see you tried to use it as a clever ploy to dodge the
initial question: how did you get there?

>> - Have you tried to use the compiler as benchmark (i.e. how much faster
>>   can Emacs compile (either byte-compile or native-compile)) if the
>>   compiler code is native-compiled (since it's all using
>>   lexical-binding already)?
> I use the compiler native compiled but because of the previous point I
> think is hard to measure the difference.

How 'bout measuring the time to byte-compile a given set of files, then:
first using the byte-compiled compiler and then using the
native-compiled compiler (where "compiler" here means at least cconv.el,
byte-opt.el, bytecomp.el, and macroexp.el)?

BTW, I think developing a good set of Elisp benchmarks is useful
independently from this, so I'd encourage you to submit your benchmarks
as a new GNU ELPA package (we could also incorporate it into Emacs
itself, but I think we'll want to use it to compare performance between
diverse Emacsen, so a separate package makes more sense).

Maybe someone from the Gnus side will want to submit more benchmarks
(such as one that manipulates "sets/ranges or article numbers").

> Talking about compile time in general I think we are looking at
> something like few minutes to compile the whole Emacs at speed 0.  The
> time goes up to say ~4 hours with 4 cores for the same job at speed 2.

[ Compile time varies for me with the normal Emacs from less than
  5 minutes to more than an hour depending on the machine on which
  I compile, so absolute times don't speak to me very much.  ]
 
So, IIUC, with enough optimisations enabled, we gets into "a long
time" territory?

> I think it will be interesting to look into the gcc compilation pipe to
> see where we are losing so much time, my guess is that there's one or
> few passes that go a little nuts with all the moves we do.  I had no
> time to look into it but my guess is that once understood the problem we
> can probably dime it down.

Indeed, I'm surprised that compilation time in gcc would blow up by
significantly more than a factor 10 just because of optimisation
options, so either we're using optimisations which are really too
costly, or there should be something we can do to avoid this blow up
without any significant performance loss.


        Stefan


Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Andrea Corallo
Stefan Monnier <[hidden email]> writes:

>>> [ I wasn't able to follow all the explanations at
>>>   http://akrl.sdf.org/gccemacs.html, such as the one around "function
>>>   frames", with which I'm not familiar.  Are these like activation
>>>   frames? ]
>> Yes I think we both mean the same.  In this case basically where we store
>> automatic variables and data related to the single activated function.
>
> OK, thanks.  I think "activation frame" is the standard term (of which
> there can be several on the stack at the same time in case of recursion).

OK good to know, I don't have an official education as a compiler engineer
so my nomenclature can be occasionally a bit off.

>>> - How did you get there?  I see some "we" in the web page, which makes
>>>   it sound like you weren't completely alone.
>> Sorry for that I'm not much into using 'I'.
>
> That's OK, but I see you tried to use it as a clever ploy to dodge the
> initial question: how did you get there?

Sorry I though the question was more to understand if there were other
contributors for copyright reasons.

On my side the long story short is about this:

I was already into gcc and libgccjit.  I thought was cool to apply these
to some lisp implementation.  I decided to have Emacs as a target cause
I imagined would have been useful and because I'm obviously an Emacs
user and fan.

I wanted to do something with the potential to be completed and
up streamed one day.  Therefore I discarded the idea of writing the full
lisp front-end from scratch.  On the other side I considered the idea
seen in previous projects of reusing the byte-compiler infrastructure
quite clever.

The original plan was the to do something like Tromey's jitter but gcc
based and with a mechanism to reload the compiled code.  So I did it.

I had a single pass compiler all written in C that was decoding the byte
code and driving libgccjit.

I was quite unhappy with that solution for two reasons:

1- The C file was getting huge without doing anything really smart.

2- After some test and observation became clear that to generate
efficient code this approach was quite limited and a more sophisticated
approach with a propagation engine and the classical compiler theory
data structures was needed.  The idea of just driving gcc and having
everything magically optimized was simply naive.

So I came up with the idea of defining LIMPLE and using it as interface
between the C and the lisp side of the compiler.

In this way I had the right IR for implementing the 'clever' algorithmic
into lisp and the C side has just to 'replay' the result on libgccjit.
Moreover it saved me from the pain of exposing libgccjit to lisp.

I then realized I could, instead of decoding op-codes, just spill the LAP
from the byte-compiler.  This makes the system simpler and more robust
cause I get also information on the stack depth I can double check or
use during limplification.

Lastly I managed to reuse the information defined in the byte-compiler
on the stack offset of every op to generate automatically or semi the
code of my compiler for the translation from LAP to LIMPLE for good part
of the op codes.

The rest just iterating over tests debugging and implementing.

I'm not sure this answer the question. Does it?

>>> - Have you tried to use the compiler as benchmark (i.e. how much faster
>>>   can Emacs compile (either byte-compile or native-compile)) if the
>>>   compiler code is native-compiled (since it's all using
>>>   lexical-binding already)?
>> I use the compiler native compiled but because of the previous point I
>> think is hard to measure the difference.
>
> How 'bout measuring the time to byte-compile a given set of files, then:
> first using the byte-compiled compiler and then using the
> native-compiled compiler (where "compiler" here means at least cconv.el,
> byte-opt.el, bytecomp.el, and macroexp.el)?

I think is a test we can do, sounds like a very good benchmark.

> BTW, I think developing a good set of Elisp benchmarks is useful
> independently from this, so I'd encourage you to submit your benchmarks
> as a new GNU ELPA package (we could also incorporate it into Emacs
> itself, but I think we'll want to use it to compare performance between
> diverse Emacsen, so a separate package makes more sense).

OK I'll do some clean-up then.  BTW I think for dhrystone my colleague
has to do the paper-works and we have to look also into the original
license.

> Maybe someone from the Gnus side will want to submit more benchmarks
> (such as one that manipulates "sets/ranges or article numbers").
>
>> Talking about compile time in general I think we are looking at
>> something like few minutes to compile the whole Emacs at speed 0.  The
>> time goes up to say ~4 hours with 4 cores for the same job at speed 2.
>
> [ Compile time varies for me with the normal Emacs from less than
>   5 minutes to more than an hour depending on the machine on which
>   I compile, so absolute times don't speak to me very much.  ]
>
> So, IIUC, with enough optimisations enabled, we gets into "a long
> time" territory?

Yes feels like compiling C++ :x

>> I think it will be interesting to look into the gcc compilation pipe to
>> see where we are losing so much time, my guess is that there's one or
>> few passes that go a little nuts with all the moves we do.  I had no
>> time to look into it but my guess is that once understood the problem we
>> can probably dime it down.
>
> Indeed, I'm surprised that compilation time in gcc would blow up by
> significantly more than a factor 10 just because of optimisation
> options, so either we're using optimisations which are really too
> costly, or there should be something we can do to avoid this blow up
> without any significant performance loss.

Me too.  My guess is that because the code we feed into gcc does not
look at all like it's written by a human something has just to be tuned
somewhere in some pass.  I'm looking forward to investigate it but I'm a
bit saturated now.

I'm quite confident we can at least mitigate it but in general maybe we
should give also the possibility to specify different optimization
levels per function granularity.

Andrea

--
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Eric Abrahamsen-2
In reply to this post by Stefan Monnier
Stefan Monnier <[hidden email]> writes:

>>> [ I wasn't able to follow all the explanations at
>>>   http://akrl.sdf.org/gccemacs.html, such as the one around "function
>>>   frames", with which I'm not familiar.  Are these like activation
>>>   frames? ]
>> Yes I think we both mean the same.  In this case basically where we store
>> automatic variables and data related to the single activated function.
>
> OK, thanks.  I think "activation frame" is the standard term (of which
> there can be several on the stack at the same time in case of recursion).
>
>>> - How did you get there?  I see some "we" in the web page, which makes
>>>   it sound like you weren't completely alone.
>> Sorry for that I'm not much into using 'I'.
>
> That's OK, but I see you tried to use it as a clever ploy to dodge the
> initial question: how did you get there?
>
>>> - Have you tried to use the compiler as benchmark (i.e. how much faster
>>>   can Emacs compile (either byte-compile or native-compile)) if the
>>>   compiler code is native-compiled (since it's all using
>>>   lexical-binding already)?
>> I use the compiler native compiled but because of the previous point I
>> think is hard to measure the difference.
>
> How 'bout measuring the time to byte-compile a given set of files, then:
> first using the byte-compiled compiler and then using the
> native-compiled compiler (where "compiler" here means at least cconv.el,
> byte-opt.el, bytecomp.el, and macroexp.el)?
>
> BTW, I think developing a good set of Elisp benchmarks is useful
> independently from this, so I'd encourage you to submit your benchmarks
> as a new GNU ELPA package (we could also incorporate it into Emacs
> itself, but I think we'll want to use it to compare performance between
> diverse Emacsen, so a separate package makes more sense).
>
> Maybe someone from the Gnus side will want to submit more benchmarks
> (such as one that manipulates "sets/ranges or article numbers").

Maybe so!


Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Lars Brinkhoff
In reply to this post by Andrea Corallo
Hello Andrea,

First off, I think this is very exciting news and possibly a major step
forward for Emacs.  So thank you.


Andrea Corallo wrote:
> Lars Ingebrigtsen wrote:
>> Also, I'm wondering about debugging: I spend a lot of time in Emacs just
>> edebugging or in the *Backtrace* buffer.  Does the natively compiled
>> code mean that all that has to happen in gdb now?
> No, you can trap into native compiled code with a gdb as you can do it
> for any piece of the C core, but I would do that just for debugging the
> internals or the functionality of the generated code.  Should be
> something not routinely done for writing lisp.

I think the concern is whether natively compiled code would be less
debuggable.  And I think the answer would be: it depends.  If speed is
set to 3, maybe you forego some debugging features.  And if it's low
enough, debugging would hopefully work exactly the same as byte-compiled
code.  The default for building Emacs might be somewhere in between but
probably lean more towards debugging.

Are there more compiler parameters than speed, like debug, safety, space
as in CL?


Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Andrea Corallo
In reply to this post by Stefan Monnier
Stefan Monnier <[hidden email]> writes:

> How 'bout measuring the time to byte-compile a given set of files, then:
> first using the byte-compiled compiler and then using the
> native-compiled compiler (where "compiler" here means at least cconv.el,
> byte-opt.el, bytecomp.el, and macroexp.el)?

I did the following simple test.

I byte-compiled all files in emacs/lisp (avoiding sub-folders).  Using
two Emacs, one conventionally byte-compiled the other one after having
loaded all native compiled files.

Note that in this case all lisp files were native compiled at *speed 2*.

The result of this very preliminary test looks like this.  Please take
this with grain of salt:

|             | byte-compiled | native-compiled | speed-up |
|-------------+---------------+-----------------+----------|
| interactive |           27s |             19s |     1.4x |
| batch       |           15s |              8s |     1.9x |

To me makes quite sense that in interactive there's less difference
cause of the re-display done in C anyway.

To a quick look with perf seems garbage collection is also a
considerable part of the result.

I think is encouraging and I'd really like having somebody reproducing
these kind of measure.

I'll have more time to look into all of this in the week-end.

Andrea

--
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Eli Zaretskii
> From: Andrea Corallo <[hidden email]>
> Date: Fri, 29 Nov 2019 14:59:16 +0000
> Cc: [hidden email]
>
> |             | byte-compiled | native-compiled | speed-up |
> |-------------+---------------+-----------------+----------|
> | interactive |           27s |             19s |     1.4x |
> | batch       |           15s |              8s |     1.9x |
>
> To me makes quite sense that in interactive there's less difference
> cause of the re-display done in C anyway.

Regardless of the speed-up due to using native code, it sounds strange
to me that byte-compiling interactively takes twice the time it takes
non-interactively.  I have hard time convincing myself that redisplay
has such a profound effect on byte compilation, since byte-compiling a
file normally yields one or two lines of output, regardless of the
size of the file being compiled.

Does the timing change if you delete the window showing the
compilation log?  In that case, redisplay is not involved at all.

Also, was the interactive session started only once, and then used for
compiling all the files?  Or was it restarted anew for each
compilation?  If the latter, then the slow-down is probably due to a
slower startup of a GUI session.

Thanks.

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Stefan Monnier
>> |             | byte-compiled | native-compiled | speed-up |
>> |-------------+---------------+-----------------+----------|
>> | interactive |           27s |             19s |     1.4x |
>> | batch       |           15s |              8s |     1.9x |

So, there's 11s-12s of "interactive cost".

>> To me makes quite sense that in interactive there's less difference
>> cause of the re-display done in C anyway.

I'm not sure what those 11s-12s come from, but I think it's safe to take
the "1.9x" as the more relevant measure in terms of measuring the impact
of native compilation on the speed of bytecomp.el.

> Regardless of the speed-up due to using native code, it sounds strange
> to me that byte-compiling interactively takes twice the time it takes
> non-interactively.  I have hard time convincing myself that redisplay
> has such a profound effect on byte compilation, since byte-compiling a
> file normally yields one or two lines of output, regardless of the
> size of the file being compiled.

I agree it's a bit surprising.  Even it was running in a "large"
interactive session, it could also be due to the time it takes to GC
a larger heap (tho we normally GC such larger heaps proportionally less
often, so that doesn't really explain it either).

But since this is orthogonal to the gccemacs native compilation, maybe
we should move it to a bug report where we can try and investigate it.


        Stefan


Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Andrea Corallo
In reply to this post by Eli Zaretskii
Eli Zaretskii <[hidden email]> writes:

>> From: Andrea Corallo <[hidden email]>
>> Date: Fri, 29 Nov 2019 14:59:16 +0000
>> Cc: [hidden email]
>>
>> |             | byte-compiled | native-compiled | speed-up |
>> |-------------+---------------+-----------------+----------|
>> | interactive |           27s |             19s |     1.4x |
>> | batch       |           15s |              8s |     1.9x |
>>
>> To me makes quite sense that in interactive there's less difference
>> cause of the re-display done in C anyway.
>
> Regardless of the speed-up due to using native code, it sounds strange
> to me that byte-compiling interactively takes twice the time it takes
> non-interactively.  I have hard time convincing myself that redisplay
> has such a profound effect on byte compilation, since byte-compiling a
> file normally yields one or two lines of output, regardless of the
> size of the file being compiled.
>
> Does the timing change if you delete the window showing the
> compilation log?  In that case, redisplay is not involved at all.
>
> Also, was the interactive session started only once, and then used for
> compiling all the files?  Or was it restarted anew for each
> compilation?  If the latter, then the slow-down is probably due to a
> slower startup of a GUI session.
>
> Thanks.
>

Hi Eli,
yeah sounds strange.  I'm very possibly doing something wrong here.

What I'm doing is starting a fresh "emacs -Q" and then measuring the
time of:

(mapc #'byte-compile-file (directory-files "~/emacs/lisp" t "el$"))

Then is one single start of the GUI for all compilations.

I see an intense message activity going on in the mini-buffer so maybe
that's the reason?

Question how could I delete the compilation log without interrupting the
compilation it-self?

Bests

Andrea

--
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Eli Zaretskii
> From: Andrea Corallo <[hidden email]>
> Cc: [hidden email], [hidden email]
> Date: Fri, 29 Nov 2019 16:43:21 +0000
>
> (mapc #'byte-compile-file (directory-files "~/emacs/lisp" t "el$"))
>
> Then is one single start of the GUI for all compilations.
>
> I see an intense message activity going on in the mini-buffer so maybe
> that's the reason?
>
> Question how could I delete the compilation log without interrupting the
> compilation it-self?

How about binding inhibit-message to a non-nil value, around that mapc
call?

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Andrea Corallo
Eli Zaretskii <[hidden email]> writes:

>> From: Andrea Corallo <[hidden email]>
>> Cc: [hidden email], [hidden email]
>> Date: Fri, 29 Nov 2019 16:43:21 +0000
>>
>> (mapc #'byte-compile-file (directory-files "~/emacs/lisp" t "el$"))
>>
>> Then is one single start of the GUI for all compilations.
>>
>> I see an intense message activity going on in the mini-buffer so maybe
>> that's the reason?
>>
>> Question how could I delete the compilation log without interrupting the
>> compilation it-self?
>
> How about binding inhibit-message to a non-nil value, around that mapc
> call?
>

Great, doing that we are straight down into the 15s territory, exactly as
the measured batch.  I guess this explains.

Andrea

--
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Andrea Corallo
In reply to this post by Stefan Monnier
Stefan Monnier <[hidden email]> writes:

> I'm not sure what those 11s-12s come from, but I think it's safe to take
> the "1.9x" as the more relevant measure in terms of measuring the impact
> of native compilation on the speed of bytecomp.el.

I've got some time to repeat the measure trying to understand better
what's going on.

I've repeated the same test but running it 10 times.

(benchmark 10 '(mapc #'byte-compile-file (directory-files
                                          "~/emacs/lisp" t "el$")))
                     
I've discovered that my previous measure made not much sense because the
time spent into GC is much bigger during the byte-code runs.

-bytecode
 "Elapsed time: 156.960728s (77.049537s in 3421 GCs)"
-native speed 2
 "Elapsed time: 94.538094s (46.362582s in 1737 GCs)"
-native speed 3
 "Elapsed time: 92.288413s (47.509687s in 1816 GCs)"

My explanation for that (you'll tell me if it makes sense) is that
having to load by hand all the .eln we start the test native compiled
tests with a bigger heap:

(heap 1024 1065 464) vs (heap 1024 7561 376)

As a consequence GC triggers way less often and in the total result
count less.  This makes a huge difference in a test like this where GC
time contribute to ~50% of the perf result.

It's not easy to start we with a comparable status for the GC in this
situation so I think makes sense to compare just the execution time
having removed the GC form the equation.  If we do this:

|             | bytecode |  native |  native | speed 3 vs |
|             |          | speed 2 | speed 3 | bytecode   |
|-------------+----------+---------+---------+------------|
| non GC time |       80 |      49 |      44 | 1.8x       |
| GC time     |       77 |      46 |      48 |            |
| Total       |      157 |      95 |      92 |            |

So ~1.8x of execution time excluding GC for the native compiler in the
current statu.

Please let me know if something looks wrong.

There's an heap of room for improvements but I think I'll leave the perf
focus for now to continue the bring-up of the missing essential
features.

Andrea

--
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: On elisp running native

Stefan Monnier
> I've discovered that my previous measure made not much sense because the
> time spent into GC is much bigger during the byte-code runs.

The GC time should never be discarded: it's real work that is being performed.

> My explanation for that (you'll tell me if it makes sense) is that
> having to load by hand all the .eln we start the test native compiled
> tests with a bigger heap:

That's possible, but a smaller heap also makes for a faster GC.
Usually the time to perform one GC is largely proportional to the size
of the heap, and we set the "time between GC" to be itself proportional
to the size of the heap, so that overall the "time spent in GC" should
be *more or less* independent from the heap size.

Another possible source of difference is that the two codes don't behave
the same w.r.t the amount of allocation they perform.

In any case, to the extent that GC time is reduced, I think we should
take it as a nice side-benefit.


        Stefan