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) 1000000)
            (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), 500000 mutations, 9/1539 GCs 
(major/minor)
  500000
  #(268435456 230448536 1048576)
  0.034s CPU time, 0/213 GCs (major/minor)
  500000
  #(268435456 230448536 1048576)

with the patch:

  0.506s CPU time, 0.233s GC time (major), 500000 mutations, 11/1500 GCs 
(major/minor)
  500000
  #(134217728 107357264 1048576)
  0.03s CPU time, 0/198 GCs (major/minor)
  500000
  #(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 <mor...@twoticketsplease.de>
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

Reply via email to