Elisp performance
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
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
> 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
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
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.