Skip to content

Instantly share code, notes, and snippets.

@IntelOrca
Last active December 12, 2021 03:34
Show Gist options
  • Save IntelOrca/82e98e825a7fde3ed92a6316332b9e89 to your computer and use it in GitHub Desktop.
Save IntelOrca/82e98e825a7fde3ed92a6316332b9e89 to your computer and use it in GitHub Desktop.
/// <reference path="C:\Users\Ted\Documents\GitHub\openrct2\distribution\openrct2.d.ts" />
var perf =
['tick',
[
['update', [
'rides',
'entities',
'network',
'scripting'
]],
['draw', [
'paint',
'blit'
]],
['input']
]
];
function createNode(perfNode, depth) {
var isString = typeof perfNode === 'string';
var node = {};
node.label = isString ? perfNode : perfNode[0];
node.depth = depth;
node.inclusive = 0;
node.exclusive = 0;
node.expanded = true;
node.children = [];
if (!isString && perfNode.length > 1) {
var prefChildren = perfNode[1];
for (var i = 0; i < prefChildren.length; i++) {
var childNode = createNode(prefChildren[i], depth + 1);
node.children.push(childNode);
}
}
return node;
}
var tree = createNode(perf, 0);
randomiseNumbers(tree, 1);
var visibleNodes = [];
function randomiseNumbers(node, total) {
var numChildren = node.children.length;
node.inclusive = total;
if (numChildren !== 0) {
node.exclusive = Math.random();
var randomAmounts = [];
var totalTemp = node.exclusive;
for (var i = 0; i < numChildren; i++) {
var r = Math.random();
randomAmounts.push(r);
totalTemp += r;
}
node.exclusive = (node.exclusive / totalTemp) * total;
for (var i = 0; i < numChildren; i++) {
randomAmounts[i] = (randomAmounts[i] / totalTemp) * total;
randomiseNumbers(node.children[i], randomAmounts[i]);
}
} else {
node.exclusive = total;
}
}
function appendItems(items, node) {
items.push(node);
if (node.expanded) {
for (var i = 0; i < node.children.length; i++) {
appendItems(items, node.children[i]);
}
}
}
function percent(n) {
var s = (n * 100).toFixed(2) + '%';
if (n > 0.3) {
s = "{RED}" + s;
} else if (n > 0.1) {
s = "{YELLOW}" + s;
} else {
s = "{GREEN}" + s;
}
return s;
}
function getFriendlyFunctionName(name) {
var pattern = /.+cdecl (?:OpenRCT2::)?(.+)\(.*/i;
var result = name.match(pattern);
return result[1];
}
function createTreeFromData(data) {
// Create node for each function
var nodes = data.map(function (f) {
return {
label: getFriendlyFunctionName(f.name),
expanded: true,
avg: f.totalTime / f.callCount,
inclusive: 0,
f: f
};
});
// Set parents and children for each node
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
node.parents = node.f.parents.map(function (idx) {
return nodes[idx];
});
node.children = node.f.children.map(function (idx) {
return nodes[idx];
});
}
var root = {
label: 'root',
expanded: true,
avg: 0,
inclusive: 1,
children: nodes.filter(function (n) {
return n.parents.length === 0;
})
};
function setDepth(node, depth) {
node.depth = depth;
for (var i = 0; i < node.children.length; i++) {
setDepth(node.children[i], depth + 1);
}
}
setDepth(root, 0);
function removeZeroCalls(node) {
node.children = node.children.filter(function (node) {
return node.f.callCount !== 0;
});
for (var i = 0; i < node.children.length; i++) {
removeZeroCalls(node.children[i]);
}
}
removeZeroCalls(root);
for (var i = 0; i < root.children.length; i++) {
var child = root.children[i];
if (isFinite(child.avg)) {
root.avg += child.avg;
}
}
function calcInclusive(node) {
node.inclusive = node.avg / root.avg;
for (var i = 0; i < node.children.length; i++) {
calcInclusive(node.children[i]);
}
node.children.sort(function (a, b) {
return b.avg - a.avg;
});
}
calcInclusive(root);
return root;
}
function createItems() {
var data = profiler.getData();
var tree = createTreeFromData(data);
visibleNodes = [];
appendItems(visibleNodes, tree);
return visibleNodes.map(function (n) {
return [
"{GREY}" + ' '.repeat(n.depth * 4) + n.label,
percent(n.inclusive),
n.avg.toPrecision(3)
];
});
}
function toggleVisibleNode(index) {
var visibleNode = visibleNodes[index];
visibleNode.expanded = !visibleNode.expanded;
}
function open() {
profiler.reset();
profiler.start();
var width = 500;
var height = 400;
var w = ui.openWindow({
x: (ui.width - width) / 2,
y: (ui.height - height) / 2,
width: width,
height: height,
title: 'Performance Monitor',
classification: 'perfmon',
colours: [0, 0],
widgets: [
{
type: "listview",
name: "list",
scrollbars: "vertical",
showColumnHeaders: true,
columns: [
{
width: 250,
header: ''
},
{
width: 80,
header: '{GREY}Inclusive'
},
{
width: 80,
header: '{GREY}Exclusive'
}
],
x: 5,
y: 20,
width: width - 10,
height: height - 24,
onClick: function (i, c) {
toggleVisibleNode(i);
var listWidget = w.findWidget('list');
listWidget.items = createItems();
}
}
]
});
var listWidget = w.findWidget('list');
listWidget.items = createItems();
context.setInterval(function() {
randomiseNumbers(tree, 1);
var listWidget = w.findWidget('list');
listWidget.items = createItems();
}, 1000);
}
function main() {
ui.registerMenuItem('Performance Monitor', function() {
ui.closeAllWindows();
open();
});
ui.closeAllWindows();
open();
}
registerPlugin({
name: 'Test',
version: '1.0',
authors: ['Ted'],
type: 'local',
licence: 'MIT',
main: main
});
@IntelOrca
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment