Dear Chickeneers,
the attached patch changes the implementation of promises to be slightly
more efficient when forcing a promise more than once (one procedure call
less). Also, instead of keeping the promise result in the promise
thunk's closure it is now kept in a slot of the promise structure. This
allows for removing the reference to the thunk once the promise has been
forced and thus saving some memory. I measured its effect by running the
following program with and without the patch:
(define seq
(let next ((n 0))
(cons n (delay (next (+ n 1))
(define (run)
(print
(time
(let loop ((seq seq))
(if (< (car seq) 100)
(loop (force (cdr seq)))
(car seq)
(print (memory-statistics)))
(run)
(run)
The results of which are:
without patch:
0.856s CPU time, 0.352s GC time (major), 50 mutations, 9/1539 GCs
(major/minor)
50
#(268435456 230448536 1048576)
0.034s CPU time, 0/213 GCs (major/minor)
50
#(268435456 230448536 1048576)
with the patch:
0.506s CPU time, 0.233s GC time (major), 50 mutations, 11/1500 GCs
(major/minor)
50
#(134217728 107357264 1048576)
0.03s CPU time, 0/198 GCs (major/minor)
50
#(134217728 107357264 1048576)
Hope it's of interested and not fatally flawed!
Moritz
>From b42464bccb2852121148c726eb49b90566d4519e Mon Sep 17 00:00:00 2001
From: Moritz Heidkamp
Date: Mon, 5 Nov 2012 16:14:36 +0100
Subject: [PATCH] Make promises slightly more efficient and less memory
intensive
Instead of keeping the promise result in the promise thunk's closure
the implementation is changed to keep the result in a slot of the
promise structure. This allows for removing the reference to the thunk
once the promise has been forced and thus saving some memory.
---
library.scm | 28 ++--
1 file changed, 10 insertions(+), 18 deletions(-)
diff --git a/library.scm b/library.scm
index 438004a..1711b84 100644
--- a/library.scm
+++ b/library.scm
@@ -341,8 +341,15 @@ EOF
(define (##sys#force promise)
(if (##sys#structure? promise 'promise)
- ((##sys#slot promise 1))
- promise) )
+ (apply ##sys#values
+ (or (##sys#slot promise 2)
+ (let ((results (##sys#call-with-values (##sys#slot promise 1) (lambda xs xs
+ (or (##sys#slot promise 2)
+ (begin
+ (##sys#setslot promise 1 #f)
+ (##sys#setslot promise 2 results)
+ results)
+ promise))
(define force ##sys#force)
@@ -4708,22 +4715,7 @@ EOF
;;; Promises:
(define (##sys#make-promise proc)
- (let ([result-ready #f]
- [results #f] )
-(##sys#make-structure
- 'promise
- (lambda ()
- (if result-ready
- (apply ##sys#values results)
- (##sys#call-with-values
- proc
- (lambda xs
- (if result-ready
- (apply ##sys#values results)
- (begin
- (set! result-ready #t)
- (set! results xs)
- (apply ##sys#values results) ) ) ) ) ) ) ) ) )
+ (##sys#make-structure 'promise proc #f))
(define (promise? x)
(##sys#structure? x 'promise) )
--
1.7.12
___
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers