9bd9590767
Previously we would write to class/style as strings `element.className` and `element.style.cssText`. Turns out that approach is good for initial render but not good for updates. Updates using this approach are problematic because we have to check to see if there was an out of bound write to style and than perform reconciliation. This also requires the browser to bring up CSS parser which is expensive. Another problem with old approach is that we had to queue the DOM writes and flush them twice. Once on element advance instruction and once in `hostBindings`. The double flushing is expensive but it also means that a directive can observe that styles are not yet written (they are written after directive executes.) The new approach uses `element.classList.add/remove` and `element.style.setProperty/removeProperty` API for updates only (it continues to use `element.className` and `element.style.cssText` for initial render as it is cheaper.) The other change is that the styling changes are applied immediately (no queueing). This means that it is the instruction which computes priority. In some circumstances it may result in intermediate writes which are than overwritten with new value. (This should be rare) Overall this change deletes most of the previous code and replaces it with new simplified implement. The simplification results in code savings. PR Close #34804 |
||
---|---|---|
.. | ||
class_binding | ||
directive_inputs | ||
directive_instantiate | ||
duplicate_map_based_style_and_class_bindings | ||
duplicate_style_and_class_bindings | ||
element_text_create | ||
interpolation | ||
listeners | ||
map_based_style_and_class_bindings | ||
ng_template | ||
noop_change_detection | ||
property_binding | ||
property_binding_update | ||
style_and_class_bindings | ||
style_binding | ||
BUILD.bazel | ||
README.md | ||
micro_bench.ts | ||
noop_renderer.ts | ||
noop_renderer_spec.ts | ||
profile_all.js | ||
profile_in_browser.html | ||
setup.ts | ||
shared.ts |
README.md
Build
yarn bazel build //packages/core/test/render3/perf:${BENCHMARK}_lib.min_debug.es2015.js --config=ivy
Run
node dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.es2015.js
Profile
node --no-turbo-inlining --inspect-brk dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.es2015.js
then connect with a debugger (the --inspect-brk
option will make sure that benchmark execution doesn't start until a debugger is connected and the code execution is manually resumed).
The actual benchmark code has calls that will start (console.profile
) and stop (console.profileEnd
) a profiling session.
Deoptigate
yarn add deoptigate
yarn deoptigate dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.es2015.js
Run All
To run all of the benchmarks use the profile_all.js
script:
node packages/core/test/render3/perf/profile_all.js
NOTE: This command will build all of the tests, so there is no need to do so manually.
Optionally use the --write
command to save the run result to a file for later comparison.
node packages/core/test/render3/perf/profile_all.js --write baseline.json
Comparing Runs
If you have saved the baseline (as described in the step above) you can use it to get change in performance like so:
node packages/core/test/render3/perf/profile_all.js --read baseline.json
The resulting output should look something like this:
┌────────────────────────────────────┬─────────┬──────┬───────────┬───────────┬───────┐
│ (index) │ time │ unit │ base_time │ base_unit │ % │
├────────────────────────────────────┼─────────┼──────┼───────────┼───────────┼───────┤
│ directive_instantiate │ 276.652 │ 'ms' │ 286.292 │ 'ms' │ -3.37 │
│ element_text_create │ 262.868 │ 'ms' │ 260.031 │ 'ms' │ 1.09 │
│ interpolation │ 257.733 │ 'us' │ 260.489 │ 'us' │ -1.06 │
│ listeners │ 1.997 │ 'us' │ 1.985 │ 'us' │ 0.6 │
│ map_based_style_and_class_bindings │ 10.07 │ 'ms' │ 9.786 │ 'ms' │ 2.9 │
│ noop_change_detection │ 93.256 │ 'us' │ 91.745 │ 'us' │ 1.65 │
│ property_binding │ 290.777 │ 'us' │ 280.586 │ 'us' │ 3.63 │
│ property_binding_update │ 588.545 │ 'us' │ 583.334 │ 'us' │ 0.89 │
│ style_and_class_bindings │ 1.061 │ 'ms' │ 1.047 │ 'ms' │ 1.34 │
│ style_binding │ 543.841 │ 'us' │ 545.385 │ 'us' │ -0.28 │
└────────────────────────────────────┴─────────┴──────┴───────────┴───────────┴───────┘
Notes
To run the benchmark use bazel run <benchmark_target>
, example:
yarn bazel run --config=ivy //packages/core/test/render3/perf:noop_change_detection
To profile, append _profile
to the target name and attach a debugger via chrome://inspect, example:
yarn bazel run --config=ivy //packages/core/test/render3/perf:noop_change_detection_profile
To interactively edit/rerun benchmarks use ibazel
instead of bazel
.