emacs-devel
[Top][All Lists]
Advanced

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

Re: Making 'eq' == 'eql' in bignum branch


From: Paul Eggert
Subject: Re: Making 'eq' == 'eql' in bignum branch
Date: Sat, 28 Jul 2018 20:34:32 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1

Stefan Monnier wrote:

I'm afraid you might be comparing apples and pears, since the relative
cost may vary substantially depending on the CPU's architecture.
Have you tried to measure the slowdown of my patch on your machine?

It's definitely apples-to-pears, as your patch hashes incorrectly and that might be a performance advantage.

For what it's worth I tried to do the measurement again, and this time got different numbers. Again, this is Fedora 28 x86-64, AMD Phenom II X4 910e, user+system time, average of 3 runs for "cd lisp; time make compile-always", otherwise-idle system. However, this time I started with master commit db80851a1f10d73f0b2c12299c3d77716bb8425a, and I did 4 runs and ignored the first one to avoid any startup overheads involved. This time I got: master 460.587 s, my patch 465.373 s (1% slower than master), your patch 469.619 s (2% slower than master).

have you thought about hashing floating-point objects instead, so
that comparing pointers suffices for eql, and eq becomes equivalent to eql
in a different way?

No I have not considered this trade-off carefully.  It's true that
floats aren't used very often, but it would make floats enormously more
expensive both in CPU and memory resources.  Currently, they cost
8 bytes of allocated heap, and currently our hash-tables cost about
6 words per entry (i.e. 48 bytes per entry on 64bit systems).
Clearly we could cut that down for hash-consing uses (where key==value),
but it's still pretty bad.

How about if we do to floats what fixnum+bignum would do to integers?

That is, on a 64-bit host, if the low-order 4 bits of the significand are all zero, we encode the floating-point number directly in the Lisp_Object (with a tag) so that the Lisp_Object need not be dereferenced and uses zero bytes of floating-point heap. Otherwise, we put the floating-point value into a special hash-consed table that should use about 16 bytes per entry (one for the double, one for the pointer to it). I just checked 'make compile-always' and under this proposal a full run would create 95694 Lisp floats of which 80048 (84%) would use zero bytes and 15646 (16%) would use 16 bytes of floating-point heap. This would mean a total floating-point heap usage of 15646*16 = 250 kB, as opposed to current master which uses 95694*8 == 766 kB, i.e., we'd shrink floating-point heap usage by about a factor of 3.

The tradeoff would be different on a 32-bit platform, since in the above discussion we would replace '4 bits' with '36 bits', '15620 (16%)' with '16083 (17%)', and '16 bytes per entry' with '12 bytes per entry'. But it'd be an even-bigger space win, as the total heap usage of 16083*12 = 193 kB of heap would be even smaller than the 64-bit total, i.e., we'd shrink floating-point heap usage by about a factor of 4.

We could of course use even less storage simply by lowering the precision of Emacs Lisp floating-point, although that'd be a user-visible change, would be a fairly drastic thing to do on 32-bit platforms, and wouldn't really address the bignum eql issue. (Though it might be interesting to try anyway....)



reply via email to

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