docs: add `Function Inlining` rules to `PERF_NOTES.md` (#26876)
PR Close #26876
This commit is contained in:
parent
a2929dfd57
commit
683d53db4b
|
@ -68,6 +68,43 @@ for (var i = 0, keys = Object.keys(obj); i < keys.length; i++) {
|
||||||
## Recursive functions
|
## Recursive functions
|
||||||
Avoid recursive functions when possible because they cannot be inlined.
|
Avoid recursive functions when possible because they cannot be inlined.
|
||||||
|
|
||||||
|
## Function Inlining
|
||||||
|
|
||||||
|
VMs gain a lot of speed by inlining functions which are small (such as getters).
|
||||||
|
This is because the cost of the value retrieval (getter) is often way less than the cost of making a function call.
|
||||||
|
VMs use the heuristic of size to determine whether a function should be inline.
|
||||||
|
Thinking is that large functions probably will not benefit inlining because the overhead of function call is not significant to the overall function execution.
|
||||||
|
|
||||||
|
Our goal should be that all of the instructions which are in template function should be inlinable.
|
||||||
|
Here is an example of code which breaks the inlining and a way to fix it.
|
||||||
|
|
||||||
|
```
|
||||||
|
export function i18nStart(index: number, message: string, subTemplateIndex?: number): void {
|
||||||
|
const tView = getTView();
|
||||||
|
if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) {
|
||||||
|
// LOTS OF CODE HERE WHICH PREVENTS INLINING.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that the above function almost never runs because `tView.firstTemplatePass` is usually false.
|
||||||
|
The application would benefit from inlining, but the large code inside `if` prevents it.
|
||||||
|
Simple refactoring will fix it.
|
||||||
|
|
||||||
|
```
|
||||||
|
export function i18nStart(index: number, message: string, subTemplateIndex?: number): void {
|
||||||
|
const tView = getTView();
|
||||||
|
if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) {
|
||||||
|
i18nStartFirstTemplatePass(tView, index, message, subTemplateIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function i18nStartFirstTemplatePass(tView: TView, index: number, message: string, subTemplateIndex?: number): void {
|
||||||
|
// LOTS OF CODE HERE WHICH PREVENTS INLINING.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Loops
|
## Loops
|
||||||
Don't use foreach, it can cause megamorphic function calls (depending on the browser) and function allocations.
|
Don't use `forEach`, it can cause megamorphic function calls (depending on the browser) and function allocations.
|
||||||
It is [a lot slower than regular `for` loops](https://jsperf.com/for-vs-foreach-misko)
|
It is [a lot slower than regular `for` loops](https://jsperf.com/for-vs-foreach-misko)
|
||||||
|
|
Loading…
Reference in New Issue