unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Psionic K <psionik@positron.solutions>
To: Tomas Hlavaty <tom@logand.com>
Cc: Psionic K <psionik@positron.solutions>,
	help-gnu-emacs@gnu.org, incal@dataswamp.org,
	Eli Zaretskii <eliz@gnu.org>
Subject: Re: Identifying sources of allocations in a toy Mandelbrot package
Date: Sat, 27 Jan 2024 10:07:09 +0900	[thread overview]
Message-ID: <CADQMGAQrze_pG9P4PDNszLumMOJsyD=d-m_D8Z8ti0SFWf8VJg@mail.gmail.com> (raw)
In-Reply-To: <87wmrvd5va.fsf@neko.mail-host-address-is-not-set>

> I find it interesting that:
> - native compilation improves so little compared to byte compilation.
> - floating point calculations are very slow.
> - emacs-lisp is very slow

From first principles and numbers I have seen so far, I can guess
what's happening with little uncertainty.  The Elisp interpreter must
store all created conses and non-immediate values, however
short-lived, into memory, converting every computationally intensive
workload into a memory-intensive workload.  None of this is freed for
re-use between GC's, so in about 1/100th of a second, the memory
controller is fully saturated and the CPU grinds to a halt.

There are no workarounds for this using GC settings.  The GC is
non-generational, so frequent GC's must mark & sweep a lot of memory
that is irrelevant to the currently running function.  Frequent GC's
will saturate the memory attempting to free small amounts that are
relevant to the cache sizes.  Furthermore, the GC is non-moving,
resulting in fragmented reads and writes, so even for shorter
computations, much of the loaded cache could be wasted.

The sum of these behaviors is still faster than human speed, but
almost pathalogically worst case usage of memory and cache, requiring
multiple trips to RAM for almost all computations and limiting
effective CPU register bandwidth to a small multiple of RAM.  The
programmer has few tools to increase computational density and all
workloads are memory bandwidth limited.

To remedy the most egregious behavior, which is that computations
imply writes, we would take advantage of how functions usually throw
away all of their intermediate values except the return value and
implement stack-like behavior by compacting and freeing after cons
thresholds calculated at call boundaries.  We can still give this
compacted memory back to our pathologically worst GC, but it will be
less fragmented and there will be much less of it.

A lot of this can be decided at compile time, and the compiler would
write values that need to be preserved into one stack while writing
other values at a different stack and re-setting the pointer.  I can
tell that this is not happening at all because otherwise the
Mandelbrot would not be consuming multiple gigabytes of RAM for values
that are thrown away at first use.

Elisp could be exceptionally fast for small runs, especially with
today's generous L1 sizes.   That drops off as the interpreter and new
data start hitting L2, L3, and then RAM.  Any work on the compiler
should focus on keeping memory from being entrusted to the existing GC
because no amount of doing less work means anything if all work also
consumes memory and freeing memory is hugely wasteful.

Fixed point was neat!  I didn't think to try that.  Thanks for code!



  reply	other threads:[~2024-01-27  1:07 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-19  9:19 Identifying sources of allocations in a toy Mandelbrot package Psionic K
2024-01-19 15:33 ` Tomas Hlavaty
2024-01-20  3:14   ` Psionic K
2024-01-20  3:37     ` Psionic K
2024-01-20  7:29     ` Eli Zaretskii
2024-01-20  9:09     ` Tomas Hlavaty
2024-01-20 10:03       ` Psionic K
2024-01-20 10:31         ` Eli Zaretskii
2024-01-26 23:36         ` Tomas Hlavaty
2024-01-27  1:07           ` Psionic K [this message]
2024-01-19 15:44 ` Eli Zaretskii
  -- strict thread matches above, loose matches on Subject: below --
2024-01-27  9:25 Psionic K
2024-01-17 12:39 Psionic K
2024-01-17 12:58 ` Eli Zaretskii
2024-01-17 13:25 ` Emanuel Berg

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='CADQMGAQrze_pG9P4PDNszLumMOJsyD=d-m_D8Z8ti0SFWf8VJg@mail.gmail.com' \
    --to=psionik@positron.solutions \
    --cc=eliz@gnu.org \
    --cc=help-gnu-emacs@gnu.org \
    --cc=incal@dataswamp.org \
    --cc=tom@logand.com \
    /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).