Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: tools/profview/profview.js

Issue 2737083003: [tools/profview] Add individual function timeline view (Closed)
Patch Set: Rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« tools/profview/profile-utils.js ('K') | « tools/profview/profview.css ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 the V8 project authors. All rights reserved. 1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 "use strict" 5 "use strict"
6 6
7 function $(id) { 7 function $(id) {
8 return document.getElementById(id); 8 return document.getElementById(id);
9 } 9 }
10 10
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 }, 144 },
145 145
146 setFile(file) { 146 setFile(file) {
147 if (file != main.currentState.file) { 147 if (file != main.currentState.file) {
148 main.currentState = Object.assign({}, main.currentState); 148 main.currentState = Object.assign({}, main.currentState);
149 main.currentState.file = file; 149 main.currentState.file = file;
150 main.delayRender(); 150 main.delayRender();
151 } 151 }
152 }, 152 },
153 153
154 setCurrentCode(codeId) {
155 if (codeId != main.currentState.currentCodeId) {
156 main.currentState = Object.assign({}, main.currentState);
157 main.currentState.currentCodeId = codeId;
158 main.delayRender();
159 }
160 },
161
154 onResize() { 162 onResize() {
155 main.setTimeLineDimensions( 163 main.setTimeLineDimensions(
156 window.innerWidth - 20, window.innerHeight / 5); 164 window.innerWidth - 20, window.innerHeight / 5);
157 }, 165 },
158 166
159 onLoad() { 167 onLoad() {
160 function loadHandler(evt) { 168 function loadHandler(evt) {
161 let f = evt.target.files[0]; 169 let f = evt.target.files[0];
162 if (f) { 170 if (f) {
163 let reader = new FileReader(); 171 let reader = new FileReader();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 let bucket = bucketDescriptors[i]; 242 let bucket = bucketDescriptors[i];
235 for (let j = 0; j < bucket.kinds.length; j++) { 243 for (let j = 0; j < bucket.kinds.length; j++) {
236 if (bucket.kinds[j] === kind) { 244 if (bucket.kinds[j] === kind) {
237 return bucket; 245 return bucket;
238 } 246 }
239 } 247 }
240 } 248 }
241 return null; 249 return null;
242 } 250 }
243 251
252 function codeTypeToText(type) {
253 switch (type) {
254 case "UNKNOWN":
255 return "Unknown";
256 case "CPPCOMP":
257 return "C++ (compiler)";
258 case "CPPGC":
259 return "C++";
260 case "CPPEXT":
261 return "C++ External";
262 case "CPP":
263 return "C++";
264 case "LIB":
265 return "Library";
266 case "IC":
267 return "IC";
268 case "BC":
269 return "Bytecode";
270 case "STUB":
271 return "Stub";
272 case "BUILTIN":
273 return "Builtin";
274 case "REGEXP":
275 return "RegExp";
276 case "JSOPT":
277 return "JS opt";
278 case "JSUNOPT":
279 return "JS unopt";
280 }
281 console.error("Unknown type: " + type);
282 }
283
284 function createTypeDiv(type) {
285 if (type === "CAT") {
286 return document.createTextNode("");
287 }
288 let div = document.createElement("div");
289 div.classList.add("code-type-chip");
290
291 let span = document.createElement("span");
292 span.classList.add("code-type-chip");
293 span.textContent = codeTypeToText(type);
294 div.appendChild(span);
295
296 span = document.createElement("span");
297 span.classList.add("code-type-chip-space");
298 div.appendChild(span);
299
300 return div;
301 }
302
303 function isBytecodeHandler(kind) {
304 return kind === "BytecodeHandler";
305 }
306
307 function filterFromFilterId(id) {
308 switch (id) {
309 case "full-tree":
310 return (type, kind) => true;
311 case "js-funs":
312 return (type, kind) => type !== 'CODE';
313 case "js-exclude-bc":
314 return (type, kind) =>
315 type !== 'CODE' || !isBytecodeHandler(kind);
316 }
317 }
318
244 class CallTreeView { 319 class CallTreeView {
245 constructor() { 320 constructor() {
246 this.element = $("calltree"); 321 this.element = $("calltree");
247 this.treeElement = $("calltree-table"); 322 this.treeElement = $("calltree-table");
248 this.selectAttribution = $("calltree-attribution"); 323 this.selectAttribution = $("calltree-attribution");
249 this.selectCategories = $("calltree-categories"); 324 this.selectCategories = $("calltree-categories");
250 this.selectSort = $("calltree-sort"); 325 this.selectSort = $("calltree-sort");
251 326
252 this.selectAttribution.onchange = () => { 327 this.selectAttribution.onchange = () => {
253 main.setCallTreeAttribution(this.selectAttribution.value); 328 main.setCallTreeAttribution(this.selectAttribution.value);
254 }; 329 };
255 330
256 this.selectCategories.onchange = () => { 331 this.selectCategories.onchange = () => {
257 main.setCallTreeCategories(this.selectCategories.value); 332 main.setCallTreeCategories(this.selectCategories.value);
258 }; 333 };
259 334
260 this.selectSort.onchange = () => { 335 this.selectSort.onchange = () => {
261 main.setCallTreeSort(this.selectSort.value); 336 main.setCallTreeSort(this.selectSort.value);
262 }; 337 };
263 338
264 this.currentState = null; 339 this.currentState = null;
265 } 340 }
266 341
267 filterFromFilterId(id) {
268 switch (id) {
269 case "full-tree":
270 return (type, kind) => true;
271 case "js-funs":
272 return (type, kind) => type !== 'CODE';
273 case "js-exclude-bc":
274 return (type, kind) =>
275 type !== 'CODE' || !CallTreeView.IsBytecodeHandler(kind);
276 }
277 }
278
279 sortFromId(id) { 342 sortFromId(id) {
280 switch (id) { 343 switch (id) {
281 case "time": 344 case "time":
282 return (c1, c2) => { 345 return (c1, c2) => {
283 if (c1.ticks < c2.ticks) return 1; 346 if (c1.ticks < c2.ticks) return 1;
284 else if (c1.ticks > c2.ticks) return -1; 347 else if (c1.ticks > c2.ticks) return -1;
285 return c2.ownTicks - c1.ownTicks; 348 return c2.ownTicks - c1.ownTicks;
286 } 349 }
287 case "own-time": 350 case "own-time":
288 return (c1, c2) => { 351 return (c1, c2) => {
289 if (c1.ownTicks < c2.ownTicks) return 1; 352 if (c1.ownTicks < c2.ownTicks) return 1;
290 else if (c1.ownTicks > c2.ownTicks) return -1; 353 else if (c1.ownTicks > c2.ownTicks) return -1;
291 return c2.ticks - c1.ticks; 354 return c2.ticks - c1.ticks;
292 } 355 }
293 case "category-time": 356 case "category-time":
294 return (c1, c2) => { 357 return (c1, c2) => {
295 if (c1.type === c2.type) return c2.ticks - c1.ticks; 358 if (c1.type === c2.type) return c2.ticks - c1.ticks;
296 if (c1.type < c2.type) return 1; 359 if (c1.type < c2.type) return 1;
297 return -1; 360 return -1;
298 }; 361 };
299 case "category-own-time": 362 case "category-own-time":
300 return (c1, c2) => { 363 return (c1, c2) => {
301 if (c1.type === c2.type) return c2.ownTicks - c1.ownTicks; 364 if (c1.type === c2.type) return c2.ownTicks - c1.ownTicks;
302 if (c1.type < c2.type) return 1; 365 if (c1.type < c2.type) return 1;
303 return -1; 366 return -1;
304 }; 367 };
305 } 368 }
306 } 369 }
307 370
308 static IsBytecodeHandler(kind) {
309 return kind === "BytecodeHandler";
310 }
311
312 createExpander(indent) { 371 createExpander(indent) {
313 let div = document.createElement("div"); 372 let div = document.createElement("div");
314 div.style.width = (1 + indent) + "em"; 373 div.style.width = (1 + indent) + "em";
315 div.style.display = "inline-block"; 374 div.style.display = "inline-block";
316 div.style.textAlign = "right"; 375 div.style.textAlign = "right";
317 return div; 376 return div;
318 } 377 }
319 378
320 codeTypeToText(type) { 379 createFunctionNode(name, codeId) {
321 switch (type) { 380 if (codeId == -1) {
322 case "UNKNOWN": 381 return document.createTextNode(name);
323 return "Unknown";
324 case "CPPCOMP":
325 return "C++ (compiler)";
326 case "CPPGC":
327 return "C++";
328 case "CPPEXT":
329 return "C++ External";
330 case "CPP":
331 return "C++";
332 case "LIB":
333 return "Library";
334 case "IC":
335 return "IC";
336 case "BC":
337 return "Bytecode";
338 case "STUB":
339 return "Stub";
340 case "BUILTIN":
341 return "Builtin";
342 case "REGEXP":
343 return "RegExp";
344 case "JSOPT":
345 return "JS opt";
346 case "JSUNOPT":
347 return "JS unopt";
348 } 382 }
349 console.error("Unknown type: " + type); 383 let nameElement = document.createElement("span");
350 } 384 nameElement.classList.add("codeid-link")
351 385 nameElement.onclick = function() {
352 createTypeDiv(type) { 386 main.setCurrentCode(codeId);
353 if (type === "CAT") { 387 };
354 return document.createTextNode(""); 388 nameElement.appendChild(document.createTextNode(name));
355 } 389 return nameElement;
356 let div = document.createElement("div");
357 div.classList.add("code-type-chip");
358
359 let span = document.createElement("span");
360 span.classList.add("code-type-chip");
361 span.textContent = this.codeTypeToText(type);
362 div.appendChild(span);
363
364 span = document.createElement("span");
365 span.classList.add("code-type-chip-space");
366 div.appendChild(span);
367
368 return div;
369 } 390 }
370 391
371 expandTree(tree, indent) { 392 expandTree(tree, indent) {
372 let that = this; 393 let that = this;
373 let index = 0; 394 let index = 0;
374 let id = "R/"; 395 let id = "R/";
375 let row = tree.row; 396 let row = tree.row;
376 let expander = tree.expander; 397 let expander = tree.expander;
377 398
378 if (row) { 399 if (row) {
379 console.assert("expander"); 400 console.assert("expander");
380 index = row.rowIndex; 401 index = row.rowIndex;
381 id = row.id; 402 id = row.id;
382 403
383 // Make sure we collapse the children when the row is clicked 404 // Make sure we collapse the children when the row is clicked
384 // again. 405 // again.
385 expander.textContent = "\u25BE"; 406 expander.textContent = "\u25BE";
386 let expandHandler = expander.onclick; 407 let expandHandler = expander.onclick;
387 expander.onclick = () => { 408 expander.onclick = () => {
388 that.collapseRow(tree, expander, expandHandler); 409 that.collapseRow(tree, expander, expandHandler);
389 } 410 }
390 } 411 }
391 412
392 // Collect the children, and sort them by ticks. 413 // Collect the children, and sort them by ticks.
393 let children = []; 414 let children = [];
394 let filter = 415 let filter =
395 this.filterFromFilterId(this.currentState.callTree.attribution); 416 filterFromFilterId(this.currentState.callTree.attribution);
396 for (let childId in tree.children) { 417 for (let childId in tree.children) {
397 let child = tree.children[childId]; 418 let child = tree.children[childId];
398 if (child.ticks > 0) { 419 if (child.ticks > 0) {
399 children.push(child); 420 children.push(child);
400 if (child.delayedExpansion) { 421 if (child.delayedExpansion) {
401 expandTreeNode(this.currentState.file, child, filter); 422 expandTreeNode(this.currentState.file, child, filter);
402 } 423 }
403 } 424 }
404 } 425 }
405 children.sort(this.sortFromId(this.currentState.callTree.sort)); 426 children.sort(this.sortFromId(this.currentState.callTree.sort));
(...skipping 19 matching lines...) Expand all
425 if (this.currentState.callTree.mode !== "bottom-up") { 446 if (this.currentState.callTree.mode !== "bottom-up") {
426 c = row.insertCell(-1); 447 c = row.insertCell(-1);
427 c.textContent = (node.ownTicks * 100 / this.tickCount).toFixed(2) + "%"; 448 c.textContent = (node.ownTicks * 100 / this.tickCount).toFixed(2) + "%";
428 c.style.textAlign = "right"; 449 c.style.textAlign = "right";
429 } 450 }
430 451
431 // Create the name cell. 452 // Create the name cell.
432 let nameCell = row.insertCell(); 453 let nameCell = row.insertCell();
433 let expander = this.createExpander(indent); 454 let expander = this.createExpander(indent);
434 nameCell.appendChild(expander); 455 nameCell.appendChild(expander);
435 nameCell.appendChild(this.createTypeDiv(node.type)); 456 nameCell.appendChild(createTypeDiv(node.type));
436 nameCell.appendChild(document.createTextNode(node.name)); 457 nameCell.appendChild(this.createFunctionNode(node.name, node.codeId));
437 458
438 // Inclusive ticks cell. 459 // Inclusive ticks cell.
439 c = row.insertCell(); 460 c = row.insertCell();
440 c.textContent = node.ticks; 461 c.textContent = node.ticks;
441 c.style.textAlign = "right"; 462 c.style.textAlign = "right";
442 if (this.currentState.callTree.mode !== "bottom-up") { 463 if (this.currentState.callTree.mode !== "bottom-up") {
443 // Exclusive ticks cell. 464 // Exclusive ticks cell.
444 c = row.insertCell(-1); 465 c = row.insertCell(-1);
445 c.textContent = node.ownTicks; 466 c.textContent = node.ownTicks;
446 c.style.textAlign = "right"; 467 c.style.textAlign = "right";
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 } 587 }
567 588
568 let ownTimeClass = (mode === "bottom-up") ? "numeric-hidden" : "numeric"; 589 let ownTimeClass = (mode === "bottom-up") ? "numeric-hidden" : "numeric";
569 let ownTimeTh = $(this.treeElement.id + "-own-time-header"); 590 let ownTimeTh = $(this.treeElement.id + "-own-time-header");
570 ownTimeTh.classList = ownTimeClass; 591 ownTimeTh.classList = ownTimeClass;
571 let ownTicksTh = $(this.treeElement.id + "-own-ticks-header"); 592 let ownTicksTh = $(this.treeElement.id + "-own-ticks-header");
572 ownTicksTh.classList = ownTimeClass; 593 ownTicksTh.classList = ownTimeClass;
573 594
574 // Build the tree. 595 // Build the tree.
575 let stackProcessor; 596 let stackProcessor;
576 let filter = this.filterFromFilterId(this.currentState.callTree.attribution) ; 597 let filter = filterFromFilterId(this.currentState.callTree.attribution);
577 if (mode === "top-down") { 598 if (mode === "top-down") {
578 stackProcessor = 599 stackProcessor =
579 new PlainCallTreeProcessor(filter, false); 600 new PlainCallTreeProcessor(filter, false);
580 } else if (mode === "function-list") { 601 } else if (mode === "function-list") {
581 stackProcessor = new FunctionListTree( 602 stackProcessor = new FunctionListTree(
582 filter, this.currentState.callTree.categories === "code-type"); 603 filter, this.currentState.callTree.categories === "code-type");
583 604
584 } else { 605 } else {
585 console.assert(mode === "bottom-up"); 606 console.assert(mode === "bottom-up");
586 if (this.currentState.callTree.categories == "none") { 607 if (this.currentState.callTree.categories == "none") {
(...skipping 25 matching lines...) Expand all
612 // Swap in the new rows. 633 // Swap in the new rows.
613 this.treeElement.replaceChild(newRows, oldRows[0]); 634 this.treeElement.replaceChild(newRows, oldRows[0]);
614 } 635 }
615 } 636 }
616 637
617 class TimelineView { 638 class TimelineView {
618 constructor() { 639 constructor() {
619 this.element = $("timeline"); 640 this.element = $("timeline");
620 this.canvas = $("timeline-canvas"); 641 this.canvas = $("timeline-canvas");
621 this.legend = $("timeline-legend"); 642 this.legend = $("timeline-legend");
643 this.currentCode = $("timeline-currentCode");
622 644
623 this.canvas.onmousedown = this.onMouseDown.bind(this); 645 this.canvas.onmousedown = this.onMouseDown.bind(this);
624 this.canvas.onmouseup = this.onMouseUp.bind(this); 646 this.canvas.onmouseup = this.onMouseUp.bind(this);
625 this.canvas.onmousemove = this.onMouseMove.bind(this); 647 this.canvas.onmousemove = this.onMouseMove.bind(this);
626 648
627 this.selectionStart = null; 649 this.selectionStart = null;
628 this.selectionEnd = null; 650 this.selectionEnd = null;
629 this.selecting = false; 651 this.selecting = false;
630 652
631 this.fontSize = 12; 653 this.fontSize = 12;
632 this.imageOffset = this.fontSize * 1.2; 654 this.imageOffset = this.fontSize * 1.2;
655 this.functionTimelineHeight = 12;
633 656
634 this.currentState = null; 657 this.currentState = null;
635 } 658 }
636 659
637 onMouseDown(e) { 660 onMouseDown(e) {
638 this.selectionStart = 661 this.selectionStart =
639 e.clientX - this.canvas.getBoundingClientRect().left; 662 e.clientX - this.canvas.getBoundingClientRect().left;
640 this.selectionEnd = this.selectionStart + 1; 663 this.selectionEnd = this.selectionStart + 1;
641 this.selecting = true; 664 this.selecting = true;
642 } 665 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 // Draw the timeline image. 714 // Draw the timeline image.
692 ctx.drawImage(this.buffer, 0, this.imageOffset); 715 ctx.drawImage(this.buffer, 0, this.imageOffset);
693 716
694 // Draw the current interval highlight. 717 // Draw the current interval highlight.
695 let left; 718 let left;
696 let right; 719 let right;
697 if (this.selectionStart !== null && this.selectionEnd !== null) { 720 if (this.selectionStart !== null && this.selectionEnd !== null) {
698 ctx.fillStyle = "rgba(0, 0, 0, 0.3)"; 721 ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
699 left = Math.min(this.selectionStart, this.selectionEnd); 722 left = Math.min(this.selectionStart, this.selectionEnd);
700 right = Math.max(this.selectionStart, this.selectionEnd); 723 right = Math.max(this.selectionStart, this.selectionEnd);
701 ctx.fillRect(0, this.imageOffset, left, this.buffer.height); 724 let height = this.buffer.height - this.functionTimelineHeight;
702 ctx.fillRect(right, this.imageOffset, this.buffer.width - right, 725 ctx.fillRect(0, this.imageOffset, left, height);
703 this.buffer.height); 726 ctx.fillRect(right, this.imageOffset, this.buffer.width - right, height);
704 } else { 727 } else {
705 left = 0; 728 left = 0;
706 right = this.buffer.width; 729 right = this.buffer.width;
707 } 730 }
708 731
709 // Draw the scale text. 732 // Draw the scale text.
710 let file = this.currentState.file; 733 let file = this.currentState.file;
711 ctx.fillStyle = "white"; 734 ctx.fillStyle = "white";
712 ctx.fillRect(0, 0, this.canvas.width, this.imageOffset); 735 ctx.fillRect(0, 0, this.canvas.width, this.imageOffset);
713 if (file && file.ticks.length > 0) { 736 if (file && file.ticks.length > 0) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 if (!newState.file) { 779 if (!newState.file) {
757 this.element.style.display = "none"; 780 this.element.style.display = "none";
758 return; 781 return;
759 } 782 }
760 783
761 this.currentState = newState; 784 this.currentState = newState;
762 if (oldState) { 785 if (oldState) {
763 if (newState.timeLine.width === oldState.timeLine.width && 786 if (newState.timeLine.width === oldState.timeLine.width &&
764 newState.timeLine.height === oldState.timeLine.height && 787 newState.timeLine.height === oldState.timeLine.height &&
765 newState.file === oldState.file && 788 newState.file === oldState.file &&
789 newState.currentCodeId === oldState.currentCodeId &&
766 newState.start === oldState.start && 790 newState.start === oldState.start &&
767 newState.end === oldState.end) { 791 newState.end === oldState.end) {
768 // No change, nothing to do. 792 // No change, nothing to do.
769 return; 793 return;
770 } 794 }
771 } 795 }
772 796
773 this.element.style.display = "inherit"; 797 this.element.style.display = "inherit";
774 798
775 // Make sure the canvas has the right dimensions. 799 // Make sure the canvas has the right dimensions.
776 let width = this.currentState.timeLine.width; 800 let width = this.currentState.timeLine.width;
777 let height = this.currentState.timeLine.height; 801 let height = this.currentState.timeLine.height;
778 this.canvas.width = width; 802 this.canvas.width = width;
779 this.canvas.height = height; 803 this.canvas.height = height;
780 804
781 // Make space for the selection text. 805 // Make space for the selection text.
782 height -= this.imageOffset; 806 height -= this.imageOffset;
783 807
784 let file = this.currentState.file; 808 let file = this.currentState.file;
785 if (!file) return; 809 if (!file) return;
786 810
811 let currentCodeId = this.currentState.currentCodeId;
812
787 let firstTime = file.ticks[0].tm; 813 let firstTime = file.ticks[0].tm;
788 let lastTime = file.ticks[file.ticks.length - 1].tm; 814 let lastTime = file.ticks[file.ticks.length - 1].tm;
789 let start = Math.max(this.currentState.start, firstTime); 815 let start = Math.max(this.currentState.start, firstTime);
790 let end = Math.min(this.currentState.end, lastTime); 816 let end = Math.min(this.currentState.end, lastTime);
791 817
792 this.selectionStart = (start - firstTime) / (lastTime - firstTime) * width; 818 this.selectionStart = (start - firstTime) / (lastTime - firstTime) * width;
793 this.selectionEnd = (end - firstTime) / (lastTime - firstTime) * width; 819 this.selectionEnd = (end - firstTime) / (lastTime - firstTime) * width;
794 820
795 let tickCount = file.ticks.length; 821 let tickCount = file.ticks.length;
796 822
797 let minBucketPixels = 10; 823 let minBucketPixels = 10;
798 let minBucketSamples = 30; 824 let minBucketSamples = 30;
799 let bucketCount = Math.min(width / minBucketPixels, 825 let bucketCount = Math.min(width / minBucketPixels,
800 tickCount / minBucketSamples); 826 tickCount / minBucketSamples);
801 827
802 let stackProcessor = new CategorySampler(file, bucketCount); 828 let stackProcessor = new CategorySampler(file, bucketCount);
803 generateTree(file, 0, Infinity, stackProcessor); 829 generateTree(file, 0, Infinity, stackProcessor);
830 let codeIdProcessor = new FunctionTimelineProcessor(
831 currentCodeId,
832 filterFromFilterId(this.currentState.callTree.attribution));
833 generateTree(file, 0, Infinity, codeIdProcessor);
Jarin 2017/03/08 16:35:56 One thought: for delayed expansions we already hav
804 834
805 let buffer = document.createElement("canvas"); 835 let buffer = document.createElement("canvas");
806 836
807 buffer.width = width; 837 buffer.width = width;
808 buffer.height = height; 838 buffer.height = height;
809 839
810 // Calculate the bar heights for each bucket. 840 // Calculate the bar heights for each bucket.
811 let graphHeight = height; 841 let graphHeight = height - this.functionTimelineHeight;
812 let buckets = stackProcessor.buckets; 842 let buckets = stackProcessor.buckets;
813 let bucketsGraph = []; 843 let bucketsGraph = [];
814 for (let i = 0; i < buckets.length; i++) { 844 for (let i = 0; i < buckets.length; i++) {
815 let sum = 0; 845 let sum = 0;
816 let bucketData = []; 846 let bucketData = [];
817 let total = buckets[i].total; 847 let total = buckets[i].total;
818 for (let j = 0; j < bucketDescriptors.length; j++) { 848 for (let j = 0; j < bucketDescriptors.length; j++) {
819 let desc = bucketDescriptors[j]; 849 let desc = bucketDescriptors[j];
820 for (let k = 0; k < desc.kinds.length; k++) { 850 for (let k = 0; k < desc.kinds.length; k++) {
821 sum += buckets[i][desc.kinds[k]]; 851 sum += buckets[i][desc.kinds[k]];
(...skipping 13 matching lines...) Expand all
835 ctx.beginPath(); 865 ctx.beginPath();
836 ctx.moveTo(i * bucketWidth, j && bucketData[j - 1]); 866 ctx.moveTo(i * bucketWidth, j && bucketData[j - 1]);
837 ctx.lineTo((i + 1) * bucketWidth, j && nextBucketData[j - 1]); 867 ctx.lineTo((i + 1) * bucketWidth, j && nextBucketData[j - 1]);
838 ctx.lineTo((i + 1) * bucketWidth, nextBucketData[j]); 868 ctx.lineTo((i + 1) * bucketWidth, nextBucketData[j]);
839 ctx.lineTo(i * bucketWidth, bucketData[j]); 869 ctx.lineTo(i * bucketWidth, bucketData[j]);
840 ctx.closePath(); 870 ctx.closePath();
841 ctx.fillStyle = bucketDescriptors[j].color; 871 ctx.fillStyle = bucketDescriptors[j].color;
842 ctx.fill(); 872 ctx.fill();
843 } 873 }
844 } 874 }
875 let functionTimelineYOffset = graphHeight;
876 let functionTimelineHeight = this.functionTimelineHeight;
877 let timestampScaler = width / (lastTime - firstTime);
878 ctx.fillStyle = "white";
879 ctx.fillRect(
880 0,
881 functionTimelineYOffset,
882 buffer.width,
883 functionTimelineHeight);
884 for (let i = 0; i < codeIdProcessor.blocks.length; i++) {
885 let block = codeIdProcessor.blocks[i];
886 ctx.fillStyle = "#000000";
887 ctx.fillRect(
888 Math.round((block.start - firstTime) * timestampScaler),
889 functionTimelineYOffset,
890 Math.max(1, Math.round((block.end - block.start) * timestampScaler)),
891 block.topOfStack ? functionTimelineHeight : functionTimelineHeight / 2);
892 }
845 893
846 // Remember stuff for later. 894 // Remember stuff for later.
847 this.buffer = buffer; 895 this.buffer = buffer;
848 896
849 // Draw the buffer. 897 // Draw the buffer.
850 this.drawSelection(); 898 this.drawSelection();
851 899
852 // (Re-)Populate the graph legend. 900 // (Re-)Populate the graph legend.
853 while (this.legend.cells.length > 0) { 901 while (this.legend.cells.length > 0) {
854 this.legend.deleteCell(0); 902 this.legend.deleteCell(0);
855 } 903 }
856 let cell = this.legend.insertCell(-1); 904 let cell = this.legend.insertCell(-1);
857 cell.textContent = "Legend: "; 905 cell.textContent = "Legend: ";
858 cell.style.padding = "1ex"; 906 cell.style.padding = "1ex";
859 for (let i = 0; i < bucketDescriptors.length; i++) { 907 for (let i = 0; i < bucketDescriptors.length; i++) {
860 let cell = this.legend.insertCell(-1); 908 let cell = this.legend.insertCell(-1);
861 cell.style.padding = "1ex"; 909 cell.style.padding = "1ex";
862 let desc = bucketDescriptors[i]; 910 let desc = bucketDescriptors[i];
863 let div = document.createElement("div"); 911 let div = document.createElement("div");
864 div.style.display = "inline-block"; 912 div.style.display = "inline-block";
865 div.style.width = "0.6em"; 913 div.style.width = "0.6em";
866 div.style.height = "1.2ex"; 914 div.style.height = "1.2ex";
867 div.style.backgroundColor = desc.color; 915 div.style.backgroundColor = desc.color;
868 div.style.borderStyle = "solid"; 916 div.style.borderStyle = "solid";
869 div.style.borderWidth = "1px"; 917 div.style.borderWidth = "1px";
870 div.style.borderColor = "Black"; 918 div.style.borderColor = "Black";
871 cell.appendChild(div); 919 cell.appendChild(div);
872 cell.appendChild(document.createTextNode(" " + desc.text)); 920 cell.appendChild(document.createTextNode(" " + desc.text));
873 } 921 }
922
923 while (this.currentCode.firstChild) {
924 this.currentCode.removeChild(this.currentCode.firstChild);
925 }
926 if (currentCodeId) {
927 let currentCode = file.code[currentCodeId];
928 this.currentCode.appendChild(createTypeDiv(resolveCodeKind(currentCode)));
929 this.currentCode.appendChild(document.createTextNode(currentCode.name));
930
931 } else {
932 this.currentCode.appendChild(document.createTextNode("<none>"));
933 }
874 } 934 }
875 } 935 }
876 936
877 class HelpView { 937 class HelpView {
878 constructor() { 938 constructor() {
879 this.element = $("help"); 939 this.element = $("help");
880 } 940 }
881 941
882 render(newState) { 942 render(newState) {
883 this.element.style.display = newState.file ? "none" : "inherit"; 943 this.element.style.display = newState.file ? "none" : "inherit";
884 } 944 }
885 } 945 }
OLDNEW
« tools/profview/profile-utils.js ('K') | « tools/profview/profview.css ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698