通过计算fib(45) 对比 js WebAssembly 的速度
python 花了大概400秒.....计算密集型任务很不适合原生python
import time
def fib(n):
return n if n<2 else fib(n-1)+fib(n-2)
for i in range(10):
print(i,fib(i))
st = time.time()
print(fib(45))
ed = time.time()
print(ed-st) # 399.13077569007874
原生c 6秒左右,开O3优化效果没有显著变化,而且有时候更慢...
#include
#include //用到rand()函数
#include //用到clock()函数
int fib(int n)
{
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
int main()
{
int begintime, endtime;
int i = 0;
for (i = 0; i < 10; i++)
printf("%d\n", fib(i));
begintime = clock(); //计时开始
printf("%d\n", fib(45));
endtime = clock(); //计时结束
printf("\n\nRunning Time:%dms\n", endtime - begintime); // 6489 ms
return 0;
}
使用numba加速, 有点厉害
import time
from numba import jit
@jit
def fib(n):
return n if n < 2 else fib(n - 1) + fib(n - 2)
for i in range(10):
print(i, fib(i))
st = time.time()
print(fib(45)) // 1134903170
ed = time.time()
print(ed - st) # 7.599677801132202
java, 竟然比c快, 应该是做了递归优化
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(fib(i));
}
long st = System.currentTimeMillis();
System.out.println(fib(45)); // 1134903170
long ed = System.currentTimeMillis();
System.out.println(ed - st); // 4105
}
public static int fib(int n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
}
js 10 秒左右,相比python已经很好了
Titlefunction fib(n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2)
}
for (let i = 0; i < 10; i++) {
console.log(i, fib(i))
}
let st = new Date().getTime()
fib(45)
let ed = new Date().getTime()
console.log(ed - st) // 11016 11397
使用 WebAssembly 7秒多! 很接近c了
创建hello 项目, 在main中增加代码
WASM_EXPORT 为导出命令,类似export
构建运行,如果没有错误,下载项目,WebAssembly 代码大小为100多k....稍微有点大,但为了速度可以接受
在本地修改main.js
获取导出对象,以及使用
instance = results.instance;
console.log(instance)
let fib = instance.exports.fib
fib(45)
let st = new Date().getTime()
console.log(fib(45));
let ed = new Date().getTime()
console.log('time', ed - st)
完整代码
let x = '../out/main.wasm';
let instance = null;
let memoryStates = new WeakMap();
function syscall(instance, n, args) {
switch (n) {
default:
// console.log("Syscall " + n + " NYI.");
break;
case /* brk */
45:
return 0;
case /* writev */
146:
return instance.exports.writev_c(args[0], args[1], args[2]);
case /* mmap2 */
192:
debugger;
const memory = instance.exports.memory;
let memoryState = memoryStates.get(instance);
const requested = args[1];
if (!memoryState) {
memoryState = {
object: memory,
currentPosition: memory.buffer.byteLength,
};
memoryStates.set(instance, memoryState);
}
let cur = memoryState.currentPosition;
if (cur + requested > memory.buffer.byteLength) {
const need = Math.ceil((cur + requested - memory.buffer.byteLength) / 65536);
memory.grow(need);
}
memoryState.currentPosition += requested;
return cur;
}
}
let s = "";
fetch(x).then(response =>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, {
env: {
__syscall0: function __syscall0(n) {
return syscall(instance, n, []);
},
__syscall1: function __syscall1(n, a) {
return syscall(instance, n, [a]);
},
__syscall2: function __syscall2(n, a, b) {
return syscall(instance, n, [a, b]);
},
__syscall3: function __syscall3(n, a, b, c) {
return syscall(instance, n, [a, b, c]);
},
__syscall4: function __syscall4(n, a, b, c, d) {
return syscall(instance, n, [a, b, c, d]);
},
__syscall5: function __syscall5(n, a, b, c, d, e) {
return syscall(instance, n, [a, b, c, d, e]);
},
__syscall6: function __syscall6(n, a, b, c, d, e, f) {
return syscall(instance, n, [a, b, c, d, e, f]);
},
putc_js: function (c) {
c = String.fromCharCode(c);
if (c == "\n") {
console.log(s);
s = "";
} else {
s += c;
}
}
}
})
).then(results => {
instance = results.instance;
document.getElementById("container").textContent = instance.exports.main();
console.log(instance)
let fib = instance.exports.fib
fib(45)
let st = new Date().getTime()
console.log(fib(45));
let ed = new Date().getTime()
console.log('time', ed - st)
}).catch(console.error);