Hi Daniel, On Wed 29 Jul 2009 14:50, Daniel Kraft <d...@domob.eu> writes:
> For the timings, I used a simple prime sieve implemented imperatively > with while and set's, because the recursive one would put elisp without > tail-calls at a disadvantage (and because lexical binding does not yet > work for lambda arguments); the code is attached. Both Scheme and Elisp > version are identical with just syntax changed (set! -> setq, define -> > defun, begin -> progn). Additionally, for lexical let all let's were > replaced by lexical-let's in the elisp version. After some thought on it, your approach sounds good. If you are benchmarking "how fast does X implement the prime sieve", it would be better to compare idiomatic code -- for Scheme, that would be a functional solution to the problem. But if your goal is "how fast is idiom X in language Y compared to language Z", your approach makes sense to me. > Iterative prime sieve, (length (find-primes-to 5000)): > Scheme: 0.42s > Elisp, no void checks, lexical let: 3.40s > Elisp, no void checks, dynamic let: 4.43s > Elisp, void checks, dynamic let: 5.12s > Elisp, void checks, lexical let: 4.06s > > So it apparent that both disabling void checks and using lexical let's > instead of the standard dynamic ones improve performance notably. > However, were quite out of reach of the Scheme version. > > My conjecture is that Don't conjecture, profile ;-) Also, disassembly is your friend here. > Obviously, it would help a lot to do so. On the other hand, switching > to primitive-ref's would help even more, but I fear we can not easily do > so, because we can not know if a symbol targets a primitive or was > rebound at compile time... BTW, a quick test with Scheme: > > scheme@(guile-user)> (set! + (lambda (a b) 42)) > scheme@(guile-user)> + > #<program b700a790 at <unknown port>:0:8 (a b)> > scheme@(guile-user)> (+ 1 2) > 3 > scheme@(guile-user)> (let ((+ (lambda (a b) 42))) > ... (+ 1 2)) > 42 This looks like a bug to me in the compiler. I guess we should open-code primitives based on value and not variable identity. > In any case, because of dynamic scoping and the expected behaviour of > flet to change possibly primitives during its extent, I think we can't > do anything like that for Elisp (except providing guile-primitive for > hand-optimizing such calls). Hmmmmmm. It seems that Emacs does inline, but it also reacts to flet. ELISP> (defun add (x y) (+ x y)) add ELISP> (compile-defun 'add) nil ELISP> (disassemble #'add) byte code for add: args: (x y) 0 varref x 1 varref y 2 plus 3 return ELISP> (require 'cl) cl ELISP> (flet ((+ (x y) (- x y))) (add 10 20)) -10 How does this work? Ken do you know? Regards, Andy -- http://wingolog.org/