这个编译成JavaScript的Haskell程序如何比JavaScript本身更快?

我总是相信GHCJS,由于显而易见的原因,与手动编写和优化的代码相比,生成了非常慢的 JavaScript程序.然而,在试验它时,我注意到它没有我想象的那么糟糕.我决定运行一系列小基准来掌握真正的表现,这一点特别让我感到惊讶.该程序只需用“1”填充一个数组并将它们加起来.

哈斯克尔:

import Data.Array.Repa
len  = 1024*1024*64
arr  = fromFunction (Z :. len) (const 1) :: Array D DIM1 Float
main = sumAllP arr >>= print

JavaScript的:

var len = 1024*1024*64
var arr = [];
var sum = 0;
for (var i=0; i<len; ++i)
    arr[i] = 1;
for (var i=0; i<len; ++i)
    sum += arr[i];
console.log(sum);

一个粗略的基准:

apple1$ghcjs -O2 bench_fill.hs -funfolding-use-threshold10000 -funfolding-keeness-factor1000 -o bench_fill.js; time node bench_fill.js/all.js
Linking bench_fill.js (Main)
6.7108864e7

real    0m1.543s
user    0m1.512s
sys 0m0.033s

apple1$time node benchfill.js
67108864

real    0m1.764s
user    0m1.173s
sys 0m0.583s

GHCJS如何比苗条,干净的原生for循环运行得更快?考虑到生成代码应该暴露给的盒装数量,这应该是不可能的.

解决方法

数组D DIM1 Float是一个 delayed array.它只是表示为函数const 1加上数组的边界.在任何地方都没有存储6400万个Floats的数组.

JavaScript程序实际上创建了一个6400万双精度数组,使用512 MB内存.读取和写入如此大的阵列的成本是不可忽视的(分配成本的成本;注意大量的系统时间).

相关文章

什么是深拷贝与浅拷贝?深拷贝与浅拷贝是js中处理对象或数据...
前言 今天复习了一些前端算法题,写到一两道比较有意思的题:...
最近在看回JavaScript的面试题,this 指向问题是入坑前端必须...
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面