all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Re: Optimising Elisp code [again]
  2018-10-07 15:59                 ` Emanuel Berg
@ 2018-10-07 16:30                   ` Garreau, Alexandre
       [not found]                   ` <mailman.1805.1538929865.1284.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 16+ messages in thread
From: Garreau, Alexandre @ 2018-10-07 16:30 UTC (permalink / raw)
  To: help-gnu-emacs

On 2018-10-07 at 17:59, Emanuel Berg wrote:
> Stefan Monnier wrote:
> So there is no gain as to the number of machine instructions. So where
> is the gain? The `call' instruction specifically, or the implied
> funcall overhead not visible in the disassembly?

A smarter compiler could have optimized the discarded value (since we
don’t use its return value, and the inlined function don’t have any
side-effects (which otherwise would have been preserved)), or could have
simplified the result (I checked and with + 2 then - 2 it seems elisp
compiler don’t do this, while I’m sure gcc can) if something was going
to be done with it.

However, inlining is not an optimization made to gain space or reduce
the number of instruction (even worse: normally it could *increase* the
total amount of instruction and therefore use more memory), it’s here to
gain *speed*.  Not by executing less instructions, but by removing a
jump (the funcall), as in today’s computers, jumps (like function calls,
or conditionals) can increase execution time.  So at the end,
duplicating instructions can lead to faster execution, albeit increased
memory usage.

I kind of forgot why jumps are slow, but afair, either because the cache
being little it’s faster to execute nearby code, either because as
modern cpus try to do as much as possible in the same time (pipeline
instructions optimization, found in today’s superscalar cpu, iirc), they
need to know what will be executed next, and they stop searching what’s
next after a jump…  but that (+ loop unrolling) might be mitigated by
the fact that if you use too much memory at same time, it might not fit
in the smaller and faster cache, and then get slower…  so I guess here
it gets complex and architecture dependant, and becomes the job of
complex and native compilers to guess what is best to do.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
       [not found]                   ` <mailman.1805.1538929865.1284.help-gnu-emacs@gnu.org>
@ 2018-10-08 14:11                     ` Emanuel Berg
  2018-10-08 14:43                       ` tomas
       [not found]                       ` <mailman.1852.1539009893.1284.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-10-08 14:11 UTC (permalink / raw)
  To: help-gnu-emacs

Garreau, Alexandre wrote:

> I kind of forgot why jumps are slow

Isn't it as simple as all the overhead of
placing the new function on the stack with
return pointers and stuff?

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-08 14:11                     ` Emanuel Berg
@ 2018-10-08 14:43                       ` tomas
       [not found]                       ` <mailman.1852.1539009893.1284.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 16+ messages in thread
From: tomas @ 2018-10-08 14:43 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 511 bytes --]

On Mon, Oct 08, 2018 at 04:11:14PM +0200, Emanuel Berg wrote:
> Garreau, Alexandre wrote:
> 
> > I kind of forgot why jumps are slow
> 
> Isn't it as simple as all the overhead of
> placing the new function on the stack with
> return pointers and stuff?

And cold caches, and pipeline stalls and...

Modern processors are quite complex beasts, and much of it has to
do with the sad fact that RAM is much, much, MUCH slower than the
CPU, and they try to lie to you about it...

Cheers
-- tomás

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
       [not found]                       ` <mailman.1852.1539009893.1284.help-gnu-emacs@gnu.org>
@ 2018-10-09  0:38                         ` Barry Margolin
  2018-10-09  6:26                           ` Emanuel Berg
  0 siblings, 1 reply; 16+ messages in thread
From: Barry Margolin @ 2018-10-09  0:38 UTC (permalink / raw)
  To: help-gnu-emacs

In article <mailman.1852.1539009893.1284.help-gnu-emacs@gnu.org>,
 <tomas@tuxteam.de> wrote:

> On Mon, Oct 08, 2018 at 04:11:14PM +0200, Emanuel Berg wrote:
> > Garreau, Alexandre wrote:
> > 
> > > I kind of forgot why jumps are slow
> > 
> > Isn't it as simple as all the overhead of
> > placing the new function on the stack with
> > return pointers and stuff?
> 
> And cold caches, and pipeline stalls and...
> 
> Modern processors are quite complex beasts, and much of it has to
> do with the sad fact that RAM is much, much, MUCH slower than the
> CPU, and they try to lie to you about it...

