emacs-devel
[Top][All Lists]
Advanced

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

Re: Suppressing native compilation (short and long term)


From: Liliana Marie Prikler
Subject: Re: Suppressing native compilation (short and long term)
Date: Thu, 13 Oct 2022 21:20:13 +0200
User-agent: Evolution 3.46.0

Am Donnerstag, dem 13.10.2022 um 08:46 +0300 schrieb Eli Zaretskii:
> > From: Liliana Marie Prikler <liliana.prikler@gmail.com>
> > Cc: emacs-devel@gnu.org
> > Date: Wed, 12 Oct 2022 22:22:46 +0200
> > 
> > In GNU Guix, we observe certain packages breaking when trying to
> > compile them natively.  While some of that is on us for messing up
> > the package descriptions, one could also encounter genuine bugs in
> > native compilation that one wants to work around by disabling it.
> 
> When you encounter bugs in native compilation, please report them to
> us, so we could fix them.  As of now, we are not aware of any such
> bugs that were reported and haven't been fixed.  So if you still have
> such problem, please report them ASAP.
Of course, that's the intention, but this fix will only make it into
the next Emacs release.  Thus, if you're between releases, you still
need a workaround.

A particular candidate known to cause issues with the currently
packaged 28.1 is [1].

> > (For added trouble, whether or not your package breaks could depend
> > on the CPU due to being *native* compilation; thus the "no-native-
> > compile" local variable is insufficient to address this generally.)
> 
> Why isn't it sufficient to use no-native-compile?  It just means that
> on some architectures the corresponding file will be loaded as
> byte-compiled, and thus will be slightly slower (how much slower
> depends on the code, so if you are worried, my recommendation is
> first to measure the difference -- you might be surprised).
Because it'd require a distro-wide fix to address something that e.g.
only happens on some AMD CPUs.  Why AMD?  Because we already had bugs
in other languages, where AMD and Intel disagreed about floating points
and that caused tests to fail (though admittedly that's not relevant.

> In any case, if no-native-compile doesn't for some reason solve the
> problem, I don't understand how disabling native compilation will:
> the latter is a more blunt instrument than the former, e.g., it
> cannot be applied on the per-file resolution.
> 
> > In GNU Guix, we default to not compiling packages ahead-of-time,
> > instead using a minimal emacs that can only do byte compilation for
> > most packages.  Users can however pretty easily switch to ahead-of-
> > time compilation by swapping out the emacs package (using what Guix
> > calls package transformations).  This is also important because
> > apart from the current Emacs we typically provide an emacs-next
> > package for upcoming versions, as well as some other variants that
> > the user might want to use instead.  Again, we assume that users
> > who want to opt in to native compilation do so via a
> > transformation.
> 
> Sorry, I'm unfamiliar with this terminology.  When you say
> "ahead-of-time compilation", do you mean native compilation of all
> the Lisp files before they are loaded for the first time?  Or do you
> mean something else?
Exactly, it's more or less the same as ahead-of-time compilation via
package.el, which Emacs supports out of the box.

> And what is "swapping out the emacs package", and what is "package
> transformation"?
Guix users can decide between an Emacs package that only does byte-
compilation (emacs-minimal, the default) or native compilation (emacs).
They can easily write this by using the command-line switch --with-
input=emacs-minimal=emacs while building their Emacs package (e.g.
emacs-dash for dash.el).

For the record, we could probably also offer transformations, that
annotate files with no-native-compile, but this would probably be a
little harder to access as a user.  What I'm instead hoping for would
be a variable that can be set in early-init.el or similar.

> > In this context, the default of compiling everything that has
> > hitherto only been byte-compiled is an ill-advised choice.  Now,
> > there is a chance that the user meant to do this anyway, but I
> > think they rather a) use whatever the distro default is without
> > caring either way or b) actually didn't want this package natively
> > compiled.  Due to some packages breaking, we had a lot of b) in our
> > mailing lists in the past few days.
> 
> If a package is a single file or a small number of files, those users
> can add the no-native-compile cookies in those files.
This is not trivial in the case where the Elisp code is placed in
system-managed storage and thus requires elevated privileges to modify
(as is the default in most package managers, I assume).  Of course, you
can copy the file to your $HOME, but editing it with a broken Emacs is
rather painful.  We wouldn't want to resort to users using nano ;)

