Scheme Chez方案分配:--程序vs--脚本

Scheme Chez方案分配:--程序vs--脚本,scheme,chez-scheme,Scheme,Chez Scheme,考虑以下代码: Yikes,分配了800000字节 有什么不同 Ed以下是Kent Dybvig的回复: 这是一个有趣的问题 当使用--script(使用REPL语义)运行时,变量 脚本中定义的列表枚举和列表索引是可变的, 这会抑制过程间优化,包括内联。什么时候 但是,这些变量是不可变的,这允许 过程间优化 在这种情况下,--程序允许编译器将列表枚举内联到 列表索引的主体,以及列表索引中的lambda表达式 将主体放入列表枚举的主体中。最终的结果是有条件的 使用值生成器表达式调用中的表达式。这

考虑以下代码:

Yikes,分配了800000字节

有什么不同


Ed

以下是Kent Dybvig的回复:


这是一个有趣的问题

当使用--script(使用REPL语义)运行时,变量 脚本中定义的列表枚举和列表索引是可变的, 这会抑制过程间优化,包括内联。什么时候 但是,这些变量是不可变的,这允许 过程间优化

在这种情况下,--程序允许编译器将列表枚举内联到 列表索引的主体,以及列表索引中的lambda表达式 将主体放入列表枚举的主体中。最终的结果是有条件的 使用值生成器表达式调用中的表达式。这导致 编译器为使用者创建闭包,以避免代码 沿条件的then和else分支复制。这 每次通过list enumerate的循环创建闭包,导致 额外的分配开销。这就是优化经常采用的方式。 大多数情况下你会赢,但有时你会输。总的来说,好消息是 即使在你的项目中,收益也大于成本。我打电话给 在循环中列出索引(下面是修改后的代码),并发现 --程序运行时,代码运行速度大约快30%

肯特


(进口(chezscheme)) (定义(列表枚举ls val proc) (let循环((ls ls)(返回?#f)(val)) (如果(或)(空?ls) 返回?) 瓦尔 (使用值(lambda()(proc val(car ls))调用) (λ(返回?val) (循环(cdr ls)返回?val()()()))) (定义(列表索引ls proc) (列表)枚举 0 (兰姆达(一) (如果(程序elt) (价值观) (值#f(+i 1(()())(#f))) (定义n 100000) (定义数据(时间(iota n))) (让() (定义runalot (兰姆达(我砰的一声) (let循环([i]) (让([x(thunk)]) (如果(fx=i 1) x (循环(fx-i 1‘‘‘‘‘‘‘‘‘) (时间 (runalot 1000 (lambda() (列出索引数据(lambda(elt)(=elt(-n1(()())))) (import (chezscheme)) (define (list-enumerate ls val proc) (let loop ((ls ls) (return? #f) (val val)) (if (or (null? ls) return?) val (call-with-values (lambda () (proc val (car ls))) (lambda (return? val) (loop (cdr ls) return? val)))))) (define (list-index ls proc) (list-enumerate ls 0 (lambda (i elt) (if (proc elt) (values #t i) (values #f (+ i 1)))))) (define n 100000) (define data (iota n)) (time (list-index data (lambda (elt) (= elt (- n 1))))) ~ $ scheme --script ~/scratch/_list-enumerate-allocation-test-chez-a.sps (time (list-index data ...)) no collections 3 ms elapsed cpu time 4 ms elapsed real time 8 bytes allocated ~ $ scheme --program ~/scratch/_list-enumerate-allocation-test-chez-a.sps (time (list-index data ...)) no collections 3 ms elapsed cpu time 3 ms elapsed real time 800000 bytes allocated (import (chezscheme)) (define (list-enumerate ls val proc) (let loop ((ls ls) (return? #f) (val val)) (if (or (null? ls) return?) val (call-with-values (lambda () (proc val (car ls))) (lambda (return? val) (loop (cdr ls) return? val)))))) (define (list-index ls proc) (list-enumerate ls 0 (lambda (i elt) (if (proc elt) (values #t i) (values #f (+ i 1)))))) (define n 100000) (define data (time (iota n))) (let () (define runalot (lambda (i thunk) (let loop ([i i]) (let ([x (thunk)]) (if (fx= i 1) x (loop (fx- i 1))))))) (time (runalot 1000 (lambda () (list-index data (lambda (elt) (= elt (- n 1))))))))