性能优化和引擎

Optimization in JavaScript

Posted by yellowDog on 2018-07-18

参考: V8


V8 和 SpiderMonkey

The biggest difference is in compilation. SpiderMonkey compiles JavaScript to an intermediate language which is interpreted. V8 differs by compiling JavaScript to machine instructions, eliminating a need for an interpreter.

SpiderMonkey 编译成中间的解释语言, 而 V8 则是直接编译成机器码, 无需解释器


V8 中的优化–常量折叠

Math.pow(x,x) != x**x
1
2
const diff = x => Math.pow(x, x) - x ** x;
diff(99); //0
1
2
3
4
5
6
7
8
console.log(99,99);
const {a,b} = {99,99};
console.log(a**b);
console.log(Math.pow(99,99));

3.697296376497268e+197
3.697296376497263e+197
3.697296376497263e+197
1
2
3
for(let i = 0;i<100*100*100;i++)

=> for(let i = 0;i<1000000;i++)

V8 对象属性的fast模式

V8 中所有变量都继承 Value, 原始值都继承 Primitive, 对象的类型为 Object, 继承自 Value

对象有两种访问模式:

  • Dictionary mode(字典模式)
    使用哈希表来存储对象

  • Fast mode(快速模式)
    类似 C 的 struct 来表示对象

当动态的添加/删除太多属性, 对象就会变成字典模式

  • 新建的对象 -> fast 模式

  • 添加太多的属性 -> slow 模式

  • 设置为其他对象的 prototype -> fast 模式


Array.sort()

1
[1,3,23,2].sort() // => [1,2,23,3]

之前一直想了解 sort()里的高阶函数的原理,虽然只知道是按照字典来的,正好看到了 jjc 大大的文章

Calling comparefn(a,b) always returns the same value v when given a specific pair of values a and b as its two arguments. Furthermore, Type(v) is Number, and v is not NaN. Note that this implies that exactly one of a < b, a = b, and a > b will be true for a given pair of a and b. --ECMA 规范

  • sort()的高阶函数(Calling)
1
2
3
4
5
6
7
8
9
10
comparefn = function (x, y) {
if (x === y) return 0;
if (%_IsSmi(x) && %_IsSmi(y)) {
return %SmiLexicographicCompare(x, y);
}
x = TO_STRING(x); // <----- 坑
y = TO_STRING(y); // <----- 坑
if (x == y) return 0;
else return x < y ? -1 : 1;
};
  • 插入排序算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function InsertionSort(a, from, to) {
for (var i = from + 1; i < to; i++) {
var element = a[i];
for (var j = i - 1; j >= from; j--) {
var tmp = a[j];
var order = comparefn(tmp, element);
if (order > 0) { // <---- 注意这里
a[j + 1] = tmp;
} else {
break;
}
}
a[j + 1] = element;
}

数组元素小于 10 个,V8 选择插入排序,大于 10 个的时候使用快排

函数都写好 -> 进行排序

Move array holes and undefineds to the end using a Javascript function

下面比较两个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let data = [
{value: 4},
{value: 2},
{value: undefined},
{value: undefined},
{value: 1},
{value: undefined},
{value: undefined},
{value: 7},
{value: undefined},
{value: 4}
];

//method1
data
.map(x => x.value)
.sort((x,y) => x-y)

//method2
data
.sort((x,y) => x.value - y.value)
.map(x => x.value)
  • 方法1把undefined全部放在最后面,只比较[4,2,1,7,4],得到[1,2,4,4,7,undefined,undefined,undefined,undefined,undefined]

  • 方法2 undefined参与排序的时候会得到NaN,进入上面的else,得到[2, 4, undefined, undefined, 1, undefined, undefined, 7, undefined, 4]