Since we're talking about a byte-code interpreter, not machine code, the 
pipeline is probably not relevant.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-09  0:38                         ` Barry Margolin
@ 2018-10-09  6:26                           ` Emanuel Berg
  2018-10-09  8:07                             ` Garreau, Alexandre
       [not found]                             ` <mailman.1903.1539072429.1284.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-10-09  6:26 UTC (permalink / raw)
  To: help-gnu-emacs

Barry Margolin wrote:

> Since we're talking about a byte-code
> interpreter, not machine code, the pipeline
> is probably not relevant.

Cannot one have a three-layer architecture, C,
compiled Lisp, interpretated Lisp?

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-09  6:26                           ` Emanuel Berg
@ 2018-10-09  8:07                             ` Garreau, Alexandre
       [not found]                             ` <mailman.1903.1539072429.1284.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 16+ messages in thread
From: Garreau, Alexandre @ 2018-10-09  8:07 UTC (permalink / raw)
  To: help-gnu-emacs

On 2018-10-09 at 08:26, Emanuel Berg wrote:
> Barry Margolin wrote:
>
>> Since we're talking about a byte-code interpreter, not machine code,
>> the pipeline is probably not relevant.
>
> Cannot one have a three-layer architecture, C, compiled Lisp,
> interpretated Lisp?

It’s already like this… or what are you talking about otherwise?  We got
C, which interprets directly both byte-compiled and interpreted lisp,
which is all the high-level stuff.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
       [not found]                             ` <mailman.1903.1539072429.1284.help-gnu-emacs@gnu.org>
@ 2018-10-09 13:28                               ` Emanuel Berg
  2018-10-09 15:03                                 ` Garreau, Alexandre
       [not found]                                 ` <mailman.1911.1539097442.1284.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-10-09 13:28 UTC (permalink / raw)
  To: help-gnu-emacs

Garreau, Alexandre wrote:

>> Cannot one have a three-layer architecture,
>> C, compiled Lisp, interpretated Lisp?
>
> It’s already like this… or what are you
> talking about otherwise? We got C, which
> interprets directly both byte-compiled and
> interpreted lisp, which is all the
> high-level stuff.

Isn't there an FOSS CL compiler around one can
duplicate/modify?

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-09 13:28                               ` Emanuel Berg
@ 2018-10-09 15:03                                 ` Garreau, Alexandre
       [not found]                                 ` <mailman.1911.1539097442.1284.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 16+ messages in thread
From: Garreau, Alexandre @ 2018-10-09 15:03 UTC (permalink / raw)
  To: help-gnu-emacs

On 2018-10-09 at 15:28, Emanuel Berg wrote:
> Garreau, Alexandre wrote:
>>> Cannot one have a three-layer architecture,
>>> C, compiled Lisp, interpretated Lisp?
>>
>> It’s already like this… or what are you
>> talking about otherwise? We got C, which
>> interprets directly both byte-compiled and
>> interpreted lisp, which is all the
>> high-level stuff.
>
> Isn't there an FOSS CL compiler around one can
> duplicate/modify?

gcl. It’s GNU, it uses gcc (for now it generates C and compile that with
gcc, but it was planned to make it a gcc frontend a long time ago, but
iso support comes first afair).  The only other compiler I know is the
most used/popular (afaik), sbcl, but it’s not GNU (so it would be less
meaningful since there are a bunch of GNU lisp implementations)… and
clisp has a *VM* too (and its byte-compiler), but I guess it’s better
than emacs’ one.

However if you’re talking about using a cl compiler to host emacs,
*iirc*, rms said cl was too big for emacs which he wanted not too big
(and indeed, unless some modifications are maid, afaiu, it might imply
to make gcc a mandatory dependency of emacs, which is pretty big)…

Interestingly, on my (debian stable) system, gcl [0] appears to be 7,8M
(but there is a 15M gcl static library [3]), emacs [1] 11M, and libguile
[2] 1,6M… so is gcl smaller than emacs (also maybe it is the static that
contain all gcl, and maybe gcl should be bigger when everything is
complete and standard?)? I can’t measure clisp as I didn’t attempted
(yet) to recompile here, and it’s not packaged for the current debian
stable.

Btw, what would it change to make emacs hosted by gcl, compared to by
guile (modulo the obvious facilities of having elisp and cl more near
than elisp and scheme)? would the gcc runtime dep hard to remove? would
that be so big? would that be easier to get buffer-local variables,
dynamic scoping, et al?

