[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Optimizing ‘string=’
From: |
Ludovic Courtès |
Subject: |
Re: Optimizing ‘string=’ |
Date: |
Tue, 22 Jun 2010 23:32:43 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) |
Hi,
Andy Wingo <address@hidden> writes:
> On Tue 22 Jun 2010 21:40, address@hidden (Ludovic Courtès) writes:
>
>> @@ -1168,6 +1168,21 @@ SCM_DEFINE (scm_string_eq, "string=", 2, 4, 0,
>> "value otherwise.")
>> #define FUNC_NAME s_scm_string_eq
>> {
>> + if (SCM_LIKELY (scm_i_is_narrow_string (s1) == scm_i_is_narrow_string (s2)
>> + && SCM_UNBNDP (start1) && SCM_UNBNDP (end1)
>> + && SCM_UNBNDP (start2) && SCM_UNBNDP (end2)))
>> + {
>> + size_t len1, len2;
>> +
>> + len1 = scm_i_string_length (s1);
>> + len2 = scm_i_string_length (s2);
>> +
>> + if (SCM_LIKELY (len1 == len2))
>> + return scm_from_bool (memcmp (scm_i_string_chars (s1),
>> + scm_i_string_chars (s2),
>> + len1) == 0);
>> + }
>> +
>
> Nasty, but OK I guess if you need it. Why not also add a fast path for
> scm_is_eq (s1, s2), or for comparing stringbufs, or something ?
Hmm yes. Though if there are too many fast paths the whole thing ends
up being slow. ;-)
I don’t expect (eq? s1 s2) and (eq? (string-buf s1) (string-buf s2)) to
be common enough to warrant a more specific special case, though.
>> It’s quite inelegant, but it leads to a more balanced profile:
>>
>> samples % symbol name
>> 8079 23.3984 scm_string_eq
>> 5649 16.3606 vm_debug_engine
>> 5624 16.2882 scm_i_str2symbol
> ^ What is this doing here?
I comes from the ‘load-symbol’ instruction.
Indeed, the loop’s body goes like this:
--8<---------------cut here---------------start------------->8---
36 (new-frame)
37 (load-symbol "string=") ;; string=
48 (link-now)
49 (variable-ref)
50 (load-symbol "s") ;; s
55 (link-now)
56 (variable-ref)
57 (load-symbol "s") ;; s
62 (link-now)
63 (variable-ref)
64 (mv-call 2 :L39) ;; MV -> 74
69 (drop)
70 (br :L40) ;; -> 77
74 (truncate-values 0 0)
77 (br :L41) ;; -> 36
81 (br :L41) ;; -> 36
--8<---------------cut here---------------end--------------->8---
Because it’s a top-level program, “string=” is looked up at each
iteration.
If we instead do:
--8<---------------cut here---------------start------------->8---
(define s (make-string 123 #\a))
(define (foo)
(let loop ()
(string= s s)
(loop)))
(foo)
--8<---------------cut here---------------end--------------->8---
we get:
--8<---------------cut here---------------start------------->8---
0 (assert-nargs-ee/locals 0)
2 (br :L38) ;; -> 30
6 (new-frame)
7 (toplevel-ref 1)
9 (toplevel-ref 2)
11 (toplevel-ref 2)
13 (mv-call 2 :L39) ;; MV -> 23
18 (drop)
19 (br :L40) ;; -> 26
23 (truncate-values 0 0)
26 (br :L41) ;; -> 6
30 (br :L41) ;; -> 6
--8<---------------cut here---------------end--------------->8---
and thus presumably no ‘scm_i_str2symbol’.
> And for the matter, what are the rest about?
Lookups of ‘string=’.
> Did you just do a really short profile?
Yes.
Ludo’.