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

Side by Side Diff: Source/devtools/front_end/timeline/TracingTimelineUIUtils.js

Issue 654013003: Implement invalidation tracking in devtools (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Address reviewer comments, update how stacks are handled Created 6 years, 2 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium 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 /** 5 /**
6 * @constructor 6 * @constructor
7 * @extends {WebInspector.TimelineUIUtils} 7 * @extends {WebInspector.TimelineUIUtils}
8 */ 8 */
9 WebInspector.TracingTimelineUIUtils = function() 9 WebInspector.TracingTimelineUIUtils = function()
10 { 10 {
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 * @param {!WebInspector.TracingModel.Event} event 479 * @param {!WebInspector.TracingModel.Event} event
480 * @param {!WebInspector.TracingTimelineModel} model 480 * @param {!WebInspector.TracingTimelineModel} model
481 * @param {!WebInspector.Linkifier} linkifier 481 * @param {!WebInspector.Linkifier} linkifier
482 * @param {function(!DocumentFragment)} callback 482 * @param {function(!DocumentFragment)} callback
483 */ 483 */
484 WebInspector.TracingTimelineUIUtils.buildTraceEventDetails = function(event, mod el, linkifier, callback) 484 WebInspector.TracingTimelineUIUtils.buildTraceEventDetails = function(event, mod el, linkifier, callback)
485 { 485 {
486 var target = event.thread.target(); 486 var target = event.thread.target();
487 var relatedNode = null; 487 var relatedNode = null;
488 var barrier = new CallbackBarrier(); 488 var barrier = new CallbackBarrier();
489 if (!event.previewElement && target) { 489 var invalidationBackendNodeIds;
490 if (!event.previewElement) {
490 if (event.imageURL) 491 if (event.imageURL)
491 WebInspector.DOMPresentationUtils.buildImagePreviewContents(target, event.imageURL, false, barrier.createCallback(saveImage)); 492 WebInspector.DOMPresentationUtils.buildImagePreviewContents(target, event.imageURL, false, barrier.createCallback(saveImage));
492 else if (event.picture) 493 else if (event.picture)
493 WebInspector.TracingTimelineUIUtils.buildPicturePreviewContent(event , barrier.createCallback(saveImage)); 494 WebInspector.TracingTimelineUIUtils.buildPicturePreviewContent(event , barrier.createCallback(saveImage));
494 } 495 }
495 if (event.backendNodeId && target) 496 if (event.backendNodeId)
496 target.domModel.pushNodesByBackendIdsToFrontend([event.backendNodeId], b arrier.createCallback(setRelatedNode)); 497 target.domModel.pushNodesByBackendIdsToFrontend([event.backendNodeId], b arrier.createCallback(setRelatedNode));
498 if (event.invalidationTrackingEvents)
499 invalidationBackendNodeIds = WebInspector.TracingTimelineUIUtils._pushIn validationNodeIdsToFrontend(event, barrier.createCallback(updateInvalidationNode Ids));
caseq 2014/10/17 15:48:55 nit: I would make this function pass a map from ba
pdr. 2014/10/20 21:38:05 Done.
497 barrier.callWhenDone(callbackWrapper); 500 barrier.callWhenDone(callbackWrapper);
498 501
499 /** 502 /**
500 * @param {!Element=} element 503 * @param {!Element=} element
501 */ 504 */
502 function saveImage(element) 505 function saveImage(element)
503 { 506 {
504 event.previewElement = element || null; 507 event.previewElement = element || null;
505 } 508 }
506 509
507 /** 510 /**
508 * @param {?Array.<!DOMAgent.NodeId>} nodeIds 511 * @param {?Array.<!DOMAgent.NodeId>} nodeIds
509 */ 512 */
510 function setRelatedNode(nodeIds) 513 function setRelatedNode(nodeIds)
511 { 514 {
512 if (nodeIds) 515 if (nodeIds)
513 relatedNode = target.domModel.nodeForId(nodeIds[0]); 516 relatedNode = target.domModel.nodeForId(nodeIds[0]);
514 } 517 }
515 518
519 /**
520 * @param {?Array.<!DOMAgent.NodeId>} frontendNodeIds
521 */
522 function updateInvalidationNodeIds(frontendNodeIds)
523 {
524 if (!frontendNodeIds)
525 return;
526 if (frontendNodeIds.length != invalidationBackendNodeIds.length) {
caseq 2014/10/17 15:48:55 !==
pdr. 2014/10/20 21:38:05 Done.
527 console.error("Did not resolve the correct number of invalidation no de ids.");
528 return;
529 }
530
531 var backendToFrontendNodeIdMap = {};
532 invalidationBackendNodeIds.forEach(function(backendNodeId, index) {
533 backendToFrontendNodeIdMap[backendNodeId] = frontendNodeIds[index];
534 });
535
536 if (event.nodeId)
537 event.frontendNodeId = backendToFrontendNodeIdMap[event.nodeId];
538 event.invalidationTrackingEvents.forEach(function(invalidation) {
539 if (invalidation.nodeId)
540 invalidation.frontendNodeId = backendToFrontendNodeIdMap[invalid ation.nodeId];
541 });
542 }
543
516 function callbackWrapper() 544 function callbackWrapper()
517 { 545 {
518 callback(WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSync hronously(event, model, linkifier, relatedNode)); 546 callback(WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSync hronously(event, model, linkifier, relatedNode));
519 } 547 }
520 } 548 }
521 549
522 /** 550 /**
523 * @param {!WebInspector.TracingModel.Event} event 551 * @param {!WebInspector.TracingModel.Event} event
524 * @param {!WebInspector.TracingTimelineModel} model 552 * @param {!WebInspector.TracingTimelineModel} model
525 * @param {!WebInspector.Linkifier} linkifier 553 * @param {!WebInspector.Linkifier} linkifier
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 683
656 var warning = event.warning; 684 var warning = event.warning;
657 if (warning) { 685 if (warning) {
658 var div = document.createElement("div"); 686 var div = document.createElement("div");
659 div.textContent = warning; 687 div.textContent = warning;
660 contentHelper.appendElementRow(WebInspector.UIString("Warning"), div); 688 contentHelper.appendElementRow(WebInspector.UIString("Warning"), div);
661 } 689 }
662 if (event.previewElement) 690 if (event.previewElement)
663 contentHelper.appendElementRow(WebInspector.UIString("Preview"), event.p reviewElement); 691 contentHelper.appendElementRow(WebInspector.UIString("Preview"), event.p reviewElement);
664 692
665 if (event.stackTrace || (event.initiator && event.initiator.stackTrace)) 693 if (event.stackTrace || (event.initiator && event.initiator.stackTrace) || e vent.invalidationTrackingEvents)
666 WebInspector.TracingTimelineUIUtils._generateCauses(event, contentHelper ); 694 WebInspector.TracingTimelineUIUtils._generateCauses(event, contentHelper );
667 695
668 fragment.appendChild(contentHelper.element); 696 fragment.appendChild(contentHelper.element);
669 return fragment; 697 return fragment;
670 } 698 }
671 699
672 /** 700 /**
673 * @param {!WebInspector.TracingModel.Event} event 701 * @param {!WebInspector.TracingModel.Event} event
674 * @param {!WebInspector.TimelineDetailsContentHelper} contentHelper 702 * @param {!WebInspector.TimelineDetailsContentHelper} contentHelper
675 */ 703 */
676 WebInspector.TracingTimelineUIUtils._generateCauses = function(event, contentHel per) 704 WebInspector.TracingTimelineUIUtils._generateCauses = function(event, contentHel per)
677 { 705 {
678 var recordTypes = WebInspector.TracingTimelineModel.RecordType; 706 var recordTypes = WebInspector.TracingTimelineModel.RecordType;
679 707
680 var callSiteStackLabel; 708 var callSiteStackLabel;
681 var stackLabel; 709 var stackLabel;
710 var initiator = event.initiator;
682 711
683 switch (event.name) { 712 switch (event.name) {
684 case recordTypes.TimerFire: 713 case recordTypes.TimerFire:
685 callSiteStackLabel = WebInspector.UIString("Timer installed"); 714 callSiteStackLabel = WebInspector.UIString("Timer installed");
686 break; 715 break;
687 case recordTypes.FireAnimationFrame: 716 case recordTypes.FireAnimationFrame:
688 callSiteStackLabel = WebInspector.UIString("Animation frame requested"); 717 callSiteStackLabel = WebInspector.UIString("Animation frame requested");
689 break; 718 break;
690 case recordTypes.RecalculateStyles: 719 case recordTypes.RecalculateStyles:
691 stackLabel = WebInspector.UIString("Stack when style recalculation was f orced"); 720 stackLabel = WebInspector.UIString("Stack when style recalculation was f orced");
692 break; 721 break;
693 case recordTypes.Layout: 722 case recordTypes.Layout:
694 callSiteStackLabel = WebInspector.UIString("First layout invalidation"); 723 callSiteStackLabel = WebInspector.UIString("First layout invalidation");
695 stackLabel = WebInspector.UIString("Stack when layout was forced"); 724 stackLabel = WebInspector.UIString("Stack when layout was forced");
696 break; 725 break;
697 } 726 }
698 727
699 // Direct cause. 728 // Direct cause.
700 if (event.stackTrace) 729 if (event.stackTrace)
701 contentHelper.appendStackTrace(stackLabel || WebInspector.UIString("Stac k when this event occurred"), event.stackTrace); 730 contentHelper.appendStackTrace(stackLabel || WebInspector.UIString("Stac k when this event occurred"), event.stackTrace);
702 731
703 // Indirect cause / invalidation. 732 // Indirect causes.
704 var initiator = event.initiator; 733 if (event.invalidationTrackingEvents) { // Full invalidation tracking (exper imental).
705 if (initiator && initiator.stackTrace) 734 WebInspector.TracingTimelineUIUtils._generateInvalidations(event, conten tHelper);
735 } else if (initiator && initiator.stackTrace) { // Partial invalidation trac king.
706 contentHelper.appendStackTrace(callSiteStackLabel || WebInspector.UIStri ng("Stack when first invalidated"), initiator.stackTrace); 736 contentHelper.appendStackTrace(callSiteStackLabel || WebInspector.UIStri ng("Stack when first invalidated"), initiator.stackTrace);
737 }
707 } 738 }
708 739
709 /** 740 /**
741 * @param {!WebInspector.TracingModel.Event} event
742 * @param {!WebInspector.TimelineDetailsContentHelper} contentHelper
743 */
744 WebInspector.TracingTimelineUIUtils._generateInvalidations = function(event, con tentHelper)
745 {
746 if (!event.invalidationTrackingEvents)
747 return;
748
749 var target = event.thread.target();
750 var invalidations = {};
751 event.invalidationTrackingEvents.forEach(function(invalidation) {
752 if (invalidations[invalidation.type] === undefined)
caseq 2014/10/17 15:48:55 nit: if (!invalidations[invalidation.type]) ...
pdr. 2014/10/20 21:38:05 Done
753 invalidations[invalidation.type] = [invalidation];
754 else
755 invalidations[invalidation.type].push(invalidation);
756 });
757
758 Object.keys(invalidations).forEach(function(type) {
759 WebInspector.TracingTimelineUIUtils._generateInvalidationsForType(
760 type, target, invalidations[type], contentHelper);
761 });
762 }
763
764 /**
765 * @param {string} type
766 * @param {?WebInspector.Target} target
767 * @param {!Object} invalidationEvents
768 * @param {!WebInspector.TimelineDetailsContentHelper} contentHelper
769 */
770 WebInspector.TracingTimelineUIUtils._generateInvalidationsForType = function(typ e, target, invalidationEvents, contentHelper)
771 {
772 var title;
773 switch (type) {
774 case WebInspector.TracingTimelineModel.RecordType.StyleRecalcInvalidationTra cking:
775 title = WebInspector.UIString("Style invalidations");
776 break;
777 case WebInspector.TracingTimelineModel.RecordType.LayoutInvalidationTracking :
778 title = WebInspector.UIString("Layout invalidations");
779 break;
780 default:
781 title = WebInspector.UIString("Other invalidations");
782 break;
783 }
784
785 var detailsNode = document.createElement("div");
786 detailsNode.className = "timeline-details-view-row";
787 var titleElement = detailsNode.createChild("span", "timeline-details-view-ro w-title");
788 titleElement.textContent = WebInspector.UIString("%s: ", title);
789 var eventsList = detailsNode.createChild("ol");
790 invalidationEvents.forEach(appendInvalidations);
791
792 contentHelper.element.appendChild(detailsNode);
793
794
795 function appendInvalidations(invalidation, index)
796 {
797 var row = eventsList.createChild("li");
798 var nodeRow = row.createChild("div");
799 var node = target.domModel.nodeForId(invalidation.frontendNodeId);
800 if (node)
801 nodeRow.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeRef erence(node));
802 else if (invalidation.nodeName)
803 nodeRow.textContent = WebInspector.UIString("[ %s ]", invalidation.n odeName);
804 else
805 nodeRow.textContent = WebInspector.UIString("[ unknown node ]");
806
807 if (invalidation.reason) {
808 var reasonRow = row.createChild("div");
809 var reason = invalidation.reason;
810 // We should clean up invalidation strings so they are consistent: c rbug.com/424451.
811 if (!invalidation.reason.endsWith("."))
812 reason += ".";
813 reasonRow.textContent = WebInspector.UIString("Reason: %s", reason);
814 }
815
816 if (invalidation.stackTrace)
817 contentHelper.createChildStackTraceElement(row, invalidation.stackTr ace);
818 }
819 }
820
821 /**
822 * @param {!WebInspector.TracingModel.Event} event
823 * @param {function(!Array.<number>)} callback
824 * @return {?Array.<number>} backend node ids
825 */
826 WebInspector.TracingTimelineUIUtils._pushInvalidationNodeIdsToFrontend = functio n(event, callback)
827 {
828 var backendNodeIds = [];
829
830 var dedupedNodeIds = {};
831 if (event.nodeId) {
832 backendNodeIds.push(event.nodeId);
833 dedupedNodeIds[event.nodeId] = true;
834 }
835 event.invalidationTrackingEvents.forEach(function(invalidation) {
836 if (invalidation.nodeId && !dedupedNodeIds[invalidation.nodeId]) {
837 backendNodeIds.push(invalidation.nodeId);
838 dedupedNodeIds[invalidation.nodeId] = true;
839 }
840 });
841
842 var target = event.thread.target();
843 target.domModel.pushNodesByBackendIdsToFrontend(backendNodeIds, callback);
844 return backendNodeIds;
845 }
846
847 /**
710 * @param {!Object} total 848 * @param {!Object} total
711 * @param {!WebInspector.TracingTimelineModel} model 849 * @param {!WebInspector.TracingTimelineModel} model
712 * @param {!WebInspector.TracingModel.Event} event 850 * @param {!WebInspector.TracingModel.Event} event
713 * @return {boolean} 851 * @return {boolean}
714 */ 852 */
715 WebInspector.TracingTimelineUIUtils._aggregatedStatsForTraceEvent = function(tot al, model, event) 853 WebInspector.TracingTimelineUIUtils._aggregatedStatsForTraceEvent = function(tot al, model, event)
716 { 854 {
717 var events = model.inspectedTargetEvents(); 855 var events = model.inspectedTargetEvents();
718 /** 856 /**
719 * @param {number} startTime 857 * @param {number} startTime
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 return result; 973 return result;
836 } 974 }
837 975
838 /** 976 /**
839 * @return {!WebInspector.TracingTimelineModel.Filter} 977 * @return {!WebInspector.TracingTimelineModel.Filter}
840 */ 978 */
841 WebInspector.TracingTimelineUIUtils.hiddenEventsFilter = function() 979 WebInspector.TracingTimelineUIUtils.hiddenEventsFilter = function()
842 { 980 {
843 return new WebInspector.TracingTimelineModel.InclusiveEventNameFilter(WebIns pector.TracingTimelineUIUtils._visibleTypes()); 981 return new WebInspector.TracingTimelineModel.InclusiveEventNameFilter(WebIns pector.TracingTimelineUIUtils._visibleTypes());
844 } 982 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698