Adding artifacts (#15145)
parent
df646a03eb
commit
45cecf385d
@ -0,0 +1,170 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="utf-8" /> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
||||
|
||||
<link |
||||
rel="stylesheet" |
||||
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" |
||||
/> |
||||
<link rel="stylesheet" type="text/css" href="../lib/d3-flamegraph.css" /> |
||||
|
||||
<style> |
||||
/* Space out content a bit */ |
||||
body { |
||||
padding-top: 20px; |
||||
padding-bottom: 20px; |
||||
} |
||||
|
||||
/* Custom page header */ |
||||
.header { |
||||
padding-bottom: 20px; |
||||
padding-right: 15px; |
||||
padding-left: 15px; |
||||
border-bottom: 1px solid #e5e5e5; |
||||
} |
||||
|
||||
/* Make the masthead heading the same height as the navigation */ |
||||
.header h3 { |
||||
margin-top: 0; |
||||
margin-bottom: 0; |
||||
line-height: 40px; |
||||
} |
||||
|
||||
/* Customize container */ |
||||
.container { |
||||
max-width: 990px; |
||||
} |
||||
</style> |
||||
|
||||
<title>Performance Measurements</title> |
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> |
||||
<!--[if lt IE 9]> |
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> |
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> |
||||
<![endif]--> |
||||
</head> |
||||
<body> |
||||
<div class="container"> |
||||
<div class="header clearfix"> |
||||
<nav> |
||||
<div class="pull-right"> |
||||
<form class="form-inline" id="form"> |
||||
<a class="btn" href="javascript: resetZoom();">Reset zoom</a> |
||||
<a class="btn" href="javascript: clear();">Clear</a> |
||||
<div class="form-group"> |
||||
<input type="text" class="form-control" id="term" /> |
||||
</div> |
||||
<a class="btn btn-primary" href="javascript: search();">Search</a> |
||||
</form> |
||||
</div> |
||||
</nav> |
||||
<h3 class="text-muted">d3-flame-graph</h3> |
||||
</div> |
||||
<div id="chart"></div> |
||||
<hr /> |
||||
<div id="details"></div> |
||||
</div> |
||||
|
||||
<!-- D3.js --> |
||||
<script src="https://d3js.org/d3.v7.js" charset="utf-8"></script> |
||||
|
||||
<!-- d3-flamegraph --> |
||||
<script type="text/javascript" src="../lib/d3-flamegraph.js"></script> |
||||
<script |
||||
type="text/javascript" |
||||
src="../lib/d3-flamegraph-tooltip.js" |
||||
></script> |
||||
|
||||
<script type="text/javascript"> |
||||
var chart = flamegraph() |
||||
.width(960) |
||||
.cellHeight(18) |
||||
.transitionDuration(750) |
||||
.minFrameSize(5) |
||||
.transitionEase(d3.easeCubic) |
||||
.sort(true) |
||||
//Example to sort in reverse order |
||||
//.sort(function(a,b){ return d3.descending(a.name, b.name);}) |
||||
.title('') |
||||
.onClick(onClick) |
||||
.selfValue(false) |
||||
.setColorMapper((d, originalColor) => |
||||
d.highlight ? '#6aff8f' : originalColor, |
||||
); |
||||
|
||||
// Example on how to use custom a tooltip. |
||||
var tip = flamegraph.tooltip |
||||
.defaultFlamegraphTooltip() |
||||
.text((d) => 'name: ' + d.data.name + ', value: ' + d.data.value); |
||||
chart.tooltip(tip); |
||||
|
||||
var details = document.getElementById('details'); |
||||
chart.setDetailsElement(details); |
||||
|
||||
// Example on how to use searchById() function in flamegraph. |
||||
// To invoke this function after loading the graph itself, this function should be registered in d3 datum(data).call() |
||||
// (See d3.json invocation in this file) |
||||
function invokeFind() { |
||||
var searchId = parseInt(location.hash.substring(1), 10); |
||||
if (searchId) { |
||||
find(searchId); |
||||
} |
||||
} |
||||
|
||||
// Example on how to use custom labels |
||||
// var label = function(d) { |
||||
// return "name: " + d.name + ", value: " + d.value; |
||||
// } |
||||
// chart.label(label); |
||||
|
||||
// Example of how to set fixed chart height |
||||
// chart.height(540); |
||||
|
||||
d3.json('stacks.json') |
||||
.then((data) => { |
||||
d3.select('#chart').datum(data).call(chart).call(invokeFind); |
||||
}) |
||||
.catch((error) => { |
||||
return console.warn(error); |
||||
}); |
||||
|
||||
document |
||||
.getElementById('form') |
||||
.addEventListener('submit', function (event) { |
||||
event.preventDefault(); |
||||
search(); |
||||
}); |
||||
|
||||
function search() { |
||||
var term = document.getElementById('term').value; |
||||
chart.search(term); |
||||
} |
||||
|
||||
function find(id) { |
||||
var elem = chart.findById(id); |
||||
if (elem) { |
||||
console.log(elem); |
||||
chart.zoomTo(elem); |
||||
} |
||||
} |
||||
|
||||
function clear() { |
||||
document.getElementById('term').value = ''; |
||||
chart.clear(); |
||||
} |
||||
|
||||
function resetZoom() { |
||||
chart.resetZoom(); |
||||
} |
||||
|
||||
function onClick(d) { |
||||
console.info(`Clicked on ${d.data.name}, id: "${d.id}"`); |
||||
history.pushState({ id: d.id }, d.data.name, `#${d.id}`); |
||||
} |
||||
</script> |
||||
</body> |
||||
</html> |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,46 @@ |
||||
.d3-flame-graph rect { |
||||
stroke: #EEEEEE; |
||||
fill-opacity: .8; |
||||
} |
||||
|
||||
.d3-flame-graph rect:hover { |
||||
stroke: #474747; |
||||
stroke-width: 0.5; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.d3-flame-graph-label { |
||||
pointer-events: none; |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
overflow: hidden; |
||||
font-size: 12px; |
||||
font-family: Verdana; |
||||
margin-left: 4px; |
||||
margin-right: 4px; |
||||
line-height: 1.5; |
||||
padding: 0 0 0; |
||||
font-weight: 400; |
||||
color: black; |
||||
text-align: left; |
||||
} |
||||
|
||||
.d3-flame-graph .fade { |
||||
opacity: 0.6 !important; |
||||
} |
||||
|
||||
.d3-flame-graph .title { |
||||
font-size: 20px; |
||||
font-family: Verdana; |
||||
} |
||||
|
||||
.d3-flame-graph-tip { |
||||
background-color: black; |
||||
border: none; |
||||
border-radius: 3px; |
||||
padding: 5px 10px 5px 10px; |
||||
min-width: 250px; |
||||
text-align: left; |
||||
color: white; |
||||
z-index: 10; |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,67 @@ |
||||
<html> |
||||
<head> |
||||
<script type="text/javascript" src="./jquery.min.js"></script> |
||||
<style> |
||||
table { |
||||
border: 1px solid black; |
||||
border-collapse: collapse; |
||||
} |
||||
tr { |
||||
border: 1px solid black; |
||||
} |
||||
</style> |
||||
<script> |
||||
$(function () { |
||||
var loadTime = []; |
||||
|
||||
$.getJSON('stats.json', function (data) { |
||||
$.each(data.children, function (index, datum) { |
||||
if (datum.name) { |
||||
var tblRow = |
||||
'<tr>' + |
||||
'<td>' + |
||||
index + |
||||
'</td>' + |
||||
'<td>' + |
||||
datum.name + |
||||
'</td>' + |
||||
'<td>' + |
||||
datum.value + |
||||
'</td>' + |
||||
'</tr>'; |
||||
$(tblRow).appendTo('#loaddata tbody'); |
||||
} |
||||
}); |
||||
$( |
||||
'<tr>' + |
||||
'<td>' + |
||||
'Total' + |
||||
'</td>' + |
||||
'<td>' + |
||||
'--' + |
||||
'</td>' + |
||||
'<td>' + |
||||
data.value + |
||||
'</td>' + |
||||
'</tr>', |
||||
).appendTo('#loaddata tbody'); |
||||
}); |
||||
}); |
||||
</script> |
||||
</head> |
||||
|
||||
<body> |
||||
<div class="wrapper"> |
||||
<div class="profile"> |
||||
<table id="loaddata"> |
||||
<thead> |
||||
<th>S.No</th> |
||||
<th>Name</th> |
||||
<th>TotalTime</th> |
||||
</thead> |
||||
<tbody></tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
</body> |
||||
</html> |
File diff suppressed because one or more lines are too long
@ -0,0 +1,111 @@ |
||||
#!/usr/bin/env node
|
||||
|
||||
/* eslint-disable node/shebang */ |
||||
const path = require('path'); |
||||
const { promises: fs } = require('fs'); |
||||
const yargs = require('yargs/yargs'); |
||||
const { hideBin } = require('yargs/helpers'); |
||||
|
||||
const { exitWithError } = require('../../development/lib/exit-with-error'); |
||||
const { |
||||
isWritable, |
||||
getFirstParentDirectoryThatExists, |
||||
} = require('../helpers/file'); |
||||
const { withFixtures, tinyDelayMs } = require('./helpers'); |
||||
|
||||
/** |
||||
* The e2e test case is used to capture load and initialisation time statistics for extension in MV3 environment. |
||||
*/ |
||||
|
||||
async function profilePageLoad() { |
||||
const parsedLogs = {}; |
||||
try { |
||||
await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => { |
||||
await driver.delay(tinyDelayMs); |
||||
await driver.navigate(); |
||||
await driver.delay(1000); |
||||
const logs = await driver.checkBrowserForLavamoatLogs(); |
||||
|
||||
let logString = ''; |
||||
let logType = ''; |
||||
|
||||
logs.forEach((log) => { |
||||
if (log.indexOf('"version": 1') >= 0) { |
||||
// log end here
|
||||
logString += log; |
||||
parsedLogs[logType] = JSON.parse(`{${logString}}`); |
||||
logString = ''; |
||||
logType = ''; |
||||
} else if (logType) { |
||||
// log string continues
|
||||
logString += log; |
||||
} else if ( |
||||
log.search(/"name": ".*app\/scripts\/background.js",/u) >= 0 |
||||
) { |
||||
// background log starts
|
||||
logString += log; |
||||
logType = 'background'; |
||||
} else if (log.search(/"name": ".*app\/scripts\/ui.js",/u) >= 0) { |
||||
// ui log starts
|
||||
logString += log; |
||||
logType = 'ui'; |
||||
} else if (log.search(/"name": "Total"/u) >= 0) { |
||||
// load time log starts
|
||||
logString += log; |
||||
logType = 'loadTime'; |
||||
} |
||||
}); |
||||
}); |
||||
} catch (error) { |
||||
console.log('Error in trying to parse logs.'); |
||||
} |
||||
return parsedLogs; |
||||
} |
||||
|
||||
async function main() { |
||||
const { argv } = yargs(hideBin(process.argv)).usage( |
||||
'$0 [options]', |
||||
'Run a page load benchmark', |
||||
(_yargs) => |
||||
_yargs.option('out', { |
||||
description: |
||||
'Output filename. Output printed to STDOUT of this is omitted.', |
||||
type: 'string', |
||||
normalize: true, |
||||
}), |
||||
); |
||||
|
||||
const results = await profilePageLoad(); |
||||
const { out } = argv; |
||||
|
||||
const logCategories = [ |
||||
{ key: 'background', dirPath: 'initialisation/background/stacks.json' }, |
||||
{ key: 'ui', dirPath: 'initialisation/ui/stacks.json' }, |
||||
{ key: 'loadTime', dirPath: 'load_time/stats.json' }, |
||||
]; |
||||
|
||||
if (out) { |
||||
logCategories.forEach(async ({ key, dirPath }) => { |
||||
if (results[key]) { |
||||
const outPath = `${out}/${dirPath}`; |
||||
const outputDirectory = path.dirname(outPath); |
||||
const existingParentDirectory = await getFirstParentDirectoryThatExists( |
||||
outputDirectory, |
||||
); |
||||
if (!(await isWritable(existingParentDirectory))) { |
||||
throw new Error('Specified output file directory is not writable'); |
||||
} |
||||
if (outputDirectory !== existingParentDirectory) { |
||||
await fs.mkdir(outputDirectory, { recursive: true }); |
||||
} |
||||
await fs.writeFile(outPath, JSON.stringify(results[key], null, 2)); |
||||
} |
||||
}); |
||||
} else { |
||||
console.log(JSON.stringify(results, null, 2)); |
||||
} |
||||
} |
||||
|
||||
main().catch((error) => { |
||||
exitWithError(error); |
||||
}); |
@ -0,0 +1,37 @@ |
||||
/* eslint-disable node/shebang */ |
||||
const path = require('path'); |
||||
const { promises: fs, constants: fsConstants } = require('fs'); |
||||
|
||||
async function isWritable(directory) { |
||||
try { |
||||
await fs.access(directory, fsConstants.W_OK); |
||||
return true; |
||||
} catch (error) { |
||||
if (error.code !== 'EACCES') { |
||||
throw error; |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
async function getFirstParentDirectoryThatExists(directory) { |
||||
let nextDirectory = directory; |
||||
for (;;) { |
||||
try { |
||||
await fs.access(nextDirectory, fsConstants.F_OK); |
||||
return nextDirectory; |
||||
} catch (error) { |
||||
if (error.code !== 'ENOENT') { |
||||
throw error; |
||||
} else if (nextDirectory === path.dirname(nextDirectory)) { |
||||
throw new Error('Failed to find parent directory that exists'); |
||||
} |
||||
nextDirectory = path.dirname(nextDirectory); |
||||
} |
||||
} |
||||
} |
||||
|
||||
module.exports = { |
||||
isWritable, |
||||
getFirstParentDirectoryThatExists, |
||||
}; |
Loading…
Reference in new issue