我正在尝试提高在网络工作者中执行脚本的性能。它旨在解析浏览器中的大型文本文件而不会崩溃。一切正常,但我注意到使用Web Worker时大文件的性能存在严重差异。
所以我进行了一个简单的实验。我在同一输入上运行了两次脚本。第一次运行在页面主线程中执行了脚本(没有Web Worker)。自然,这将导致页面冻结并变得无响应。对于第二次运行,我在Web Worker中执行了脚本。
对于本实验中的小文件(<〜100 MB),性能差异可以忽略不计。但是,在大文件上,解析工作线程所需的时间大约是原来的20倍:
蓝线是预期的。解析文件只需要大约11秒,并且性能相当稳定:
红线是网络工作人员内部的表现。更令人惊讶的是:
前30秒的锯齿状线是正常现象(锯齿现象是由于在解析文件的每个块之后将结果发送到主线程中的轻微延迟引起的)。但是,解析会在30秒后突然变慢。(请注意,我只使用一个Web工作者进行该工作;一次最多只能使用一个工作者线程。)
我已经确认延迟不是使用将结果发送到主线程postMessage()
。减速器处于解析器的紧密循环中,该循环是完全同步的。由于我无法解释的原因,该循环会大大减慢速度,并且在30秒后会随着时间的推移而变慢。
但这仅在网络工作者中发生。如上所见,在主线程中运行相同的代码可以非常平稳,快速地运行。
为什么会这样呢?我该怎么做才能提高性能?(我不希望有人能完全理解该文件中的所有1200多行代码。如果您这样做,那真是太棒了,但是我觉得这比Web工作人员更重要,而不是我的代码,因为它在主代码中运行正常线。)
系统:我正在具有16 GB内存的Mac OS 10.9.4上运行Chrome 35;四核2.7 GHz Intel Core i7四核处理器,具有256 KB L2缓存(每个核心)和6 MB的L3缓存。文件块的大小约为10 MB。
更新:刚在Firefox 30上尝试过,它在工作线程中没有遇到相同的速度下降(但是在主线程中运行时,它比Chrome慢)。但是,尝试使用更大的文件(大约1 GB)进行相同的实验会在大约35-40秒后(看来)显着降低速度。
泰勒·奥尔特(Tyler Ault)在Google+上提出了一种可能性,事实证明它很有帮助。
他推测FileReaderSync
在工作线程中使用(而不是普通的ol'async FileReader
)并没有提供进行垃圾收集的机会。
更改工作线程以FileReader
异步使用(从直觉上看,这似乎是性能上的倒退),将过程加速到仅37秒,恰好是我期望的那样。
我还没有收到Tyler的回音,我也不完全确定我理解为什么垃圾回收是罪魁祸首,但是有关的事情FileReaderSync
却大大降低了代码的速度。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句