perf(ivy): introduce a node-based micro-benchmarks harness (#32510)
PR Close #32510
This commit is contained in:
		
							parent
							
								
									66df745721
								
							
						
					
					
						commit
						2895edc9c6
					
				| @ -9,6 +9,7 @@ ts_library( | |||||||
|     ), |     ), | ||||||
|     deps = [ |     deps = [ | ||||||
|         "//packages/core", |         "//packages/core", | ||||||
|  |         "@npm//@types/node", | ||||||
|     ], |     ], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ yarn bazel build //packages/core/test/render3/perf:{name}.min_debug.es2015.js -- | |||||||
| 
 | 
 | ||||||
| ### Run  | ### Run  | ||||||
| 
 | 
 | ||||||
| time node dist/bin/packages/core/test/render3/perf/{name}.min_debug.es2015.js | node dist/bin/packages/core/test/render3/perf/{name}.min_debug.es2015.js | ||||||
| 
 | 
 | ||||||
| ### Profile | ### Profile | ||||||
| 
 | 
 | ||||||
| @ -19,4 +19,4 @@ The actual benchmark code has calls that will start (`console.profile`) and stop | |||||||
| In all the above commands {name} should be replaced with the actual benchmark (folder) name, ex.: | In all the above commands {name} should be replaced with the actual benchmark (folder) name, ex.: | ||||||
| - build: `yarn bazel build //packages/core/test/render3/perf:noop_change_detection.min_debug.es2015.js --define=compile=aot` | - build: `yarn bazel build //packages/core/test/render3/perf:noop_change_detection.min_debug.es2015.js --define=compile=aot` | ||||||
| - run: `time node dist/bin/packages/core/test/render3/perf/noop_change_detection.min_debug.es2015.js` | - run: `time node dist/bin/packages/core/test/render3/perf/noop_change_detection.min_debug.es2015.js` | ||||||
| - profile: `node --no-turbo-inlining --inspect-brk dist/bin/packages/core/test/render3/perf/noop_change_detection.min_debug.es2015.js` | - profile: `node --no-turbo-inlining --inspect-brk dist/bin/packages/core/test/render3/perf/noop_change_detection.min_debug.es2015.js profile` | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ import {ɵɵtext} from '../../../../src/render3/instructions/text'; | |||||||
| import {RenderFlags} from '../../../../src/render3/interfaces/definition'; | import {RenderFlags} from '../../../../src/render3/interfaces/definition'; | ||||||
| import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node'; | import {TNodeType, TViewNode} from '../../../../src/render3/interfaces/node'; | ||||||
| import {resetComponentState} from '../../../../src/render3/state'; | import {resetComponentState} from '../../../../src/render3/state'; | ||||||
|  | import {createBenchmark} from '../micro_bench'; | ||||||
| import {createAndRenderLView} from '../setup'; | import {createAndRenderLView} from '../setup'; | ||||||
| 
 | 
 | ||||||
| `<div>
 | `<div>
 | ||||||
| @ -72,9 +73,17 @@ resetComponentState(); | |||||||
| // create view once so we don't profile first template pass
 | // create view once so we don't profile first template pass
 | ||||||
| createAndRenderLView(null, embeddedTView, viewTNode); | createAndRenderLView(null, embeddedTView, viewTNode); | ||||||
| 
 | 
 | ||||||
| // profile create views (run templates in creation mode)
 | // scenario to benchmark
 | ||||||
| console.profile('create'); | const elementTextCreate = createBenchmark('element and text create', 500000, 20); | ||||||
| for (let i = 0; i < 500000; i++) { | const createTime = elementTextCreate('create'); | ||||||
|   createAndRenderLView(null, embeddedTView, viewTNode); | 
 | ||||||
|  | console.profile('element_text_create'); | ||||||
|  | while (createTime.run()) { | ||||||
|  |   while (createTime()) { | ||||||
|  |     createAndRenderLView(null, embeddedTView, viewTNode); | ||||||
|  |   } | ||||||
| } | } | ||||||
| console.profileEnd(); | console.profileEnd(); | ||||||
|  | 
 | ||||||
|  | // report results
 | ||||||
|  | elementTextCreate.report(); | ||||||
							
								
								
									
										71
									
								
								packages/core/test/render3/perf/micro_bench.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								packages/core/test/render3/perf/micro_bench.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | /** | ||||||
|  |  * @license | ||||||
|  |  * Copyright Google Inc. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  |  */ | ||||||
|  | const performance = require('perf_hooks').performance; | ||||||
|  | 
 | ||||||
|  | interface Benchmark { | ||||||
|  |   (versionName: string): Profile; | ||||||
|  |   report(fn?: (report: string) => void): void; | ||||||
|  | } | ||||||
|  | interface Profile { | ||||||
|  |   (): boolean; | ||||||
|  |   profileName: string; | ||||||
|  |   run(): boolean; | ||||||
|  |   bestTime: number; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function createBenchmark( | ||||||
|  |     benchmarkName: string, iterationCount: number, runs: number = 50): Benchmark { | ||||||
|  |   const profiles: Profile[] = []; | ||||||
|  | 
 | ||||||
|  |   const benchmark = function Benchmark(profileName: string): Profile { | ||||||
|  |     let iterationCounter: number = iterationCount; | ||||||
|  |     const profile: Profile = function Profile() { | ||||||
|  |       if (iterationCounter === 0) { | ||||||
|  |         iterationCounter = iterationCount; | ||||||
|  |         return false; | ||||||
|  |       } else { | ||||||
|  |         iterationCounter--; | ||||||
|  |         return true; | ||||||
|  |       } | ||||||
|  |     } as Profile; | ||||||
|  |     let lastTimestamp = 0; | ||||||
|  |     let runCount = runs; | ||||||
|  |     profile.run = function() { | ||||||
|  |       const now = performance.now(); | ||||||
|  |       if (lastTimestamp !== 0) { | ||||||
|  |         const time = now - lastTimestamp; | ||||||
|  |         profile.bestTime = Math.min(profile.bestTime, time); | ||||||
|  |       } | ||||||
|  |       lastTimestamp = now; | ||||||
|  |       if (runCount === 0) { | ||||||
|  |         runCount = runs; | ||||||
|  |         return false; | ||||||
|  |       } else { | ||||||
|  |         runCount--; | ||||||
|  |         return true; | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |     profile.profileName = profileName; | ||||||
|  |     profile.bestTime = Number.MAX_SAFE_INTEGER; | ||||||
|  |     profiles.push(profile); | ||||||
|  |     return profile; | ||||||
|  |   } as Benchmark; | ||||||
|  | 
 | ||||||
|  |   benchmark.report = function(fn?: (report: string) => void) { | ||||||
|  |     setTimeout(() => { | ||||||
|  |       const fastest = profiles.reduce((previous: Profile, current: Profile) => { | ||||||
|  |         return (previous.bestTime < current.bestTime) ? previous : current; | ||||||
|  |       }); | ||||||
|  |       (fn || console.log)(`Benchmark: ${benchmarkName}\n${profiles.map((profile: Profile) => { | ||||||
|  |         const percent = (100 - profile.bestTime / fastest.bestTime * 100).toFixed(0); | ||||||
|  |         return profile.profileName + ': ' + profile.bestTime.toFixed(0) + ` us(${percent} %) `; | ||||||
|  |       }).join('\n')}`);
 | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  |   return benchmark; | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user