profview: Improve behavior when given a log with few ticks.

Previously, when given a log with few ticks, the timeline would lump
them all into one or two buckets. This patch allows ticks to be assigned
to buckets more sparsely.

This patch also fixes a bug where there was a gap on the right side of
the timeline, which also caused the function tick marks to be slightly
misaligned. This was more noticable with fewer buckets.

Bug: v8:6240
Change-Id: Ib7353c0420caec8591590815271d329ea1a030fb
Reviewed-on: https://chromium-review.googlesource.com/1174440
Commit-Queue: Bret Sepulveda <bsep@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55125}
This commit is contained in:
Bret Sepulveda 2018-08-14 14:51:12 +02:00 committed by Commit Bot
parent 87eedbc132
commit 6fcf0a0e3d

View File

@ -809,7 +809,6 @@ class TimelineView {
return;
}
this.currentState = newState;
if (oldState) {
if (newState.timeLine.width === oldState.timeLine.width &&
newState.timeLine.height === oldState.timeLine.height &&
@ -821,21 +820,27 @@ class TimelineView {
return;
}
}
this.currentState = newState;
this.element.style.display = "inherit";
// Make sure the canvas has the right dimensions.
let file = this.currentState.file;
let width = this.currentState.timeLine.width;
let height = this.currentState.timeLine.height;
const minPixelsPerBucket = 10;
const minTicksPerBucket = 8;
let maxBuckets = Math.round(file.ticks.length / minTicksPerBucket);
let bucketCount = Math.min(
Math.round(width / minPixelsPerBucket), maxBuckets);
// Make sure the canvas has the right dimensions.
this.canvas.width = width;
this.canvas.height = height;
// Make space for the selection text.
height -= this.imageOffset;
let file = this.currentState.file;
if (!file) return;
let currentCodeId = this.currentState.currentCodeId;
let firstTime = file.ticks[0].tm;
@ -846,13 +851,6 @@ class TimelineView {
this.selectionStart = (start - firstTime) / (lastTime - firstTime) * width;
this.selectionEnd = (end - firstTime) / (lastTime - firstTime) * width;
let tickCount = file.ticks.length;
let minBucketPixels = 10;
let minBucketSamples = 30;
let bucketCount = Math.min(width / minBucketPixels,
tickCount / minBucketSamples);
let stackProcessor = new CategorySampler(file, bucketCount);
generateTree(file, 0, Infinity, stackProcessor);
let codeIdProcessor = new FunctionTimelineProcessor(
@ -873,28 +871,36 @@ class TimelineView {
let sum = 0;
let bucketData = [];
let total = buckets[i].total;
for (let j = 0; j < bucketDescriptors.length; j++) {
let desc = bucketDescriptors[j];
for (let k = 0; k < desc.kinds.length; k++) {
sum += buckets[i][desc.kinds[k]];
if (total > 0) {
for (let j = 0; j < bucketDescriptors.length; j++) {
let desc = bucketDescriptors[j];
for (let k = 0; k < desc.kinds.length; k++) {
sum += buckets[i][desc.kinds[k]];
}
bucketData.push(Math.round(graphHeight * sum / total));
}
} else {
// No ticks fell into this bucket. Fill with "Unknown."
for (let j = 0; j < bucketDescriptors.length; j++) {
let desc = bucketDescriptors[j];
bucketData.push(desc.text === "Unknown" ? graphHeight : 0);
}
bucketData.push(Math.round(graphHeight * sum / total));
}
bucketsGraph.push(bucketData);
}
// Draw the category graph into the buffer.
let bucketWidth = width / bucketsGraph.length;
let bucketWidth = width / (bucketsGraph.length - 1);
let ctx = buffer.getContext('2d');
for (let i = 0; i < bucketsGraph.length - 1; i++) {
let bucketData = bucketsGraph[i];
let nextBucketData = bucketsGraph[i + 1];
let x1 = Math.round(i * bucketWidth);
let x2 = Math.round((i + 1) * bucketWidth);
for (let j = 0; j < bucketData.length; j++) {
let x1 = Math.round(i * bucketWidth);
let x2 = Math.round((i + 1) * bucketWidth);
ctx.beginPath();
ctx.moveTo(x1, j && bucketData[j - 1]);
ctx.lineTo(x2, j && nextBucketData[j - 1]);
ctx.moveTo(x1, j > 0 ? bucketData[j - 1] : 0);
ctx.lineTo(x2, j > 0 ? nextBucketData[j - 1] : 0);
ctx.lineTo(x2, nextBucketData[j]);
ctx.lineTo(x1, bucketData[j]);
ctx.closePath();