[0] resolves to /usr/lib/gcl-2.6.12/unixport/saved_gcl 
[1] /usr/bin/emacs25-x
[2] /usr/lib/i386-linux-gnu/libguile-2.0.so.22.8.1
[3] /usr/lib/gcl-2.6.12/unixport/libgcl.a



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
       [not found]                                 ` <mailman.1911.1539097442.1284.help-gnu-emacs@gnu.org>
@ 2018-10-09 15:26                                   ` Emanuel Berg
  2018-10-09 19:35                                     ` Garreau, Alexandre
  2018-10-10 16:18                                     ` Barry Margolin
  0 siblings, 2 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-10-09 15:26 UTC (permalink / raw)
  To: help-gnu-emacs

Garreau, Alexandre wrote:

> Btw, what would it change to make emacs
> hosted by gcl

I mean, compile the Lisp that isn't user
defined and unlikely to change - compile for
real, not byte-compile for
sped-up interpretation.

I.e.: fun-and-play Elisp on the top
      compiled Elisp in the middle
      C downmost

?

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-09 15:26                                   ` Emanuel Berg
@ 2018-10-09 19:35                                     ` Garreau, Alexandre
  2018-10-10 16:18                                     ` Barry Margolin
  1 sibling, 0 replies; 16+ messages in thread
From: Garreau, Alexandre @ 2018-10-09 19:35 UTC (permalink / raw)
  To: help-gnu-emacs

On 2018-10-09 at 17:26, Emanuel Berg wrote:
> Garreau, Alexandre wrote:
>
>> Btw, what would it change to make emacs
>> hosted by gcl
>
> I mean, compile the Lisp that isn't user
> defined and unlikely to change - compile for
> real, not byte-compile for
> sped-up interpretation.
>
> I.e.: fun-and-play Elisp on the top
>       compiled Elisp in the middle
>       C downmost
>
> ?

We’d get the same problems as mentioned before about loss of dynamism
(you’ll need to recompile everything if changing a core thing, which you
currently don’t need).  Yet the opposite would also be there: some core
functions might be reimplemented in lisp, and then these could be easier
to hack for beginners, or any people uncomfortable with C.

But beside that you would get awesome performances I guess.  Not
*always* like C, because, I guess there are still mallocs and garbage
collection all the way around, types may not be determined as you’d
like, etc.  but especially as elisp is quite imperative (but potentially
less well used, sometimes), you may get quite near performances (I did
hear about 1,2/1,5 more slow than C for compiled elisp).

I’d like to see how the performances of libjit (native jit compiler I
guess) emacs, as previously mentioned, I’ll try it I think.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-09 15:26                                   ` Emanuel Berg
  2018-10-09 19:35                                     ` Garreau, Alexandre
@ 2018-10-10 16:18                                     ` Barry Margolin
  2018-10-10 20:53                                       ` Óscar Fuentes
                                                         ` (2 more replies)
  1 sibling, 3 replies; 16+ messages in thread
From: Barry Margolin @ 2018-10-10 16:18 UTC (permalink / raw)
  To: help-gnu-emacs

In article <86ftxfm98q.fsf@zoho.com>, Emanuel Berg <moasen@zoho.com> 
wrote:

> Garreau, Alexandre wrote:
> 
> > Btw, what would it change to make emacs
> > hosted by gcl
> 
> I mean, compile the Lisp that isn't user
> defined and unlikely to change - compile for
> real, not byte-compile for
> sped-up interpretation.
> 
> I.e.: fun-and-play Elisp on the top
>       compiled Elisp in the middle
>       C downmost
> 
> ?

The Elisp interpreter is probably tightly intertwined with the Emacs 
editor code. Disentangling them so you can compile Elisp to machine code 
would be a big project, and probably not worth it.

Byte-code interpretation is common in many modern languages, it makes it 
easier for the languages to be portable. Python and PHP both compile to 
byte code rather than machine code. It's generally fast enough for 
interactive applications. For computationally-intensive applications, 
there are often libraries that can be linked in, like Numpy for Python.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-10 16:18                                     ` Barry Margolin
@ 2018-10-10 20:53                                       ` Óscar Fuentes
  2018-10-10 23:54                                       ` Garreau, Alexandre
       [not found]                                       ` <mailman.1975.1539205047.1284.help-gnu-emacs@gnu.org>
  2 siblings, 0 replies; 16+ messages in thread
