このコードが CMUCL でヒープをオーバーフローしているのはなぜですか? 400MBのメモリを与えても、(setq extensions:*bytes-consed-between-gcs* 400000000)
CMUCLはまだチョークします。
; [GC threshold exceeded with 12,012,544 bytes in use. Commencing GC.]
; [GC completed with 188,064 bytes retained and 11,824,480 bytes freed.]
; [GC will next occur when at least 400,188,064 bytes are in use.]
; [GC threshold exceeded with 400,202,280 bytes in use. Commencing GC.]
; [GC completed with 207,120 bytes retained and 399,995,160 bytes freed.]
; [GC will next occur when at least 400,207,120 bytes are in use.]
このコードは CCL と SBCL で正常に動作しますが、メモリ使用量は調べていません。
これは CMUCL のバグですか?? これらの関数はすべて末尾再帰的だと思います。
(defun sqrt-iter (guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
(defun improve (guess x)
(average guess (/ x guess)))
(defun average (x y)
(/ (+ x y) 2))
(defun good-enough? (guess x)
(< (abs (- (* guess guess) x)) 0.001))
(defun mysqrt (x)
(sqrt-iter 1.0 x))
(defun zint (x acc step)
(setq num-iter (+ 1 num-iter))
(if (>= x 10000.0)
acc
(zint (+ x step)
(+ acc (* step (mysqrt x)))
step)))
(setq num-iter 0)
(format t "result=~A; iterations=~A~%" (zint 0.0 0.0 .001) num-iter)
(quit)
編集: はい、CMUCL は間違いなく多くの不必要なコンスを行います。次の簡単な例を試してください。
$ ~/cmucl/bin/lisp
...
* (defun foo () (bar))
FOO
* (defun bar () (foo))
BAR
* (foo)
; [GC threshold exceeded with 12,009,008 bytes in use. Commencing GC.]
; [GC completed with 111,816 bytes retained and 11,897,192 bytes freed.]
; [GC will next occur when at least 12,111,816 bytes are in use.]
; [GC threshold exceeded with 12,120,912 bytes in use. Commencing GC.]
; [GC completed with 120,016 bytes retained and 12,000,896 bytes freed.]
; [GC will next occur when at least 12,120,016 bytes are in use.]
; [GC threshold exceeded with 12,133,576 bytes in use. Commencing GC.]