There are five full sections
1.JavaScript workflow engine: The processing pipeline JavaScript engine, this part will involve the contents of the interpreter / compiler, and will introduce the differences and points in common between the different engines;
2.JavaScript object model;
3. Optimization property access: by engine interspersed introduce the concept of Shapes, Transistion chain tree, ICs and so on is how to optimize the acquired object properties;
4. efficient storage array;
5.Take-aways: to do a full-text content summary, and gave two suggestions.
1. JavaScript engine workflow
All this had to begin from JavaScript code you write. JavaScript parsing engine after its source is converted into an abstract syntax tree (AST). Based on AST, the interpreter will be able to work and produce bytecode. Great! At this engine is executing JavaScript code.
1.1 JavaScript engine interpreter / compiler processes
Now, let's focus on the actual execution of JavaScript code that this part of the process, that is where the code is interpreted and optimized, and discuss some of the differences that exist between the major JavaScript engine.
In general, (all JavaSciript engine) has an interpreter and comprising optimizing compiler process flow. Wherein the interpreter can quickly generate bytecode is not optimized, while optimizing compiler will take longer to eventually generate highly optimized machine code.
The general procedure is almost the same with the V8 engine used in the workflow and Node.js in Chrome:
The interpreter is referred to as V8 Ignition, which is responsible for generating and executing bytecode. When it is running bytecode data collection and analysis, and then it can be used to accelerate (code) of the execution speed. When a function becomes hot, such as it is often called, the generated bytecode and analysis of data will be passed to our TurboFan-- optimizing compiler, it generates highly optimized machine code based on the analysis data.
SpiderMonkey, Firefox and the use of SpiderNode in Mozilla's JavaScript engine, there are a number of different places. They have two optimizing compiler. Code interpreter to explain Baseline compiler, the partially optimized code compiler can generate. Analysis of data collected when the code is run in conjunction with, IonMonkey compiler can generate highly optimized code. If the attempt fails optimization, IonMonkey will fall back to Baseline stage code.
Chakra, and Edge for Microsoft JavaScript engine Node-ChakraCore two projects, there are two similar compiler optimization settings. Interpreter code optimized to SimpleJIT-- Representative wherein JIT Just-In-Time compiler - it partially optimized code may be generated. Analysis of binding data, FullJIT may generate optimized code deeper.
JavaScriptCore (abbreviated as JSC), Apple's JavaScript engine, Safari and React Native is used for two projects, it reaches the ultimate three different optimizing compiler allows effects. Lower LLInt interpreter passes the code interpreter Baseline to the compiler, and (after Baseline compiler) optimized code will be passed to the compiler DFG, (DFG compiler after treatment) the results of the final pass compiler FTL deal with.
Why do some engine will have more optimizing compilers do? This is completely compromises choice. The interpreter can quickly generate bytecode, the bytecode is usually but not efficient enough. On the other hand, optimizing compiler process takes longer, but it will eventually generate more efficient machine code. In the end is quick access to executable code (interpreter), or take more time but in the end the best performance running code (optimizing compiler), which contains a balance. Some engine selects to add a plurality of different time-consuming optimizing compiler / efficiency characteristic, with higher complexity by more fine-grained control over the cost of such compromise.
We have just highlighted the JavaScript engine in each main difference between interpreter and compiler optimization process. In addition to these differences, all JavaScript engines have the same architecture: that is to have some kind of a parser and interpreter / compiler processes.
2. JavaScript Object Model
For example, JavaScript engine is how to achieve JavaScript object model, and what techniques they use to speed up JavaScript object properties get the speed? It turns out that all the major engines are very similar in the realization of this.
ECMAScript specification is defined as substantially all of the objects mapped to the string key property attribute dictionary.
In addition , the specification also defines the following properties: [[Value]]
-
[[Writable]]
Determine whether the property can be re-assigned; -
[[Enumerable]]
Determine whether this property appears in the cycle;for-in
-
[[Configurable]]
Determine whether the property can be deleted.
[[双方括号]]
The symbol indicates that looks something special, but that is not directly exposed specification defines a JavaScript representation of the property. You can still in JavaScript by the specified object's API property values: Object.getOwnPropertyDescriptor
const object = { foo: 42 };
Object.getOwnPropertyDescriptor(object, 'foo');
// → { value: 42, writable: true, enumerable: true, configurable: true }
JavaScript is an object of this definition, the array it?
You can imagine the array into a special set of objects. One difference is the array index array will both special handling. Array index referred to herein is a term specific ECMAScript specification. In JavaScript, the array is limited to a maximum of 2 ^ 32-1 have items. Refers to any valid array index index within the limits, i.e., any integer from 0 to 2 ^ 32-2.
Another difference is that there is a magical array of attributes. length
const array = ['a', 'b'];
array.length; // → 2
array[2] = 'c';
array.length; // → 3
In this example, array
when generating unit of length 2. Then we as an index to 2
the location assigned to another element, length
attribute will be automatically updated.
JavaScript on the way to define arrays and objects similar. For example, the array includes all the key indices are explicitly represented as a string. The key value is '0' position of the first array element is stored in.
'length'
Property happens to be another non-enumeration and non-configurable attributes.
Once an element is added to the array, JavaScript is automatically updated attribute property values. 'length'
[[Value]]
In general, the behavior is very similar to the array of objects.
3. Optimization of property access
Let us deep knowledge of JavaScript engine is how to effectively deal with objects related operations.
JavaScript observation program, visit a property is the most common operation. JavaScript engine enables quick access to property will be crucial.
const object = {
foo: 'bar',
baz: 'qux',
};
// Here, we’re accessing the property `foo` on `object`:
doSomething(object.foo);
// ^^^^^^^^^^
3.1 Shapes
In JavaScript program, multiple objects with the same key attributes are very common. These objects have the same shape.
const object1 = { x: 1, y: 2 };
const object2 = { x: 3, y: 4 };
// `object1` and `object2` have the same shape.
Access the same property with the same shape of the object is also very common:
function logX(object) {
console.log(object.x);
// ^^^^^^^^
}
const object1 = { x: 1, y: 2 };
const object2 = { x: 3, y: 4 };
logX(object1);
logX(object2);
With this in mind, JavaScript engine can attribute to optimize the shape of the object based on the object of acquisition. It is so achievable.
Suppose we have a property with and an object, it uses the dictionary data structures discussed earlier: it contains the key value represented by the string, but they point to the respective attribute values. x
y
If you visit a property, for example , JavaScript engine will find the key , and then load the appropriate property values, and returns . object.y
JSObject
'y'
[[Value]]
But these property values are stored in the memory of how it? Should we store them as a part of? Suppose we encounter more objects of the same shape later, then in their store contains a complete dictionary of attribute names and values is very wasteful (space), because all objects with the same shape we have repeated the attribute name . It is too redundant and introduces unnecessary memory usage. As optimization, engine objects stored separately. JSObject
JSObject
Shape
Shape
In addition to containing all the attribute names and the rest outside the properties. Instead, comprising an offset value for the inside, in order to know where to find specific JavaScript engine value. Each having the same shape are pointing to this example. Each now only need to store only those values for this object is. [[Value]]
Shape
JSObject
JSObject
Shape
JSObject
When we have multiple objects, advantages become visible. No matter how many objects as long as they have the same shape, we only need their shape and key attribute information stored once!
All of the JavaScript engine are used as shape optimization, but have different address:
-
Papers call them Hidden Classes (easily confused with class concept in JavaScript)
-
They called V8 Maps (and easily in JavaScript to confuse the concept)
Map
-
They called Chakra Types (easy and JavaScript dynamic type and keyword confusion)
typeof
-
JavaScriptCore call them Structures
-
SpiderMonkey call them Shapes.
3.2 Transition chain with tree
If you have an object with a particular shape, but it Youxiang you add a property, what will happen this time? How to find the JavaScript engine is the new shape?
const object = {};
object.x = 5;
object.y = 6;
In JavaScript engine, the representation of the shapes is referred to as transition chain. The following shows an example:
The object does not have any properties in the initialization, so that it points to a null shape. The next statement object added value for the attribute , the attribute contains a JavaScript engine steering Shape, and to the first offset is added at a 0 value . Next, a statement adds a property , then the steering engine comprising another and Shape, and the value attached to (at offset at). 5
“x”
“x”
JSObject
5
'y'
'x'
'y'
6
JSObject
1
We do not even need to complete each Shape memory attribute table. Instead, each Shape just need to know it introduced new attributes. For example, in this case, we do not have to last a Shape stored on it can be found on the earlier of the chain of information, because. To do this, each Shape of Shape will before its connected: 'x'
If you wrote the JavaScript code , the JavaScript engine will look for properties along transition chain until you find the introduction of property Shape. o.x
“x”
“x”
However, if you just can not create a transition chain it? For example, if you have two empty object, and each object you add a different attribute?
const object1 = {};
object1.x = 5;
const object2 = {};
object2.y = 6;
In this case we will have to branch operations, then we end up with a transition tree instead of transition chain:
Here, we create an empty object , and then add a property to it . We ultimately obtained contains a single value , and two Shapes: empty and contains only attributes Shape Shape. a
'x'
JSObject
x
The second example is an empty object from the beginning, but after being added to a different property . We shape the final form two chains, a total of three shape. b
'y'
Does this mean that we always need to start with an empty shape it? It is not. Engine for literal objects contain attributes will apply some optimization. Let's say we start adding either from an empty object literal property, either have a property that already contains an object literal: x
x
const object1 = {};
object1.x = 5;
const object2 = { x: 6 };
In the first example, we start with an empty shape, then turned to include shape, which, as we have seen before us. x
In one example, having a property to directly generate the object is significant, not from the empty object and then transition connection. object2
x
Attribute contains literal object from the group consisting shape begins to be effectively empty skip shape. SpiderMonkey and V8 (at least) to do so. This optimization transition shortened chain, and is configured such that an object from the literal more efficient. 'x'
'x'
Benedikt Bowen surprising polymorphism in React applications discussed how these subtleties affect actual performance.
3.3 Inline Caches (ICs)
Shapes main motivation behind the concept of Inline Caches or ICs. ICs are key factors have contributed to the rapid run JavaScript! JavaScript engines use ICs to remember where to find information about object properties, to reduce the number of costly lookup.
There is a function that takes an object and removed from the attribute values: getX
x
function getX(o) {
return o.x;
}
If we execute this function in JSC, it generates byte code as follows:
A command (from the first parameter ) in the load attribute values and stored into the address of. We returned the second instruction stored content. get_by_id
arg1
'x'
loc0
loc0
JSC also instructions embedded Inline Cache, which consists of two uninitialized slots. get_by_id
Now let's say we use the object to call a function. As we know, this object contains a property of Shape, Shape memory properties of the offsets and other properties. When you execute the first function, instruction looks for the property , and found that the offset value is stored in its place. {x:'a'}
getX
'x'
x
get_by_id
'x'
0
Embedded in the shape and offset of the IC memory instruction attribute: get_by_id
For subsequent operation, only the IC Shape contrast, if it is the same as before, only the attribute value is loaded from the memory offset. Specifically, if the shape before the JavaScript engine to see an object to be recorded through the IC, it is no longer necessary contact with the attribute information - but can skip expensive lookup attribute information (the process). Each time this attribute much faster than Find.
4. efficient storage array
For an array, the array storage attributes such as indexes, etc. are very common. The value of the property is referred to as array elements. Characteristic storage properties of each array each array element (property attributes) would be a wasteful storage. On the contrary, because the array index default attribute is writable, enumerable and configurable, JavaScript engines use this to separate array elements with other naming attributes are stored.
Consider this array:
const array = [
'#jsconfeu',
];
Engine stores the length of the array ( 1
), and comprising a point and Shape characteristic properties. offset
'length'
This've seen similar before us ...... but an array of values stored where?
Each has a separate array elements backing store, which contains the attribute values for all of the array index. JavaScript engine does not have to store any attribute characteristics to the array elements, because they are usually writable, enumerable and configurable.
So if it is not the usual situation? If you change the properties of the array elements, how to do?
// Please don’t ever do this!
const array = Object.defineProperty(
[],
'0',
{
value: 'Oh noes!!1',
writable: false,
enumerable: false,
configurable: false,
}
);
The above code fragment defines a named attribute (which happens to be an array index), but the characteristic ( ) is provided to a non-default value. '0'
value
In this case the edge, JavaScript engine will all elements backing store the dictionary as a subscript of an array mapped to the property characteristics.
Even if only one array element having a non-default attribute, backing store processing of the entire array will enter this slow and inefficient mode. Avoid using the array index Object.defineProperty
!
5. Take-aways
We have learned is how to store the JavaScript engine and an array of objects, and Shapes and how IC is optimized for their common operations. Based on this knowledge, we have identified a number of practical JavaScript coding skills help to improve the performance of:
-
Always initialize the object in the same way, to ensure that they will not come to a different shape direction.
-
Do not confuse the array element attribute property (property attributes), to ensure efficient storage and manipulation thereof.