the web workers specification defines an api for spawning background scripts in your web application. web workers allow you to do things like fire up long-running scripts to handle computationally intensive tasks, but without blocking the ui or other scripts to handle user interactions.
我们先来定义一下我们的问题,由于业务比较复杂,我这里把问题简化成求1-1,0000,0000的和,然后在依次减去1-1,0000,0000,答案显而易见: 0! 这样做是因为数字太大的话会有数据精度的问题,两种方法的结果会有一些差异,会让人觉得并行的方法不可靠。此问题在我的mac pro chrome61下直接简单地跑js运行的话大概是1.5s(我们实际业务问题需要15s,这里为了避免用户测试的时候把浏览器搞死,我们简化了问题)。
const n = 100000000;// 总次数1亿
// 更新自2017-10-24 16:47:00
// 代码没有任何含义,纯粹是为了模拟一个耗时计算,直接用
// for (let i = start; i <= end; i = 1) total = i;
// 有几个问题,一是代码太简单没有任何稍微复杂一点的操作,后面用c代码优化的时候会优化得很夸张,没法对比。
// 二是数据溢出问题, 我懒得处理这个问题,下面代码简单地先加起来,然后再减掉,答案显而易见为0,便于测试。
function sum(start, end) {
let total = 0;
for (let i = start; i <= end; i = 1) {
if (i % 2 == 0 || i % 3 == 1) {
total = i;
} else if (i % 5 == 0 || i % 7 == 1) {
total = i / 2;
}
}
for (let i = start; i <= end; i = 1) {
if (i % 2 == 0 || i % 3 == 1) {
total -= i;
} else if (i % 5 == 0 || i % 7 == 1) {
total -= i / 2;
}
}
return total;
}
function parasum(n) {
const n1 = n / 10;//我们分成10分,没分分别交给一个web worker,parallel.js会根据电脑的cpu核数建立适量的workers
let p = new parallel([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.require(sum);
return p.map(n => sum((n - 1) * 10000000 1, n * 10000000))// 在parallel.js里面没法直接应用外部变量n1
.reduce(data => {
const acc = data[0];
const e = data[1];
return acc e;
});
}
export { n, sum, parasum }
bash
# fetch the latest registry of available tools.
./emsdk update
# download and install the latest sdk tools.
./emsdk install latest
# make the "latest" sdk "active" for the current user. (writes ~/.emscripten file)
./emsdk activate latest
# activate path and other environment variables in the current terminal
source ./emsdk_env.sh
#include
#include
int emscripten_keepalive add(int a, int b) {
return a b;
}
int main() {
printf("a b: %d", add(1, 2));
emscripten_exit_with_live_runtime();
return 0;
}
或者也可以直接在命令行中添加-s no_exit_runtime=1来解决,
emcc add2.c -o add2.js -s no_exit_runtime=1
不过会报一个警告:
exit(0) implicitly called by end of main(), but noexitruntime, so not exiting the runtime (you can use emscripten_force_exit, if you want to force a true shutdown)
// file sum.c
#include
// #include
long sum(long start, long end) {
long total = 0;
for (long i = start; i <= end; i = 3) {
total = i;
}
for (long i = start; i <= end; i = 3) {
total -= i;
}
return total;
}
int main() {
printf("sum(0, 1000000000): %ld", sum(0, 1000000000));
// emscripten_exit_with_live_runtime();
return 0;
}
➜ webasm-study gcc sum.c
➜ webasm-study time ./a.out
sum(0, 1000000000): 0./a.out 5.70s user 0.02s system 99% cpu 5.746 total
➜ webasm-study gcc -o1 sum.c
➜ webasm-study time ./a.out
sum(0, 1000000000): 0./a.out 0.00s user 0.00s system 64% cpu 0.003 total
➜ webasm-study gcc -o2 sum.c
➜ webasm-study time ./a.out
sum(0, 1000000000): 0./a.out 0.00s user 0.00s system 64% cpu 0.003 total
#include
// #include
// long emscripten_keepalive sum(long start, long end) {
long sum(long start, long end) {
long total = 0;
for (long i = start; i <= end; i = 1) {
if (i % 2 == 0 || i % 3 == 1) {
total = i;
} else if (i % 5 == 0 || i % 7 == 1) {
total = i / 2;
}
}
for (long i = start; i <= end; i = 1) {
if (i % 2 == 0 || i % 3 == 1) {
total -= i;
} else if (i % 5 == 0 || i % 7 == 1) {
total -= i / 2;
}
}
return total;
}
int main() {
printf("sum(0, 1000000000): %ld", sum(0, 100000000));
// emscripten_exit_with_live_runtime();
return 0;
}
执行结果大概要正常一些了。
➜ webasm-study gcc -o2 sum.c
➜ webasm-study time ./a.out
sum(0, 1000000000): 0./a.out 0.32s user 0.00s system 99% cpu 0.324 total
ok,我们来编译成asm.js了。
#include
#include
long emscripten_keepalive sum(long start, long end) {
// long sum(long start, long end) {
long total = 0;
for (long i = start; i <= end; i = 1) {
if (i % 2 == 0 || i % 3 == 1) {
total = i;
} else if (i % 5 == 0 || i % 7 == 1) {
total = i / 2;
}
}
for (long i = start; i <= end; i = 1) {
if (i % 2 == 0 || i % 3 == 1) {
total -= i;
} else if (i % 5 == 0 || i % 7 == 1) {
total -= i / 2;
}
}
return total;
}
int main() {
printf("sum(0, 1000000000): %ld", sum(0, 100000000));
emscripten_exit_with_live_runtime();
return 0;
}