mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
162 lines
4.5 KiB
JavaScript
162 lines
4.5 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
"use strict";
|
|
|
|
self.onmessage = e => {
|
|
const { id, task, args } = e.data;
|
|
|
|
switch (task) {
|
|
case "plotTimestampsGraph":
|
|
plotTimestampsGraph(id, args);
|
|
break;
|
|
default:
|
|
self.postMessage({ id, error: e.message + "\n" + e.stack });
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @see LineGraphWidget.prototype.setDataFromTimestamps in Graphs.jsm
|
|
* @param number id
|
|
* @param number width
|
|
* @param number height
|
|
* @param array timestamps
|
|
* @param number interval
|
|
*/
|
|
function plotTimestampsGraph(id, args) {
|
|
let plottedData = plotTimestamps(args.timestamps, args.interval);
|
|
let plottedMinMaxSum = getMinMaxSum(plottedData);
|
|
let sparsifiedData = sparsifyLineData(plottedData, plottedMinMaxSum, args);
|
|
|
|
let response = { id, plottedData: sparsifiedData, plottedMinMaxSum };
|
|
self.postMessage(response);
|
|
}
|
|
|
|
/**
|
|
* Gets the min, max and average of the values in an array.
|
|
* @param array source
|
|
* @return object
|
|
*/
|
|
function getMinMaxSum(source) {
|
|
let totalTicks = source.length;
|
|
let maxValue = Number.MIN_SAFE_INTEGER;
|
|
let minValue = Number.MAX_SAFE_INTEGER;
|
|
let avgValue = 0;
|
|
let sumValues = 0;
|
|
|
|
for (let { value } of source) {
|
|
maxValue = Math.max(value, maxValue);
|
|
minValue = Math.min(value, minValue);
|
|
sumValues += value;
|
|
}
|
|
avgValue = sumValues / totalTicks;
|
|
|
|
return { minValue, maxValue, avgValue };
|
|
}
|
|
|
|
/**
|
|
* Reduce a data source for a line graph, based off of a minimum distance
|
|
* between the points to render.
|
|
*/
|
|
function sparsifyLineData(plottedData, plottedMinMaxSum, options) {
|
|
let { width: graphWidth, height: graphHeight } = options;
|
|
let { dataOffsetX, dampenValuesFactor } = options;
|
|
let { minSquaredDistanceBetweenPoints } = options;
|
|
|
|
let result = [];
|
|
|
|
let totalTicks = plottedData.length;
|
|
let maxValue = plottedMinMaxSum.maxValue;
|
|
|
|
let firstTick = totalTicks ? plottedData[0].delta : 0;
|
|
let lastTick = totalTicks ? plottedData[totalTicks - 1].delta : 0;
|
|
let dataScaleX = graphWidth / (lastTick - dataOffsetX);
|
|
let dataScaleY = graphHeight / maxValue * dampenValuesFactor;
|
|
|
|
let prevX = 0;
|
|
let prevY = 0;
|
|
|
|
for (let { delta, value } of plottedData) {
|
|
let currX = (delta - dataOffsetX) * dataScaleX;
|
|
let currY = graphHeight - value * dataScaleY;
|
|
|
|
if (delta == firstTick || delta == lastTick) {
|
|
result.push({ delta, value });
|
|
continue;
|
|
}
|
|
|
|
let dist = distSquared(prevX, prevY, currX, currY);
|
|
if (dist >= minSquaredDistanceBetweenPoints) {
|
|
result.push({ delta, value });
|
|
prevX = currX;
|
|
prevY = currY;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Takes a list of numbers and plots them on a line graph representing
|
|
* the rate of occurences in a specified interval.
|
|
*
|
|
* XXX: Copied almost verbatim from toolkit/devtools/server/actors/framerate.js
|
|
* Remove that dead code after the Performance panel lands, bug 1075567.
|
|
*
|
|
* @param array timestamps
|
|
* A list of numbers representing time, ordered ascending. For example,
|
|
* this can be the raw data received from the framerate actor, which
|
|
* represents the elapsed time on each refresh driver tick.
|
|
* @param number interval
|
|
* The maximum amount of time to wait between calculations.
|
|
* @param number clamp
|
|
* The maximum allowed value.
|
|
* @return array
|
|
* A collection of { delta, value } objects representing the
|
|
* plotted value at every delta time.
|
|
*/
|
|
function plotTimestamps(timestamps, interval = 100, clamp = 60) {
|
|
let timeline = [];
|
|
let totalTicks = timestamps.length;
|
|
|
|
// If the refresh driver didn't get a chance to tick before the
|
|
// recording was stopped, assume rate was 0.
|
|
if (totalTicks == 0) {
|
|
timeline.push({ delta: 0, value: 0 });
|
|
timeline.push({ delta: interval, value: 0 });
|
|
return timeline;
|
|
}
|
|
|
|
let frameCount = 0;
|
|
let prevTime = +timestamps[0];
|
|
|
|
for (let i = 1; i < totalTicks; i++) {
|
|
let currTime = +timestamps[i];
|
|
frameCount++;
|
|
|
|
let elapsedTime = currTime - prevTime;
|
|
if (elapsedTime < interval) {
|
|
continue;
|
|
}
|
|
|
|
let rate = Math.min(1000 / (elapsedTime / frameCount), clamp);
|
|
timeline.push({ delta: prevTime, value: rate });
|
|
timeline.push({ delta: currTime, value: rate });
|
|
|
|
frameCount = 0;
|
|
prevTime = currTime;
|
|
}
|
|
|
|
return timeline;
|
|
}
|
|
|
|
/**
|
|
* Calculates the squared distance between two 2D points.
|
|
*/
|
|
function distSquared(x0, y0, x1, y1) {
|
|
let xs = x1 - x0;
|
|
let ys = y1 - y0;
|
|
return xs * xs + ys * ys;
|
|
}
|