perftest_http3_facebook_scroll.js (4634B)
1 // This Source Code Form is subject to the terms of the Mozilla Public 2 // License, v. 2.0. If a copy of the MPL was not distributed with this 3 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 /* eslint-env node */ 5 6 /* 7 Ensure the `--firefox.preference=network.http.http3.enable:true` is 8 set for this test. 9 */ 10 11 async function captureNetworkRequest(commands) { 12 var capture_network_request = []; 13 var capture_resource = await commands.js.run(` 14 return performance.getEntriesByType("resource"); 15 `); 16 for (var i = 0; i < capture_resource.length; i++) { 17 capture_network_request.push(capture_resource[i].name); 18 } 19 return capture_network_request; 20 } 21 22 async function waitForScrollRequestsEnd( 23 prevCount, 24 maxStableCount, 25 timeout, 26 commands, 27 context 28 ) { 29 let starttime = await commands.js.run(`return performance.now();`); 30 let endtime = await commands.js.run(`return performance.now();`); 31 let changing = true; 32 let newCount = -1; 33 let stableCount = 0; 34 35 while ( 36 ((await commands.js.run(`return performance.now();`)) - starttime < 37 timeout) & 38 changing 39 ) { 40 // Wait a bit before making another round 41 await commands.wait.byTime(100); 42 newCount = (await captureNetworkRequest(commands)).length; 43 context.log.debug(`${newCount}, ${prevCount}, ${stableCount}`); 44 45 // Check if we are approaching stability 46 if (newCount == prevCount) { 47 // Gather the end time now 48 if (stableCount == 0) { 49 endtime = await commands.js.run(`return performance.now();`); 50 } 51 stableCount++; 52 } else { 53 prevCount = newCount; 54 stableCount = 0; 55 } 56 57 if (stableCount >= maxStableCount) { 58 // Stability achieved 59 changing = false; 60 } 61 } 62 63 return { 64 start: starttime, 65 end: endtime, 66 numResources: newCount, 67 }; 68 } 69 70 async function test(context, commands) { 71 let rootUrl = "https://www.facebook.com/lambofgod/"; 72 let waitTime = 1000; 73 let numScrolls = 5; 74 75 const average = arr => arr.reduce((p, c) => p + c, 0) / arr.length; 76 77 if (typeof context.options.browsertime !== "undefined") { 78 if (typeof context.options.browsertime.waitTime !== "undefined") { 79 waitTime = context.options.browsertime.waitTime; 80 } 81 if (typeof context.options.browsertime.numScrolls !== "undefined") { 82 numScrolls = context.options.browsertime.numScrolls; 83 } 84 } 85 86 // Make firefox learn of HTTP/3 server 87 await commands.navigate(rootUrl); 88 89 let cycles = 1; 90 for (let cycle = 0; cycle < cycles; cycle++) { 91 // Measure the pageload 92 await commands.measure.start("pageload"); 93 await commands.navigate(rootUrl); 94 await commands.measure.stop(); 95 96 // Initial scroll to make the new user popup show 97 await commands.js.runAndWait( 98 `window.scrollTo({ top: 1000, behavior: 'smooth' })` 99 ); 100 await commands.wait.byTime(1000); 101 await commands.click.byLinkTextAndWait("Not Now"); 102 103 let vals = []; 104 let badIterations = 0; 105 for (let iteration = 0; iteration < numScrolls; iteration++) { 106 // Clear old resources 107 await commands.js.run(`performance.clearResourceTimings();`); 108 109 // Get current resource count 110 let currCount = (await captureNetworkRequest(commands)).length; 111 112 // Scroll to a ridiculously high value for "infinite" down-scrolling 113 commands.js.runAndWait(` 114 window.scrollTo({ top: 100000000 }) 115 `); 116 117 /* 118 The maxStableCount of 22 was chosen as a trade-off between fast iterations 119 and minimizing the number of bad iterations. 120 */ 121 let newInfo = await waitForScrollRequestsEnd( 122 currCount, 123 22, 124 120000, 125 commands, 126 context 127 ); 128 129 // Gather metrics 130 let ndiff = newInfo.numResources - currCount; 131 let tdiff = (newInfo.end - newInfo.start) / 1000; 132 133 // Check if we had a bad iteration 134 if (ndiff == 0) { 135 context.log.info("Bad iteration, redoing..."); 136 iteration--; 137 badIterations++; 138 if (badIterations == 5) { 139 throw new Error("Too many bad scroll iterations occurred"); 140 } 141 continue; 142 } 143 144 vals.push(ndiff / tdiff); 145 146 // Wait X seconds before scrolling again 147 await commands.wait.byTime(waitTime); 148 } 149 150 if (!vals.length) { 151 throw new Error("No requestsPerSecond values were obtained"); 152 } 153 154 commands.measure.result[0].browserScripts.pageinfo.requestsPerSecond = 155 average(vals); 156 } 157 } 158 159 module.exports = { 160 test, 161 owner: "Network Team", 162 component: "netwerk", 163 name: "facebook-scroll", 164 description: "Measures the number of requests per second after a scroll.", 165 };