> And again, disabling native compilation is a method that doesn't
> allow them fine-tuning anyway, so I fail to see how it could help
> them here.  If the problem is real (and I don't yet see it is), we
> should perhaps discuss its details and invent some new method of
> disabling compilation with finer granularity.
The granularity here is disabling compilation of anything that isn't
already compiled – this makes it so that people can still use their
Emacs for byte compilation by invoking it with "emacs -Q", they just
won't compile anything that their package manager hasn't compiled for
them.

> > As for loading, I think there could be a case made to restrict
> > loading to certain directories managed by "trusted entities", but I
> > think native-comp-eln-load-path already accomplishes this.
> 
> Yes, but see below.
> 
> > If one wanted to disable loading altogether, I'm pretty sure one
> > could set it to nil and be done (with perhaps the exception that
> > deferred compilation breaks if there's no path to store binaries
> > in).
> 
> I don't think you can set native-comp-eln-load-path to nil.  The last
> entry, the one which points to where the preloaded *.eln files live,
> must be there, or else Emacs will refuse to start.  And at least one
> other directory should be there as well, because if and when some
> package advises some primitive, Emacs will need to generate and
> compile a trampoline .eln file.  But yes, if users want to prevent
> loading from a certain directory, they can remove it from
> native-comp-eln-load-path, provided that the two necessary entries
> are still left in the list.
I already found this annoying while implementing native compilation as
part of our emacs-build-system (i.e. the build system used to compile
Emacs packages), and I find it extra questionable that users on
traditional distros, where they don't usually get to choose their
Emacs, have no means of disabling this loading.  Calling back to the
earlier point on measuring performance, an easy way to measure
performance between bytecode and native code (in a benchmark) would be
to simply disable native code loading in one process.  But here, it
requires two separate builds of Emacs.

> > Thus, I think the issue is really only one of inadvertently
> > launching deferred compilation when all the packages the user
> > *expects* to be natively compiled are already ensured to be
> > compiled ahead-of-time.
> 
> This will not happen, so no need to prevent compilation in that case.
> If a .eln file already exists and is up-to-date, Emacs will not try
> to compile it again as part of loading the package.  If some of the
> packages aren't natively compiled, against user's expectations, I
> still see no reason for users to want to disallow JIT compilation,
> except as a kind of surprise effect due to something they see for the
> first time.  How is JIT compilation different from ahead-of-time
> compilation?  There's nothing really dangerous or harmful in JIT
> compilation, so all it takes is some getting used to it.  Educating
> your users to get used to it will go a long way towards eliminating
> the fears, because the dangers aren't real, they are largely
> imaginary.
I agree for the most part that JIT compilation is harmless.  However,
there are some cases in which it isn't.  For one, on slower hardware,
this can take unreasonable times at startup.  While bytecode
performance on such machines might too be slow (but perhaps tolerable
for the task), ahead-of-time compilation, perhaps with offloading, is
preferable.  For another, it can cause bugs like [2].

> > I hope this answers some of the questions raised.  In short, we
> > believe that users might want to control not only from where native
> > shared libraries will be loaded, but also whether to generate them
> > at runtime and that (distro) package managers should enable them to
> > compile all such shared libraries ahead of time – and better yet,
> > in a reproducible manner, but this hits other bugs I do not want to
> > discuss in detail at the moment.
> 
> Thanks for the explanations.  I still think the reasons for disabling
> native compilation are rather weak at best, and the users' requests
> to allow that based on either bugs that need to be solved or surprise
> and fears that have no real basis.  Moreover, disabling native
> compilation is a very blunt instrument that cannot be applied better
> than the existing ones, like no-native-compile (and a few others that
> we didn't mention; see the defcustom's in comp.el).
Which defcustom?  I fear that for all of its customizability, Emacs is
currently lacking a good way of disabling native compilation outside of
package management.  I also tried setting no-native-compile globally,
but it seems to only have an effect as a file-local variable.

Cheers

[1] https://github.com/DarwinAwardWinner/ido-ubiquitous
[2] https://issues.guix.gnu.org/issue/57878



reply via email to

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