emacs-devel
[Top][All Lists]
Advanced

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

Re: Performance issue w/ `cl-loop`s `collect...into`


From: Tianxiang Xiong
Subject: Re: Performance issue w/ `cl-loop`s `collect...into`
Date: Sun, 8 Apr 2018 20:38:59 -0700

I profiled

(progn
  (cl-loop for i in (number-sequence 1 1E6)
     collect i)
  :done)

w/ both the old and new code.

Old:

+ command-execute                                                 847  85%
+ ...                                                             113  11%
+ timer-event-handler                                              27   2%
+ eldoc-pre-command-refresh-echo-area                               3   0%
+ redisplay_internal (C function)                                   1   0%

New:

+ command-execute                                                 852  87%
+ ...                                                              95   9%
+ timer-event-handler                                              22   2%
+ redisplay_internal (C function)                                   2   0%
+ sp--save-pre-command-state                                        2   0%
+ flyspell-post-command-hook                                        1   0%

As you can see there's virtually no difference. I've attached the profile output for both.



On Sun, Apr 8, 2018 at 8:34 PM, Tianxiang Xiong <address@hidden> wrote:
Is there a function to easily time operations in Emacs Lisp? Something like Clojure's `core/time`?

`profile-*` a chore to use for short stuff.

On Sun, Apr 8, 2018 at 7:20 PM, Stefan Monnier <address@hidden> wrote:
> IIUC the `(eq var cl--loop-accum-var)` is used to test whether the
> accumulation is `into` or not. If not, clauses like `collect(ing)` use a
> `cons-nreverse` rather than `nconc` algorithm, which is O(n) instead of
> O(n^2). Since we're doing `setcdr` in all cases where the accumulation is
> into a list, we're always O(n), so the optimization is unnecessary.

I agree that the algorithmic complexity of "cons+nreverse" is no better
than that of the setcdr, but that doesn't mean that it's the same speed.
Since (eq var cl--loop-accum-var) is expected to be the most common
case, it'd be good to make sure that your patch doesn't make the
code slower, hence the need to test the performance.


        Stefan


> Attached is a new patch that uses `(cl--loop-accum-var)`.
>
> On Sun, Apr 8, 2018 at 6:59 PM, Stefan Monnier <address@hidden>
> wrote:
>
>> > Here's a second, cleaner attempt that separates the
>> `cl--loop-handle-accum`
>> > function into two functions, one to deal with lists and one to deal w/
>> > non-lists.
>> > The tail-tracking optimizing is also applied to `append(ing)` and
>> > `nconc(ing)`.
>>
>> Thanks.  Looks good.
>> I see you've dropped the (eq var cl--loop-accum-var) optimization.
>> Have you tried to measure the effect?
>>
>>
>>         Stefan
>>
>>
>> > +(defun cl--loop-handle-accum (def)
>> [...]
>> > +  (cond
>> [...]
>> > +    (cl--loop-accum-var cl--loop-accum-var)
>>
>> You can write this line as just
>>
>>        (cl--loop-accum-var)
>>
>>
>> -- Stefan
>>
>>
>>


Attachment: loop-perf-old
Description: Binary data

Attachment: loop-perf-new
Description: Binary data


reply via email to

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