Javascript 为什么web worker的性能在30秒后急剧下降?

Javascript 为什么web worker的性能在30秒后急剧下降?,javascript,multithreading,performance,google-chrome,web-worker,Javascript,Multithreading,Performance,Google Chrome,Web Worker,我试图提高在web worker中执行脚本时的性能。它设计用于在浏览器中解析大型文本文件而不会崩溃。一切都运行得很好,但我注意到,在使用web worker时,大型文件的性能存在严重差异 所以我做了一个简单的实验。我在同一输入上运行了两次脚本。第一次运行在页面的主线程中执行脚本(没有web工作人员)。自然地,这会导致页面冻结并失去响应。对于第二次运行,我在web worker中执行了脚本 对于本实验中的小文件(

我试图提高在web worker中执行脚本时的性能。它设计用于在浏览器中解析大型文本文件而不会崩溃。一切都运行得很好,但我注意到,在使用web worker时,大型文件的性能存在严重差异

所以我做了一个简单的实验。我在同一输入上运行了两次脚本。第一次运行在页面的主线程中执行脚本(没有web工作人员)。自然地,这会导致页面冻结并失去响应。对于第二次运行,我在web worker中执行了脚本

对于本实验中的小文件(<~100 MB),性能差异可以忽略不计。但是,在大型文件上,解析工作线程所需的时间大约要长20倍:

蓝线在预料之中。解析文件只需大约11秒,性能相当稳定:

红线是web worker内部的性能。更令人惊讶的是:

前30秒的锯齿线是正常的(锯齿线是由于在解析文件的每个块之后,将结果发送到主线程时有轻微延迟造成的)。然而,解析速度在30秒时会突然减慢。(请注意,我只使用一个web worker来完成此任务;一次绝不使用多个worker线程。)

我已经确认延迟不是通过
postMessage()
将结果发送到主线程。解析器的运行速度减慢,这是完全同步的。由于我无法解释的原因,循环速度急剧减慢,30秒后随着时间的推移,速度会变慢

但这只发生在网络工作者身上。如上所述,在主线程中运行相同的代码,运行非常平稳和快速

为什么会这样?我可以做些什么来提高性能?(我不希望任何人都能完全理解该文件中超过1200行的代码。如果你能理解,那就太棒了,但我觉得这与web workers的关系比我的代码更密切,因为它在主线程中运行良好。)

系统:我在MacOS10.9.4上运行Chrome35,内存为16GB;四核2.7 GHz Intel core i7,具有256 KB二级缓存(每核)和6 MB三级缓存。文件块的大小约为10MB


更新:刚刚在Firefox 30上试用过,在工作线程中没有遇到同样的速度减慢(但在主线程中运行时比Chrome慢)。然而,用更大的文件(大约1GB)进行同样的实验,在大约35-40秒后(看起来)产生了显著的减速。

您运行的是什么硬件?您的CPU可能会遇到缓存抖动问题。例如,如果CPU缓存为每个核心1MB(仅举一个例子),并且您开始尝试使用数据不断替换缓存(缓存未命中),那么您将遇到减速-这在MT系统中非常常见。这在IO传输中也很常见。此外,对于线程上下文,这些系统往往也有一些操作系统开销。因此,如果大量线程正在生成,您可能会花费比线程“工作”更多的时间来管理上下文。我还没有看过你的代码,所以我可能有点不对劲——但我的猜测是关于内存问题,这正是因为你的应用程序在做什么。:)

哦。如何修复。尝试使执行块成为与硬件匹配的小型单块。尽可能减少一次使用的线程数量-尽量使它们保持硬件中内核数量的2-3倍(这实际上取决于您拥有的硬件类型)。希望这会有帮助。

结果非常有用

他推测,在工作线程中使用
FileReaderSync
(而不是普通的ol'async
FileReader
)并没有为垃圾收集提供机会

将工作线程更改为异步使用
FileReader
(从直觉上看,这似乎是一种性能倒退),将进程加速到仅37秒,这正是我所期望的


我还没有收到泰勒的回复,我也不完全明白为什么垃圾收集会是罪魁祸首,但是
FileReaderSync
的一些东西大大减慢了代码的速度。

感谢这些想法。在我的问题中添加了系统规格。减小块大小是一个有趣的想法;我尝试使用2MB块而不是10MB块,但仍然注意到最后一百万行的速度显著下降(大约30秒)。而且它只运行过一个web worker(在我的问题中也得到了澄清)。不幸的是,我们似乎仍然需要找到一个解释。因此,我遇到了同样的问题,但我的垃圾收集没有发生,因为承诺链不允许恢复堆内存。使用快照,我可以看到当堆达到最大值时,fileReader的速度会减慢,然后爬行等待垃圾回收器释放更多空间。可能垃圾回收只能在返回事件循环时发生。我在一个简单的I=I+1循环中看到了同样的情况,即每100万次迭代打印一条消息。在Chrome上大约20秒,在Firefox上大约12秒后,速度开始放缓。这是什么?