emacs-devel
[Top][All Lists]
Advanced

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

Re: return


From: Chong Yidong
Subject: Re: return
Date: Fri, 03 Dec 2010 18:00:22 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux)

Stefan Monnier <address@hidden> writes:

> A few questions:
> - how do you explain that Fwhile with internal catch is faster (1.057 <
>   1.084) than without an internal catch?  Or is that what you mean by
>   "within the margin of error"?
> - You seem to be measuring time for the interpreted code, is that right?
>   If so, I think it would be more interesting to measure the time for
>   byte-code.
>
> The little tests I've performed seem to indicate that for interpreted
> code the extra `catch' doesn't make much of a difference, but for the
> compiled version of your test, the difference is around 20%.

Hmm, yes, I was testing on interpreted code.  Here is a new test using a
byte-compiled file:

(defun test-loop-nocatch ()
  (dotimes (ii 2000000)
    (let ((ll '(1 2 3 4 5 6 7 8 9 10)))
      (while ll
        (setq ll (cdr ll))))))

Averaging over ten runs, this takes 1.351 +- 0.022s without an internal
catch, and 1.371 +- 0.034s with an internal catch.

Using the Emacs without an internal-catch, I tested on a byte-compiled
version of a function with a catch inserted manually into the loop:

(defun test-loop-catch ()
  (dotimes (ii 2000000)
    (let ((ll '(1 2 3 4 5 6 7 8 9 10)))
      (while ll
        (catch 'exit
          (setq ll (cdr ll)))))))

The result is 1.725 +- 0.033s.

The simplistic "internal catch" implementation I used is this:

*** src/eval.c  2010-10-26 22:23:09 +0000
--- src/eval.c  2010-12-03 22:59:10 +0000
***************
*** 1054,1065 ****
    return unbind_to (count, elt);
  }
  
! DEFUN ("while", Fwhile, Swhile, 1, UNEVALLED, 0,
!        doc: /* If TEST yields non-nil, eval BODY... and repeat.
! The order of execution is thus TEST, BODY, TEST, BODY and so on
! until TEST returns nil.
! usage: (while TEST BODY...)  */)
!   (Lisp_Object args)
  {
    Lisp_Object test, body;
    struct gcpro gcpro1, gcpro2;
--- 1054,1061 ----
    return unbind_to (count, elt);
  }
  
! Lisp_Object
! internal_while (Lisp_Object args)
  {
    Lisp_Object test, body;
    struct gcpro gcpro1, gcpro2;
***************
*** 1078,1083 ****
--- 1074,1090 ----
    return Qnil;
  }
  
+ DEFUN ("while", Fwhile, Swhile, 1, UNEVALLED, 0,
+        doc: /* If TEST yields non-nil, eval BODY... and repeat.
+ The order of execution is thus TEST, BODY, TEST, BODY and so on
+ until TEST returns nil.
+ usage: (while TEST BODY...)  */)
+   (Lisp_Object args)
+ {
+   int count = SPECPDL_INDEX ();
+   return internal_catch (Qexit, &internal_while, args);
+ }
+ 
  DEFUN ("macroexpand", Fmacroexpand, Smacroexpand, 1, 2, 0,
         doc: /* Return result of expanding macros at top level of FORM.
  If FORM is not a macro call, it is returned unchanged.



reply via email to

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