Elisp performance

2009-07-29 Thread Daniel Kraft

Hi all,

as promised, here are some performance results for the current elisp 
compiler.  BTW, it supports now to disable checks for void-value on 
variable access via compiler options as well as the 
lexical-let/lexical-let* constructs that should mimic the ones from 
emacs' cl package (but in emacs they degrade performance, in Guile they 
improve it).


Lambda arguments are still always dynamically bound, which is quite a 
pity as it inhibits tail-call optimization; I'll work on a compiler 
option to always bind certain or all symbols lexically, including lambda 
arguments to counter this (and there's also an emacs branch doing this, 
so we're ultimatly even trying to be compatible...).


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.  Here are the results:


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 the remaining bottle-neck are the primitive calls, 
as they are still resolved using the dynamic-binding and fluid 
mechanisms; so maybe it is really a good idea to change function 
bindings to just global ones without dynamic scoping, and implement 
flet/flet* with dynamic-wind.  In contrast to variables, for functions 
access performance is a lot more important than let performance, I 
guess, so this might be the way to go.  What do you think?


As another test I implemented just a small loop, again both in Scheme 
and Elisp with identical code (also attached).  Here are the timing results:


Tight loop, (test 100):
  Scheme: 0.72s
  Elisp, no void checks, lexical let: 2.33s
  Elisp, no void checks, lexical let, guile-ref: 1.29s
  Elisp, no void checks, lexical let, guile-primitive: 0.92s

In the guile-ref and guile-primitive runs, I replaced both primitives (< 
and 1+) using the extension constructs (guile-ref (guile) is like (@ (guile) builds a (make-primitive-ref) in TreeIL.  The guile-ref timing is what 
we would also get if we changed function bindings like I suggested above.


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)> +
#:0:8 (a b)>
scheme@(guile-user)> (+ 1 2)
3
scheme@(guile-user)> (let ((+ (lambda (a b) 42)))
... (+ 1 2))
42

So it seems that the Scheme compiler just ignores this possibility... 
Is (set! + ...) and expecting (+ 1 2) to change invalid, or should this 
strictly be regarded as a bug?


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).


Yours,
Daniel

--
Done:  Arc-Bar-Cav-Ran-Rog-Sam-Tou-Val-Wiz
To go: Hea-Kni-Mon-Pri
; Imperative prime sieve in Elisp.

(defun sieve-out (pivot number-list)
  (lexical-let ((i number-list)
(result '())
(result-tail '()))
(while (not (null i))
  (if (not (zerop (% (car i) pivot)))
(if (consp result)
  (progn
(setcdr result-tail (cons (car i) '()))
(setq result-tail (cdr result-tail)))
  (progn
(setq result (cons (car i) '()))
(setq result-tail result
  (setq i (cdr i)))
result))

(defun sieve (number-list)
  (lexical-let ((i number-list)
(result '())
(result-tail '()))
(while (not (null i))
  (if (consp result)
(progn
  (setcdr result-tail (cons (car i) '()))
  (setq result-tail (cdr result-tail)))
(progn
  (setq result (list (car i)))
  (setq result-tail result)))
  (setq i (sieve-out (car i) i)))
result))

(defun find-primes-to (to)
  (lexical-let ((numbers '())
(i to))
(while (> i 2)
  (setq numbers (cons i numbers))
  (setq i (1- i)))
(sieve numbers)))
; Imperative prime sieve in Scheme.

(define (sieve-out pivot number-list)
  (let ((i number-list)
(result '())
(result-tail '()))
(while (not 

Porting GNU Projects - Guile

2009-07-29 Thread bornlibra23

Hello People
I am trying to port various GNU products to Stratus OpenVOS platform
including the guile project. However I am stuck currently for the lack of
wide & multibyte character support. Can somebody guide me to an
implementation of the same that I can port first. The glibc is also proving
a monster to port for various reasons. I have tried to build the wide
character support of glibc separately but it didnt workout. Can somebody
isolate the code & guide me in implementing it on VOS? This is proving to be
a major blocker. Please help
Thanks
bornlibra23

libtool: compile:  "/<>/OpenSource/guile-1.8.6/build-aux/compile" gcc
-DHAVE_CONFIG_H -I.. -I.. -I.. -D_POSIX_C_SOURCE=200112L -D_BSD_SOURCE
-D_SYSV -D_VOS_EXTENDED_NAMES -Wall -Wmissing-prototypes -Werror -MT
libguile_la-srfi-14.lo -MD -MP -MF .deps/libguile_la-srfi-14.Tpo -c
srfi-14.c -o libguile_la-srfi-14.o
srfi-14.c: In function `scm_srfi_14_compute_char_sets':
srfi-14.c:1531: warning: suggest parentheses around comparison in operand of
|
gmake[3]: *** [libguile_la-srfi-14.lo] Error 1
gmake[3]: Leaving directory `<>/OpenSource/guile-1.8.6/libguile'
gmake[2]: *** [all] Error 2
gmake[2]: Leaving directory `<>/OpenSource/guile-1.8.6/libguile'
gmake[1]: *** [all-recursive] Error 1
gmake[1]: Leaving directory `<>/OpenSource/guile-1.8.6'
gmake: *** [all] Error 2
-- 
View this message in context: 
http://www.nabble.com/Porting-GNU-Projects---Guile-tp24721426p24721426.html
Sent from the Gnu - Guile - Dev mailing list archive at Nabble.com.





Re: Porting GNU Projects - Guile

2009-07-29 Thread Mike Gran

> From: bornlibra23 
> 
> Hello People
> I am trying to port various GNU products to Stratus OpenVOS platform
> including the guile project. However I am stuck currently for the lack of
> wide & multibyte character support. Can somebody guide me to an
> implementation of the same that I can port first. The glibc is also proving
> a monster to port for various reasons. I have tried to build the wide
> character support of glibc separately but it didnt workout. Can somebody
> isolate the code & guide me in implementing it on VOS? This is proving to be
> a major blocker. Please help
> Thanks
> bornlibra23

Hi-

I'm a little unclear on what you need first.  It is

1. Guile doesn't do multibyte characters.

or

2. You are having problems building GNU programs in general because it is
hard to get glibc's multibyte characters to work.

If it is the former (#1) case, it is true that Guile doesn't do multi-byte.
There is an experimental version of Guile in the Git repository that does do 
multi-byte characters, but, it is still brand new and not well tested.
But, FWIW, it is the git string_abstraction2 tree.  Hopefully the multi-byte
chars support will make its way into mainline Guile in time for 2.0.

If it is the latter case, I imagine that porting GNU libc is tricky.  I
tried it once, years ago, and it was painful.

For Guile compilation problems in general for a new platform, it might help 
to use the "--disable-error-on-warning" options for Guile's ./configure 
at first when trying to get it to compile.

Also, I saw that you were trying to compile 1.8.6.  There is a 1.8.7, which
has some bug fixes.

-Mike




Re: Elisp performance

2009-07-29 Thread Ken Raeburn

On Jul 29, 2009, at 08:50, Daniel Kraft wrote:

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


It doesn't mean much without testing on the same machine, of course,  
but I get ~1s times for running your lexical-let elisp version in  
emacs.  It'd be a bit of a symbolic win if you can match Emacs's own  
Lisp execution times. :-)  Though of course, Emacs runs nearly  
everything byte-compiled, so it would only be symbolic.  (In this  
case, the byte-compiled lexical-let version took about 0.2s on my  
machine, even better than the Scheme version on your machine.)


I should run some timing tests myself -- I'm particularly interested  
in the allocation/gc performance of Guile vs Emacs, for obvious reasons.


My conjecture is that the remaining bottle-neck are the primitive  
calls, as they are still resolved using the dynamic-binding and  
fluid mechanisms; so maybe it is really a good idea to change  
function bindings to just global ones without dynamic scoping, and  
implement flet/flet* with dynamic-wind.  In contrast to variables,  
for functions access performance is a lot more important than let  
performance, I guess, so this might be the way to go.  What do you  
think?


Sounds reasonable to me, but I'm not an expert in that area.

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:

[]
So it seems that the Scheme compiler just ignores this  
possibility... Is (set! + ...) and expecting (+ 1 2) to change  
invalid, or should this strictly be regarded as a bug?


In general I don't think you can assume it for all symbols, but if it  
helps, the Emacs byte-compiler also assumes that "+" and "cons" and  
certain other functions won't be redefined.  It's even got an "add1"  
opcode.


So if I understand right, if you make similar assumptions and change  
how function bindings are handled, your performance for this code  
drops to under a second?  It sounds like maybe you can get within  
shouting distance of Emacs's own performance already, at least for  
certain test cases.


Would this interfere with possibly blending Scheme GOOPS code with  
Elisp someday?  Or is the generic support there at a lower level than  
this?  (E.g., a "marker" object holds a buffer handle, possibly nil,  
and an offset that automatically gets adjusted if text is inserted  
before it.  You can use "(+ 1 marker)" and get back an integer one  
greater than the marker's current offset.  If markers were implemented  
using GOOPS, would this use of "+" work, given the changes you're  
suggesting?)


Ken




Re: Porting GNU Projects - Guile

2009-07-29 Thread bornlibra23

Thanks Mike for the heads up but the problem I think is with the source code
itself. I get the same error on linux though it doesnt die there. I
preprocessed the code & changed the line like so :
>From (ch) == ' ' | (ch) == '\t') to (ch) == ' ' || (ch) == '\t')
(note the or operator) & the problem went away but then I had the mentioned
problem. I will build it again & get back to you. My build log seems to be
dated.
-- 
View this message in context: 
http://www.nabble.com/Porting-GNU-Projects---Guile-tp24721426p24731881.html
Sent from the Gnu - Guile - Dev mailing list archive at Nabble.com.