为什么网络工作者的表现在30秒后急剧下降?

Mat*_*att 27 javascript performance multithreading google-chrome web-worker

我正在尝试在Web worker中执行时提高脚本的性能.它旨在解析浏览器中的大型文本文件而不会崩溃.一切都运行良好,但我注意到使用Web worker时大文件的性能存在严重差异.

所以我进行了一个简单的实验.我在同一个输入上运行了两次脚本.第一次运行在页面的主线程中执行脚本(没有web worker).当然,这会导致页面冻结并变得无法响应.对于第二次运行,我在Web worker中执行了脚本.

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

两种方案在同一图表上的性能

预计蓝线.它只需要大约11秒来解析文件,性能相当稳定:

没有web worker的脚本的性能

红线是Web worker中的性能.更令人惊讶的是:

Web worker中脚本的性能

前30秒的锯齿状线是正常的(jag是由解析文件的每个块后将结果发送到主线程的轻微延迟引起的).但是,解析在30秒时相当突然减慢.(请注意,我只使用一个Web工作者来完成工作;一次只能使用一个工作线程.)

我已经确认延迟不是将结果发送到主线程的postMessage().减速是在解析器的紧密循环中,这完全是同步的.由于我无法解释的原因,该循环显着减慢并且在30秒后随着时间变慢.

但这只发生在网络工作者身上.正如您在上面看到的那样,在主线程中运行相同的代码,运行非常顺畅和快速.

为什么会这样?我该怎么做才能提高性能?(我不希望任何人完全理解该文件中的所有1,200多行代码.如果你这样做,那真是太棒了,但我觉得这与网络工作者的关系比我的代码更多,因为它在主文件中运行良好线.)

系统:我在Mac OS 10.9.4上运行Chrome 35,内存为16 GB; 四核2.7 GHz Intel Core i7,具有256 KB L2缓存(每个核心)和3 MB的L3缓存.文件块大小约为10 MB.

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

Mat*_*att 16

Tyler Ault在Google+上提出了一种可能性非常有用的建议.

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

将工作线程更改为FileReader异步使用(直观地看起来像是向后性能步骤)将该过程加速回到37秒,就在我期望的那样.

我还没有收到Tyler的回复,我不完全确定我理解为什么垃圾收集会成为罪魁祸首,但是有些事情FileReaderSync大大减慢代码的速度.