diff --git a/packages/core/src/render3/PERF_NOTES.md b/packages/core/src/render3/PERF_NOTES.md index 9a75641e00..cea21d2f12 100644 --- a/packages/core/src/render3/PERF_NOTES.md +++ b/packages/core/src/render3/PERF_NOTES.md @@ -68,6 +68,43 @@ for (var i = 0, keys = Object.keys(obj); i < keys.length; i++) { ## Recursive functions 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 -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)