From: Óscar Fuentes @ 2018-10-10 20:53 UTC (permalink / raw)
  To: help-gnu-emacs

Barry Margolin <barmar@alum.mit.edu> writes:

> The Elisp interpreter is probably tightly intertwined with the Emacs 
> editor code. Disentangling them so you can compile Elisp to machine code 
> would be a big project, and probably not worth it.

http://git.savannah.gnu.org/cgit/emacs.git/log/?h=feature/libjit

https://github.com/tromey/el-compilador




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-10 16:18                                     ` Barry Margolin
  2018-10-10 20:53                                       ` Óscar Fuentes
@ 2018-10-10 23:54                                       ` Garreau, Alexandre
       [not found]                                       ` <mailman.1975.1539205047.1284.help-gnu-emacs@gnu.org>
  2 siblings, 0 replies; 16+ messages in thread
From: Garreau, Alexandre @ 2018-10-10 23:54 UTC (permalink / raw)
  To: Barry Margolin; +Cc: help-gnu-emacs

On 2018-10-10 at 12:18, Barry Margolin wrote:
> In article <86ftxfm98q.fsf@zoho.com>, Emanuel Berg <moasen@zoho.com> 
> wrote:
>> I mean, compile the Lisp that isn't user
>> defined and unlikely to change - compile for
>> real, not byte-compile for
>> sped-up interpretation.
>> 
>> I.e.: fun-and-play Elisp on the top
>>       compiled Elisp in the middle
>>       C downmost
>> 
>> ?
>
> The Elisp interpreter is probably tightly intertwined with the Emacs 
> editor code. Disentangling them so you can compile Elisp to machine code 
> would be a big project, and probably not worth it.

Why would that need distangling?  Couldn’t editor code be compiled as
well?  I understand things need to stay dynamic and redefinable, but a
large portion would remain unchanged anyway for most of time and the
things that would most likely be changed would be less stable and
less low-level things that wouldn’t break other stuff wouldn’t it?



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
       [not found]                                       ` <mailman.1975.1539205047.1284.help-gnu-emacs@gnu.org>
@ 2018-10-11 18:10                                         ` Emanuel Berg
  2018-10-12 19:52                                           ` Robert Thorpe
  0 siblings, 1 reply; 16+ messages in thread
From: Emanuel Berg @ 2018-10-11 18:10 UTC (permalink / raw)
  To: help-gnu-emacs

Óscar Fuentes wrote:

>> The Elisp interpreter is probably tightly
>> intertwined with the Emacs editor code.
>> Disentangling them so you can compile Elisp
>> to machine code would be a big project, and
>> probably not worth it.
>
> http://git.savannah.gnu.org/cgit/emacs.git/log/?h=feature/libjit
>
> https://github.com/tromey/el-compilador

Wonderful! But how does one integrate the
compiled code with the rest of Emacs?

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
  2018-10-11 18:10                                         ` Emanuel Berg
@ 2018-10-12 19:52                                           ` Robert Thorpe
  0 siblings, 0 replies; 16+ messages in thread
From: Robert Thorpe @ 2018-10-12 19:52 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: help-gnu-emacs

Emanuel Berg <moasen@zoho.com> writes:

> Óscar Fuentes wrote:
>
>>> The Elisp interpreter is probably tightly
>>> intertwined with the Emacs editor code.
>>> Disentangling them so you can compile Elisp
>>> to machine code would be a big project, and
>>> probably not worth it.
>>
>> http://git.savannah.gnu.org/cgit/emacs.git/log/?h=feature/libjit
>>
>> https://github.com/tromey/el-compilador
>
> Wonderful! But how does one integrate the
> compiled code with the rest of Emacs?

Firstly, I think it's worth clarifying how things work now.  Emacs has
two interpreters.  There's the interactive interpreter, that's what's run
when you type elisp straight into Emacs.  It is used to interpret files
ending in ".el".  Then there's the bytecode interpreter.  To use that
you have to compile a program to bytecode first.  It's the bytecode
interpreter that deals with ".elc" files.  The bytecode interpreter is
much faster than the interactive interpreter.  (I expect you know all
this Emanuel, I'm just writing it here for others who are reading who
might not).

The libjit branch works by compiling bytecode into native code.  As I
understand it, this is done at runtime, so the user doesn't have to do
anything.  I think there was another project that did something similar
at compile time.  Compiling bytecode sounds a bit strange, but it makes
sense.  In many cases what the JIT does is emit the same code that
is inside the bytecode interpreter.  In a very simplified sense, it
works like this....  So, the bytecode interpreter is a big switch/case
statement.  Somewhere there is instruction FOO.  When the JIT compiler
sees FOO it inserts into it's output buffer the code that was in the
bytecoding interpreter to deal with that opcode.  There are some
optimizations beyond that.

I think it's a good idea and I hope it will be merged into mainline
Emacs one day.

BR,
Robert Thorpe




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Optimising Elisp code [again]
       [not found] <mailman.2089.1539373965.1284.help-gnu-emacs@gnu.org>
@ 2018-10-13 18:00 ` Emanuel Berg
  0 siblings, 0 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-10-13 18:00 UTC (permalink / raw)
  To: help-gnu-emacs

