1*c8dee2aaSAndroid Build Coastguard Worker<!-- This benchmark run a lot of small benchmarks that are defined with a karma-like sytax 2*c8dee2aaSAndroid Build Coastguard Worker in canvas_perf.js 3*c8dee2aaSAndroid Build Coastguard Worker--> 4*c8dee2aaSAndroid Build Coastguard Worker<!DOCTYPE html> 5*c8dee2aaSAndroid Build Coastguard Worker<html> 6*c8dee2aaSAndroid Build Coastguard Worker<head> 7*c8dee2aaSAndroid Build Coastguard Worker <title>CanvasKit SKP Perf</title> 8*c8dee2aaSAndroid Build Coastguard Worker <meta charset="utf-8" /> 9*c8dee2aaSAndroid Build Coastguard Worker <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 10*c8dee2aaSAndroid Build Coastguard Worker <meta name="viewport" content="width=device-width, initial-scale=1.0"> 11*c8dee2aaSAndroid Build Coastguard Worker <script src="/static/canvaskit.js" type="text/javascript" charset="utf-8"></script> 12*c8dee2aaSAndroid Build Coastguard Worker <script src="/static/benchmark.js" type="text/javascript" charset="utf-8"></script> 13*c8dee2aaSAndroid Build Coastguard Worker <script src="/static/canvas_perf.js" type="text/javascript" charset="utf-8"></script> 14*c8dee2aaSAndroid Build Coastguard Worker <style type="text/css" media="screen"> 15*c8dee2aaSAndroid Build Coastguard Worker body { 16*c8dee2aaSAndroid Build Coastguard Worker margin: 0; 17*c8dee2aaSAndroid Build Coastguard Worker padding: 0; 18*c8dee2aaSAndroid Build Coastguard Worker } 19*c8dee2aaSAndroid Build Coastguard Worker </style> 20*c8dee2aaSAndroid Build Coastguard Worker</head> 21*c8dee2aaSAndroid Build Coastguard Worker<body> 22*c8dee2aaSAndroid Build Coastguard Worker <main> 23*c8dee2aaSAndroid Build Coastguard Worker <button id="start_bench">Start Benchmark</button> 24*c8dee2aaSAndroid Build Coastguard Worker <br> 25*c8dee2aaSAndroid Build Coastguard Worker <canvas id=anim width=600 height=600 style="height: 600px; width: 600px;"></canvas> 26*c8dee2aaSAndroid Build Coastguard Worker </main> 27*c8dee2aaSAndroid Build Coastguard Worker <script type="text/javascript" charset="utf-8"> 28*c8dee2aaSAndroid Build Coastguard Worker const WIDTH = 600; 29*c8dee2aaSAndroid Build Coastguard Worker const HEIGHT = 600; 30*c8dee2aaSAndroid Build Coastguard Worker const WARM_UP_FRAMES = 5; 31*c8dee2aaSAndroid Build Coastguard Worker // Keeping this a little lower because this test runs many smaller tests, 32*c8dee2aaSAndroid Build Coastguard Worker // each for this many frames, which could add up to a long time. 33*c8dee2aaSAndroid Build Coastguard Worker const MAX_FRAMES = 51; 34*c8dee2aaSAndroid Build Coastguard Worker 35*c8dee2aaSAndroid Build Coastguard Worker // Any external files needed by tests in canvas_perf.js must be listed here. 36*c8dee2aaSAndroid Build Coastguard Worker // And checked in under canvas_perf_assets/ 37*c8dee2aaSAndroid Build Coastguard Worker // tests may then fetch them from ctx.files['filename'] 38*c8dee2aaSAndroid Build Coastguard Worker const testDataFiles = [ 39*c8dee2aaSAndroid Build Coastguard Worker 'test_64x64.png', 40*c8dee2aaSAndroid Build Coastguard Worker 'test_512x512.png', 41*c8dee2aaSAndroid Build Coastguard Worker 'test_1500x959.jpg', 42*c8dee2aaSAndroid Build Coastguard Worker 'Roboto-Regular.ttf', 43*c8dee2aaSAndroid Build Coastguard Worker 'Roboto-Regular.woff', 44*c8dee2aaSAndroid Build Coastguard Worker 'Roboto-Regular.woff2', 45*c8dee2aaSAndroid Build Coastguard Worker ]; 46*c8dee2aaSAndroid Build Coastguard Worker 47*c8dee2aaSAndroid Build Coastguard Worker (function() { 48*c8dee2aaSAndroid Build Coastguard Worker const filePromises = []; 49*c8dee2aaSAndroid Build Coastguard Worker for (const filename of testDataFiles) { 50*c8dee2aaSAndroid Build Coastguard Worker filePromises.push(fetch('/static/assets/'+filename).then((resp) => { 51*c8dee2aaSAndroid Build Coastguard Worker return resp.arrayBuffer(); // this is also a promise. 52*c8dee2aaSAndroid Build Coastguard Worker })); 53*c8dee2aaSAndroid Build Coastguard Worker } 54*c8dee2aaSAndroid Build Coastguard Worker const externals = Promise.all(filePromises).then((results) => { 55*c8dee2aaSAndroid Build Coastguard Worker const files = {}; 56*c8dee2aaSAndroid Build Coastguard Worker let i=0; 57*c8dee2aaSAndroid Build Coastguard Worker for (const bytes of results) { 58*c8dee2aaSAndroid Build Coastguard Worker // store them by name 59*c8dee2aaSAndroid Build Coastguard Worker files[testDataFiles[i]] = bytes; 60*c8dee2aaSAndroid Build Coastguard Worker i++; 61*c8dee2aaSAndroid Build Coastguard Worker } 62*c8dee2aaSAndroid Build Coastguard Worker return files; 63*c8dee2aaSAndroid Build Coastguard Worker }); 64*c8dee2aaSAndroid Build Coastguard Worker 65*c8dee2aaSAndroid Build Coastguard Worker const loadCanvasKit = CanvasKitInit({ 66*c8dee2aaSAndroid Build Coastguard Worker locateFile: (file) => '/static/' + file, 67*c8dee2aaSAndroid Build Coastguard Worker }); 68*c8dee2aaSAndroid Build Coastguard Worker 69*c8dee2aaSAndroid Build Coastguard Worker Promise.all([loadCanvasKit, externals]).then(([CanvasKit, externalFiles]) => { 70*c8dee2aaSAndroid Build Coastguard Worker const urlSearchParams = new URLSearchParams(window.location.search); 71*c8dee2aaSAndroid Build Coastguard Worker let glversion = 2; 72*c8dee2aaSAndroid Build Coastguard Worker if (urlSearchParams.has('webgl1')) { 73*c8dee2aaSAndroid Build Coastguard Worker glversion = 1; 74*c8dee2aaSAndroid Build Coastguard Worker } 75*c8dee2aaSAndroid Build Coastguard Worker let surface = getSurface(CanvasKit, glversion); 76*c8dee2aaSAndroid Build Coastguard Worker if (!surface) { 77*c8dee2aaSAndroid Build Coastguard Worker console.error('Could not make surface', window._error); 78*c8dee2aaSAndroid Build Coastguard Worker return; 79*c8dee2aaSAndroid Build Coastguard Worker } 80*c8dee2aaSAndroid Build Coastguard Worker 81*c8dee2aaSAndroid Build Coastguard Worker document.getElementById('start_bench').addEventListener('click', async () => { 82*c8dee2aaSAndroid Build Coastguard Worker window._perfData = {}; 83*c8dee2aaSAndroid Build Coastguard Worker 84*c8dee2aaSAndroid Build Coastguard Worker // canvas_perf.js should have defined an array called tests whose objects have: 85*c8dee2aaSAndroid Build Coastguard Worker // setup: A function called once before testing begins, it is expected to make its 86*c8dee2aaSAndroid Build Coastguard Worker // own canvas and put it in ctx. 87*c8dee2aaSAndroid Build Coastguard Worker // test: A function called to draw one frame 88*c8dee2aaSAndroid Build Coastguard Worker // teardown: A function called after testing finishes 89*c8dee2aaSAndroid Build Coastguard Worker // description: A human readable description 90*c8dee2aaSAndroid Build Coastguard Worker // perfkey: A key used to save the results in perf.skia.org. 91*c8dee2aaSAndroid Build Coastguard Worker // 92*c8dee2aaSAndroid Build Coastguard Worker // For quick local bench testing, there is also an array called onlytests. This way 93*c8dee2aaSAndroid Build Coastguard Worker // a developer can replace tests.push with onlytests.push to just run one or two 94*c8dee2aaSAndroid Build Coastguard Worker // performance benchmarks they care about. 95*c8dee2aaSAndroid Build Coastguard Worker let testsToRun = tests; 96*c8dee2aaSAndroid Build Coastguard Worker if (onlytests.length) { 97*c8dee2aaSAndroid Build Coastguard Worker testsToRun = onlytests; 98*c8dee2aaSAndroid Build Coastguard Worker } 99*c8dee2aaSAndroid Build Coastguard Worker 100*c8dee2aaSAndroid Build Coastguard Worker for (const t of testsToRun) { 101*c8dee2aaSAndroid Build Coastguard Worker let ctx = { 102*c8dee2aaSAndroid Build Coastguard Worker 'surface': surface, 103*c8dee2aaSAndroid Build Coastguard Worker 'files': externalFiles, 104*c8dee2aaSAndroid Build Coastguard Worker }; 105*c8dee2aaSAndroid Build Coastguard Worker console.log('Benchmarking "' + t.description + '"'); 106*c8dee2aaSAndroid Build Coastguard Worker t.setup(CanvasKit, ctx); 107*c8dee2aaSAndroid Build Coastguard Worker function draw() { 108*c8dee2aaSAndroid Build Coastguard Worker t.test(CanvasKit, ctx); 109*c8dee2aaSAndroid Build Coastguard Worker } 110*c8dee2aaSAndroid Build Coastguard Worker // TODO(nifong): is it ok to keep re-using the surface? 111*c8dee2aaSAndroid Build Coastguard Worker results = await startTimingFrames(draw, surface, WARM_UP_FRAMES, MAX_FRAMES); 112*c8dee2aaSAndroid Build Coastguard Worker t.teardown(CanvasKit, ctx); 113*c8dee2aaSAndroid Build Coastguard Worker window._perfData[t.perfKey] = results; 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker // Delete and re-create surface between tests, to prevent the possibility of 116*c8dee2aaSAndroid Build Coastguard Worker // interference between them through the state of surface, the gl context, or things 117*c8dee2aaSAndroid Build Coastguard Worker // that are keyed by the surface's gen id. 118*c8dee2aaSAndroid Build Coastguard Worker surface.delete(); 119*c8dee2aaSAndroid Build Coastguard Worker surface = getSurface(CanvasKit, glversion); 120*c8dee2aaSAndroid Build Coastguard Worker 121*c8dee2aaSAndroid Build Coastguard Worker // TODO(nifong): provide a function similar to startTimingFrames for timing 122*c8dee2aaSAndroid Build Coastguard Worker // non-visual tests. 123*c8dee2aaSAndroid Build Coastguard Worker } 124*c8dee2aaSAndroid Build Coastguard Worker surface.delete(); 125*c8dee2aaSAndroid Build Coastguard Worker window._perfDone = true; 126*c8dee2aaSAndroid Build Coastguard Worker }); 127*c8dee2aaSAndroid Build Coastguard Worker console.log('Perf is ready'); 128*c8dee2aaSAndroid Build Coastguard Worker window._perfReady = true; 129*c8dee2aaSAndroid Build Coastguard Worker }); 130*c8dee2aaSAndroid Build Coastguard Worker } 131*c8dee2aaSAndroid Build Coastguard Worker )(); 132*c8dee2aaSAndroid Build Coastguard Worker 133*c8dee2aaSAndroid Build Coastguard Worker </script> 134*c8dee2aaSAndroid Build Coastguard Worker</body> 135*c8dee2aaSAndroid Build Coastguard Worker</html> 136