承诺的网络工作者的速度
Speed of Promisified Web Workers
我需要多次 (>10,000) 次计算数学密集型函数。我想我会使用网络工作者来减少计算时间。
我正在使用一个创建函数 blob 的函数,将其执行包装在一个 promise 中,并在 blob 上运行 web worker。我测试了它并且它有效,但运行速度比单线程方法慢得多。
单线程:3 毫秒
多线程:5524 毫秒
包含时间测试的完整代码:
https://codepen.io/zakerytclarke/pen/BgRyBm?editors=0012
此代码计算前 n 个方块并将它们推入数组。控制台显示 运行 单线程和多线程各自的时间。
这是我用来承诺网络工作者的功能。是不是有什么问题导致执行时间远远超过简单的 for 循环?
function thread(fn){
return function(args){
return new Promise(function(resolve) {
var worker=new Worker(URL.createObjectURL(new Blob(['('+fn+')('+JSON.stringify(args)+')'])));
worker.postMessage(args)
worker.onmessage = function(event){
resolve(event.data);
worker.terminate();
};
});
}
}
感谢您的帮助。
如果重要的话,这是我 CPU 上的信息:
uinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 76
model name : Intel(R) Atom(TM) x7-Z8700 CPU @ 1.60GHz
stepping : 3
microcode : 0x367
cpu MHz : 901.401
cache size : 1024 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 4
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm ida arat
bugs : cpu_meltdown spectre_v1 spectre_v2
bogomips : 3200.00
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 76
model name : Intel(R) Atom(TM) x7-Z8700 CPU @ 1.60GHz
stepping : 3
microcode : 0x367
cpu MHz : 875.272
cache size : 1024 KB
physical id : 0
siblings : 4
core id : 1
cpu cores : 4
apicid : 2
initial apicid : 2
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm ida arat
bugs : cpu_meltdown spectre_v1 spectre_v2
bogomips : 3200.00
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
processor : 2
vendor_id : GenuineIntel
cpu family : 6
model : 76
model name : Intel(R) Atom(TM) x7-Z8700 CPU @ 1.60GHz
stepping : 3
microcode : 0x367
cpu MHz : 860.525
cache size : 1024 KB
physical id : 0
siblings : 4
core id : 2
cpu cores : 4
apicid : 4
initial apicid : 4
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm ida arat
bugs : cpu_meltdown spectre_v1 spectre_v2
bogomips : 3200.00
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
processor : 3
vendor_id : GenuineIntel
cpu family : 6
model : 76
model name : Intel(R) Atom(TM) x7-Z8700 CPU @ 1.60GHz
stepping : 3
microcode : 0x367
cpu MHz : 557.593
cache size : 1024 KB
physical id : 0
siblings : 4
core id : 3
cpu cores : 4
apicid : 6
initial apicid : 6
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm ida arat
bugs : cpu_meltdown spectre_v1 spectre_v2
bogomips : 3200.00
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:```
您忽略了网络工作者的严重开销。难怪你的代码会通过字符串化一个函数来创建一个 blob,从该文件创建一个 worker,解析 worker 的代码,实例化一个 promise,发送消息,设置一个监听器,并异步等待 worker 的结果,比两个双精度数的单次乘法慢几千倍。事实上,我很惊讶你竟然能在 5 秒内生成 10000 个工人。
This benchmark 估计设置一个 worker 大约需要 40 毫秒。所以不,工人不是你应该为任何事情产生的轻量级线程。它们意味着 工作线程 ,您应该向它们发送(许多)消息以进行处理和响应。您可能希望创建工作池以将负载分散到多个线程。
当然,对于你的square
功能none这个适用。它太小了——它只做一次乘法。在主线程上执行它比与另一个线程通信的任何事情都要快。如果您在该函数中有一个 100000 项循环,那么在后台线程中 运行 成为 运行 可能会变得值得。您实现的 3 毫秒 single-threaded 性能甚至不会明显阻塞主线程。
我需要多次 (>10,000) 次计算数学密集型函数。我想我会使用网络工作者来减少计算时间。
我正在使用一个创建函数 blob 的函数,将其执行包装在一个 promise 中,并在 blob 上运行 web worker。我测试了它并且它有效,但运行速度比单线程方法慢得多。
单线程:3 毫秒 多线程:5524 毫秒
包含时间测试的完整代码:
https://codepen.io/zakerytclarke/pen/BgRyBm?editors=0012
此代码计算前 n 个方块并将它们推入数组。控制台显示 运行 单线程和多线程各自的时间。
这是我用来承诺网络工作者的功能。是不是有什么问题导致执行时间远远超过简单的 for 循环?
function thread(fn){
return function(args){
return new Promise(function(resolve) {
var worker=new Worker(URL.createObjectURL(new Blob(['('+fn+')('+JSON.stringify(args)+')'])));
worker.postMessage(args)
worker.onmessage = function(event){
resolve(event.data);
worker.terminate();
};
});
}
}
感谢您的帮助。
如果重要的话,这是我 CPU 上的信息:
uinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 76 model name : Intel(R) Atom(TM) x7-Z8700 CPU @ 1.60GHz stepping : 3 microcode : 0x367 cpu MHz : 901.401 cache size : 1024 KB physical id : 0 siblings : 4 core id : 0 cpu cores : 4 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 11 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm ida arat bugs : cpu_meltdown spectre_v1 spectre_v2 bogomips : 3200.00 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual power management: processor : 1 vendor_id : GenuineIntel cpu family : 6 model : 76 model name : Intel(R) Atom(TM) x7-Z8700 CPU @ 1.60GHz stepping : 3 microcode : 0x367 cpu MHz : 875.272 cache size : 1024 KB physical id : 0 siblings : 4 core id : 1 cpu cores : 4 apicid : 2 initial apicid : 2 fpu : yes fpu_exception : yes cpuid level : 11 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm ida arat bugs : cpu_meltdown spectre_v1 spectre_v2 bogomips : 3200.00 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual power management: processor : 2 vendor_id : GenuineIntel cpu family : 6 model : 76 model name : Intel(R) Atom(TM) x7-Z8700 CPU @ 1.60GHz stepping : 3 microcode : 0x367 cpu MHz : 860.525 cache size : 1024 KB physical id : 0 siblings : 4 core id : 2 cpu cores : 4 apicid : 4 initial apicid : 4 fpu : yes fpu_exception : yes cpuid level : 11 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm ida arat bugs : cpu_meltdown spectre_v1 spectre_v2 bogomips : 3200.00 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual power management: processor : 3 vendor_id : GenuineIntel cpu family : 6 model : 76 model name : Intel(R) Atom(TM) x7-Z8700 CPU @ 1.60GHz stepping : 3 microcode : 0x367 cpu MHz : 557.593 cache size : 1024 KB physical id : 0 siblings : 4 core id : 3 cpu cores : 4 apicid : 6 initial apicid : 6 fpu : yes fpu_exception : yes cpuid level : 11 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm 3dnowprefetch epb pti ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid tsc_adjust smep erms dtherm ida arat bugs : cpu_meltdown spectre_v1 spectre_v2 bogomips : 3200.00 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual power management:```
您忽略了网络工作者的严重开销。难怪你的代码会通过字符串化一个函数来创建一个 blob,从该文件创建一个 worker,解析 worker 的代码,实例化一个 promise,发送消息,设置一个监听器,并异步等待 worker 的结果,比两个双精度数的单次乘法慢几千倍。事实上,我很惊讶你竟然能在 5 秒内生成 10000 个工人。
This benchmark 估计设置一个 worker 大约需要 40 毫秒。所以不,工人不是你应该为任何事情产生的轻量级线程。它们意味着 工作线程 ,您应该向它们发送(许多)消息以进行处理和响应。您可能希望创建工作池以将负载分散到多个线程。
当然,对于你的square
功能none这个适用。它太小了——它只做一次乘法。在主线程上执行它比与另一个线程通信的任何事情都要快。如果您在该函数中有一个 100000 项循环,那么在后台线程中 运行 成为 运行 可能会变得值得。您实现的 3 毫秒 single-threaded 性能甚至不会明显阻塞主线程。