Robert Thorpe wrote:

> The libjit branch works by compiling bytecode
> into native code. As I understand it, this is
> done at runtime, so the user doesn't have to
> do anything. I think there was another
> project that did something similar at compile
> time. Compiling bytecode sounds a bit
> strange, but it makes sense. In many cases
> what the JIT does is emit the same code that
> is inside the bytecode interpreter. In a very
> simplified sense, it works like this.... So,
> the bytecode interpreter is a big switch/case
> statement. Somewhere there is instruction
> FOO. When the JIT compiler sees FOO it
> inserts into it's output buffer the code that
> was in the bytecoding interpreter to deal
> with that opcode. There are some
> optimizations beyond that.

So it is a JIT native compiler of bytecode.

> I think it's a good idea and I hope it will
> be merged into mainline Emacs one day.

Thanks for a great post and also cred to the
people who have been, are, and/or in the future
will work on the libjit project!

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2018-10-13 18:00 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.2089.1539373965.1284.help-gnu-emacs@gnu.org>
2018-10-13 18:00 ` Optimising Elisp code [again] Emanuel Berg
2018-10-05  2:15 Optimising Elisp code Davin Pearson
2018-10-05 14:28 ` Barry Margolin
2018-10-06 14:40   ` Stefan Monnier
2018-10-06 16:55     ` Garreau, Alexandre
2018-10-06 19:24       ` tomas
2018-10-06 19:55         ` Knowing where a function has been used (bis) [Was: Re: Optimising Elisp code] Garreau, Alexandre
     [not found]           ` <mailman.1775.1538857674.1284.help-gnu-emacs@gnu.org>
2018-10-07 12:52             ` Emanuel Berg
     [not found]               ` <mailman.1792.1538918415.1284.help-gnu-emacs@gnu.org>
2018-10-07 15:59                 ` Emanuel Berg
2018-10-07 16:30                   ` Optimising Elisp code [again] Garreau, Alexandre
     [not found]                   ` <mailman.1805.1538929865.1284.help-gnu-emacs@gnu.org>
2018-10-08 14:11                     ` Emanuel Berg
2018-10-08 14:43                       ` tomas
     [not found]                       ` <mailman.1852.1539009893.1284.help-gnu-emacs@gnu.org>
2018-10-09  0:38                         ` Barry Margolin
2018-10-09  6:26                           ` Emanuel Berg
2018-10-09  8:07                             ` Garreau, Alexandre
     [not found]                             ` <mailman.1903.1539072429.1284.help-gnu-emacs@gnu.org>
2018-10-09 13:28                               ` Emanuel Berg
2018-10-09 15:03                                 ` Garreau, Alexandre
     [not found]                                 ` <mailman.1911.1539097442.1284.help-gnu-emacs@gnu.org>
2018-10-09 15:26                                   ` Emanuel Berg
2018-10-09 19:35                                     ` Garreau, Alexandre
2018-10-10 16:18                                     ` Barry Margolin
2018-10-10 20:53                                       ` Óscar Fuentes
2018-10-10 23:54                                       ` Garreau, Alexandre
     [not found]                                       ` <mailman.1975.1539205047.1284.help-gnu-emacs@gnu.org>
2018-10-11 18:10                                         ` Emanuel Berg
2018-10-12 19:52                                           ` Robert Thorpe

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.