Open smallnewer opened 6 years ago
最近在追JS的性能问题,踩到了一个坑,这个坑着实让我非常意外;而且项目里90%的性能坑都与此有关,也不知道是幸运还是不幸运。这个坑就是:当用对象[变量]的形式,我当初知道这个最差会变成一次map查询,并没在意,但是没想到会慢到150ns/per。 接下来的测试能大概复现这个问题。
对象[变量]
var obj1 = {a:1,b:1} function test1 () { var key = 'a' var key2 ='b' var st = Date.now(); // 函数保持单态可以被良好的JIT优化,而多态导致优化失败,运行期间会进行更耗时的lookup。 // 这里变化参数顺序,是为了复现多态。 for (var i = 0; i < 10000000/2; i++) { getByKEY(obj1, key, key2) }; for (var i = 0; i < 10000000/2; i++) { getByKEY(obj1, key2, key) }; console.log('test1', (Date.now() - st) * 1000000 / 10000000, 'ns') } function test2 () { var st = Date.now(); for (var i = 0; i < 10000000; i++) { getByLiteral(obj1) }; console.log('test2', (Date.now() - st) * 1000000 / 10000000, 'ns') } function getByKEY (obj1, key, key2) { return obj1[key] + obj1[key2] } function getByLiteral (obj1) { return obj1.a + obj1.b } test1(); // 15ns test1(); test1(); test1(); test1(); test2(); // 1ns test2(); test2(); test2(); test2(); test2();
测试里,一次慢查询是15ns,但在实际项目中是150ns~300ns,而使用字面量直接访问只有1ns。我不打算深究下去了(但深度怀疑两点,多个Isolate在单核里比Node慢;项目中内存使用情况复杂,有其他开销;),个人觉得这不是设计上的问题,恰好在设计上还留有余地给优化。许多语言都会触发该问题,只是慢一点和慢许多的问题。
那么解决思路的话,主要是两点:
具体下来,在我们的引擎里,已经想到了许多优化方案,相信会非常👍。
关于V8里对象的内存布局,已经有许多文章解释过了,这里贴最近看到的。 https://segmentfault.com/a/1190000008188648 http://mrale.ph/blog/2014/07/30/constructor-vs-objectcreate.html
最近在追JS的性能问题,踩到了一个坑,这个坑着实让我非常意外;而且项目里90%的性能坑都与此有关,也不知道是幸运还是不幸运。这个坑就是:当用
对象[变量]
的形式,我当初知道这个最差会变成一次map查询,并没在意,但是没想到会慢到150ns/per。 接下来的测试能大概复现这个问题。测试里,一次慢查询是15ns,但在实际项目中是150ns~300ns,而使用字面量直接访问只有1ns。我不打算深究下去了(但深度怀疑两点,多个Isolate在单核里比Node慢;项目中内存使用情况复杂,有其他开销;),个人觉得这不是设计上的问题,恰好在设计上还留有余地给优化。许多语言都会触发该问题,只是慢一点和慢许多的问题。
那么解决思路的话,主要是两点:
具体下来,在我们的引擎里,已经想到了许多优化方案,相信会非常👍。