[Top][All Lists]
[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.