unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
From: David Kastrup <dak@gnu.org>
To: "Ludovic Courtès" <ludo@gnu.org>
Cc: 41354@debbugs.gnu.org
Subject: bug#41354: equal? has no sensible code path for symbols
Date: Tue, 19 Jan 2021 22:53:37 +0100	[thread overview]
Message-ID: <874kjcr3tq.fsf@fencepost.gnu.org> (raw)
In-Reply-To: <87ftbj6ua5.fsf@gnu.org> ("Ludovic Courtès"'s message of "Fri, 29 May 2020 10:05:06 +0200")

Ludovic Courtès <ludo@gnu.org> writes:

> Hi,
>
> David Kastrup <dak@gnu.org> skribis:
>
>> Ludovic Courtès <ludo@gnu.org> writes:
>
> [...]
>
>>> Thus we could go with the patch below, though I doubt it would make a
>>> measurable difference (and it actually adds tests for other cases).
>>
>> It made a considerable measurable difference in LilyPond
>
> You measured with and without the patch I sent?  Or something else?

It made a considerable measurable difference in LilyPond to use scm_eq
over scm_eqv when one variable was known to be a symbol and most
comparisons would have turned out false.

>
>>> diff --git a/libguile/eq.c b/libguile/eq.c
>>> index 627d6f09b..16c5bfb3f 100644
>>> --- a/libguile/eq.c
>>> +++ b/libguile/eq.c
>>> @@ -303,6 +303,8 @@ scm_equal_p (SCM x, SCM y)
>>>      return SCM_BOOL_F;
>>>    if (SCM_IMP (y))
>>>      return SCM_BOOL_F;
>>> +  if (scm_is_symbol (x) || scm_is_symbol (y))
>>> +    return SCM_BOOL_F;
>>>    if (scm_is_pair (x) && scm_is_pair (y))
>>>      {
>>>        if (scm_is_false (scm_equal_p (SCM_CAR (x), SCM_CAR (y))))
>>>
>>
>> Yes, that looks reasonable.  scm_is_symbol checks some tag subset that
>> the code for equal_p later looks at closer as well: if you worry about
>> the extra cost of the scm_is_symbol check, one could try folding the
>> symbol check into that later code passage, which would slow down the
>> symbol check and effect the more costly fallbacks less.  But since those
>> fallbacks _are_ more costly, I doubt it would be worth the trouble.
>
> Looking at eq.c, I don’t see what “costly fallbacks” you’re referring
> to.  For a symbol, AIUI, we end up here:
>
>   switch (SCM_TYP7 (x))
>     {
>     default:
>       /* Check equality between structs of equal type (see cell-type test above). */
>       if (SCM_STRUCTP (x))
> 	{
> 	  if (SCM_INSTANCEP (x))
> 	    goto generic_equal;
> 	  else
> 	    return scm_i_struct_equalp (x, y);
> 	}
>       break;   // <- here, meaning we return SCM_BOOL_F
>
> All the checks leading to this line are type tag comparisons.
>
> Am I overlooking something?

That "all the checks" amount to quite a bit when the whole point of a
symbol is being faster to compare than structured types?  The main
surprise for me was that a symbol is a non-immediate type even though on
second thought it is clear that the symbol name has to be stored
somewhere associated with the symbol value.  However, from the
performance semantics a symbol should not be markedly different from
immediate types to avoid violating reasonable user expectations about
the Scheme type system: their whole point is to be fast to compare, and
fast comparisons are particularly important where you go through a large
number of them (which usually implies that most comparisons will end up
false).  This is particularly important when both arguments are symbols.

The normal expectation of functions like assv would be that they would
be only marginally slower than assq when the search key is a symbol (and
particularly so if most key/value pairs have a symbol key).  Because the
outcome for eqv(symbol1, symbol2)->#f takes quite longer than the
outcome for eq(symbol1, symbol2)->#f, this expectation is not met.

-- 
David Kastrup





      reply	other threads:[~2021-01-19 21:53 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-17 10:49 bug#41354: equal? has no sensible code path for symbols David Kastrup
2020-05-27 20:39 ` Ludovic Courtès
2020-05-27 20:49   ` David Kastrup
2020-05-28 16:06     ` Ludovic Courtès
2020-05-28 16:50       ` David Kastrup
2020-05-29  8:05         ` Ludovic Courtès
2021-01-19 21:53           ` David Kastrup [this message]

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/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=874kjcr3tq.fsf@fencepost.gnu.org \
    --to=dak@gnu.org \
    --cc=41354@debbugs.gnu.org \
    --cc=ludo@gnu.org \
    /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).