WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
Bug 88325
Web Inspector: Implement message loop instrumentation for timeline
https://bugs.webkit.org/show_bug.cgi?id=88325
Summary
Web Inspector: Implement message loop instrumentation for timeline
eustas.bug
Reported
2012-06-05 05:18:06 PDT
Created
attachment 145766
[details]
Demo screenshot Message loop instrumentation will show when the render thread is busy. That way developer can discover if a render thread business causes low fps, or not.
Attachments
Demo screenshot
(59.90 KB, image/png)
2012-06-05 05:18 PDT
,
eustas.bug
no flags
Details
Patch
(34.25 KB, patch)
2012-06-05 05:53 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Updated demo screenshot
(62.41 KB, image/png)
2012-06-05 09:03 PDT
,
eustas.bug
no flags
Details
Patch
(30.47 KB, patch)
2012-06-05 09:06 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Yet another message loop bar appearance.
(61.90 KB, image/png)
2012-06-06 01:21 PDT
,
eustas.bug
no flags
Details
Diagram1: WebView has an implicit contract to hold both WebDevToolsAgent and WebDevToolsAgentClient references
(41.64 KB, image/png)
2012-06-06 03:19 PDT
,
eustas.bug
no flags
Details
Diagram 2: Implementation of WebDevToolsAgent holds reference to WebDevToolsAgentClient
(34.68 KB, image/png)
2012-06-06 03:20 PDT
,
eustas.bug
no flags
Details
Diagram 3: Implicit contract is turned to explicit in chromium: WebDevToolsAgentClient implementation has access to corresponding WebDevToolsAgent.
(81.15 KB, image/png)
2012-06-06 03:22 PDT
,
eustas.bug
no flags
Details
Patch
(31.45 KB, patch)
2012-06-06 03:30 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
UI: take 4
(60.19 KB, image/png)
2012-06-06 07:32 PDT
,
eustas.bug
no flags
Details
UI: take 5
(60.06 KB, image/png)
2012-06-06 07:32 PDT
,
eustas.bug
no flags
Details
UI: take 5, close-up
(59.64 KB, image/png)
2012-06-06 07:37 PDT
,
eustas.bug
no flags
Details
UI: take 6
(61.14 KB, image/png)
2012-06-06 07:55 PDT
,
eustas.bug
no flags
Details
UI: take 6, close-up
(59.89 KB, image/png)
2012-06-06 07:55 PDT
,
eustas.bug
no flags
Details
UI: take 6 in light-blue
(61.49 KB, image/png)
2012-06-06 08:10 PDT
,
eustas.bug
no flags
Details
UI: take 6 in light-blue, close-up
(60.18 KB, image/png)
2012-06-06 08:11 PDT
,
eustas.bug
no flags
Details
UI: take 7: something between 4 and 5 with removed garbage dots
(60.11 KB, image/png)
2012-06-07 00:52 PDT
,
eustas.bug
no flags
Details
UI: take 7, close-up
(59.76 KB, image/png)
2012-06-07 00:53 PDT
,
eustas.bug
no flags
Details
Screenshot: close view on "unknown" tasks
(60.58 KB, image/png)
2012-06-08 07:27 PDT
,
eustas.bug
no flags
Details
Screenshot: "unknown" tasks pollute timeline
(82.00 KB, image/png)
2012-06-08 07:28 PDT
,
eustas.bug
no flags
Details
Screenshot: same data, with switched off "unknown" category
(85.71 KB, image/png)
2012-06-08 07:28 PDT
,
eustas.bug
no flags
Details
Patch
(18.16 KB, patch)
2012-06-15 10:21 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Demo screenshot
(48.16 KB, image/png)
2012-06-15 10:23 PDT
,
eustas.bug
no flags
Details
Patch
(23.64 KB, patch)
2012-06-18 14:54 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(14.28 KB, patch)
2012-06-29 03:00 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(13.15 KB, patch)
2012-07-03 09:09 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(14.79 KB, patch)
2012-07-04 01:01 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(14.82 KB, patch)
2012-07-04 02:58 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(14.84 KB, patch)
2012-07-04 03:06 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(14.47 KB, patch)
2012-07-11 05:53 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(14.39 KB, patch)
2012-07-12 02:10 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(14.57 KB, patch)
2012-07-13 03:06 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Patch
(14.51 KB, patch)
2012-07-13 04:23 PDT
,
eustas.bug
no flags
Details
Formatted Diff
Diff
Show Obsolete
(31)
View All
Add attachment
proposed patch, testcase, etc.
eustas.bug
Comment 1
2012-06-05 05:53:31 PDT
Created
attachment 145772
[details]
Patch
WebKit Review Bot
Comment 2
2012-06-05 05:56:17 PDT
Please wait for approval from
abarth@webkit.org
,
dglazkov@chromium.org
,
fishd@chromium.org
,
jamesr@chromium.org
or
tkent@chromium.org
before submitting, as this patch contains changes to the Chromium public API. See also
https://trac.webkit.org/wiki/ChromiumWebKitAPI
.
Andrey Kosyakov
Comment 3
2012-06-05 06:35:34 PDT
Comment on
attachment 145772
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=145772&action=review
> Source/WebCore/inspector/InspectorTimelineAgent.cpp:157 > + m_taskEventStartTime = std::numeric_limits<double>::quiet_NaN();
nit: I think we could as well use 0.0, we do this elsewhere.
> Source/WebCore/inspector/InspectorTimelineAgent.cpp:172 > + m_taskEventStartTime = std::numeric_limits<double>::quiet_NaN();
ditto.
> Source/WebCore/inspector/InspectorTimelineAgent.cpp:193 > + *result = m_client ? m_client->supportsFrameInstrumentation() : false;
nit: m_client && m_client->supportsFrameInstrumentation()
> Source/WebCore/inspector/InspectorTimelineAgent.cpp:462 > + counters->setNumber("nodes", (m_client) ? InspectorCounters::counterValue(InspectorCounters::NodeCounter) : 0); > + counters->setNumber("documents", (m_client) ? InspectorCounters::counterValue(InspectorCounters::DocumentCounter) : 0);
Checking for client presence to determine inspector type looks like a hack here. I think we might as well keep inspector type explicit, though at the moment it will be actually redundant.
> Source/WebCore/inspector/InspectorTimelineAgent.cpp:474 > + TaskEvents events = m_taskEvents; > + m_taskEvents.clear();
You can avoid copying a vector here by using Vector::swap()
> Source/WebCore/inspector/InspectorTimelineAgent.cpp:476 > + for (TaskEvents::iterator i = events.begin(); i != events.end(); ++i) {
We normally use it for iterators.
> Source/WebCore/inspector/InspectorTimelineAgent.cpp:477 > + RefPtr<InspectorObject> task = TimelineRecordFactory::createMessageLoopTaskData(i->startTime, i->endTime);
I think this method could accommodate the entire loop. In either case, though, it will not be a good match of the original purpose of TimelineRecordFactory -- we're not creating a complete record. Guess it may be ok.
> Source/WebCore/inspector/InspectorTimelineAgent.cpp:-464 > - , m_frameInstrumentationSupport(frameInstrumentationSupport)
As above -- though having to pass inspector type to timeline agent is perhaps unfortunate, masking it as a check for client presence looks even worse.
> Source/WebCore/inspector/InspectorTimelineAgent.h:194 > + TaskEvent(double startTime, double endTime) > + : startTime(startTime), endTime(endTime)
Given it's only internal, I think we could as well use std::pair<double, double>
> Source/WebCore/inspector/front-end/TimelinePanel.js:815 > + computeTime: function(position)
I don't think this needs to be in calculator. If it did, it would have to be in _all_ implementations of the calculator. Just use it in place.
> Source/WebCore/inspector/front-end/TimelinePanel.js:1067 > +WebInspector.TimelineMessageLoopModel = function(model)
I wonder why we need a separate model for that? It doesn't do a lot and not shared between views, so perhaps this could be done by the view itself?
> Source/WebCore/inspector/front-end/TimelinePanel.js:1087 > + if (!tasks || tasks.length == 0)
tasks.length == 0 => !tasks.length
> Source/WebCore/inspector/front-end/TimelinePanel.js:1095 > + for (var i = 0; i < tasks.length; ++i) { > + var task = tasks[i]; > + this._tasks.push({ > + startTime: task["startTime"], > + endTime: task["endTime"] > + }); > + }
doesn't this._tasks.push.apply(this._tasks, tasks) just cut it?
> Source/WebCore/inspector/front-end/TimelinePanel.js:1130 > + if (!width) > + return;
when do we hit that?
> Source/WebCore/inspector/front-end/TimelinePanel.js:1133 > + var startTime = this._calculator.computeTime(0) * 1000; > + var endTime = this._calculator.computeTime(width) * 1000;
as above -- let's do this without the calculator.
> Source/WebCore/inspector/front-end/TimelinePanel.js:1139 > + context.clearRect(0, 0, width, height);
this seems redundant, assigning to width/height should take care of this.
> Source/WebCore/inspector/front-end/TimelinePanel.js:1143 > + var delta = endTime - startTime;
we call this timeSpan elsewhere
> Source/WebCore/inspector/front-end/TimelinePanel.js:1144 > + var step = delta / width;
scale?
> Source/WebCore/inspector/front-end/TimelinePanel.js:1150 > + return value < task.endTime ? -1 : 1;
just return value - task.endTime
> Source/WebCore/inspector/front-end/TimelinePanel.js:1153 > + var taskIndex = insertionIndexForObjectInListSortedByFunction(startTime, tasks, compareEndTime);
Aren't tasks already sorted?
> Source/WebCore/inspector/front-end/TimelinePanel.js:1154 > + if (taskIndex == tasks.length) {
== => ===
> Source/WebCore/inspector/front-end/TimelinePanel.js:1155 > + context.clearRect(0, 0, width, height);
redundant
> Source/WebCore/inspector/front-end/TimelinePanel.js:1195 > + pixels[pixelIndex + 2] = 255; > + pixels[pixelIndex + width * 4 + 2] = 255; > + pixels[pixelIndex + width * 8 + 2] = 255; > + if (sum > threshold) { > + pixels[pixelIndex + 3] = 255; > + pixels[pixelIndex + width * 4 + 3] = 128; > + pixels[pixelIndex + width * 8 + 3] = 64; > + } else if (sum > 0) { > + pixels[pixelIndex + 3] = 128; > + pixels[pixelIndex + width * 4 + 3] = 64; > + pixels[pixelIndex + width * 8 + 3] = 32; > + } > + > + pixelIndex += 4; > + } > + context.putImageData(imageData, 0, 0);
This looks a bit cryptic. Any reasons not to use higher-level calls, like lineTo()?
eustas.bug
Comment 4
2012-06-05 09:01:54 PDT
Comment on
attachment 145772
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=145772&action=review
>> Source/WebCore/inspector/InspectorTimelineAgent.cpp:157 >> + m_taskEventStartTime = std::numeric_limits<double>::quiet_NaN(); > > nit: I think we could as well use 0.0, we do this elsewhere.
Done.
>> Source/WebCore/inspector/InspectorTimelineAgent.cpp:172 >> + m_taskEventStartTime = std::numeric_limits<double>::quiet_NaN(); > > ditto.
Done.
>> Source/WebCore/inspector/InspectorTimelineAgent.cpp:193 >> + *result = m_client ? m_client->supportsFrameInstrumentation() : false; > > nit: m_client && m_client->supportsFrameInstrumentation()
Done. Thanks.
>> Source/WebCore/inspector/InspectorTimelineAgent.cpp:462 >> + counters->setNumber("documents", (m_client) ? InspectorCounters::counterValue(InspectorCounters::DocumentCounter) : 0); > > Checking for client presence to determine inspector type looks like a hack here. I think we might as well keep inspector type explicit, though at the moment it will be actually redundant.
Done.
>> Source/WebCore/inspector/InspectorTimelineAgent.cpp:474 >> + m_taskEvents.clear(); > > You can avoid copying a vector here by using Vector::swap()
Done.
>> Source/WebCore/inspector/InspectorTimelineAgent.cpp:476 >> + for (TaskEvents::iterator i = events.begin(); i != events.end(); ++i) { > > We normally use it for iterators.
Done.
>> Source/WebCore/inspector/InspectorTimelineAgent.cpp:477 >> + RefPtr<InspectorObject> task = TimelineRecordFactory::createMessageLoopTaskData(i->startTime, i->endTime); > > I think this method could accommodate the entire loop. In either case, though, it will not be a good match of the original purpose of TimelineRecordFactory -- we're not creating a complete record. Guess it may be ok.
Done.
>> Source/WebCore/inspector/InspectorTimelineAgent.cpp:-464 >> - , m_frameInstrumentationSupport(frameInstrumentationSupport) > > As above -- though having to pass inspector type to timeline agent is perhaps unfortunate, masking it as a check for client presence looks even worse.
Fixed.
>> Source/WebCore/inspector/InspectorTimelineAgent.h:194 >> + : startTime(startTime), endTime(endTime) > > Given it's only internal, I think we could as well use std::pair<double, double>
Done.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1067 >> +WebInspector.TimelineMessageLoopModel = function(model) > > I wonder why we need a separate model for that? It doesn't do a lot and not shared between views, so perhaps this could be done by the view itself?
Combined.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1087 >> + if (!tasks || tasks.length == 0) > > tasks.length == 0 => !tasks.length
Fixed.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1095 >> + } > > doesn't this._tasks.push.apply(this._tasks, tasks) just cut it?
I was just unsure, if it is good to hold InspectorObjects. Fixed.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1130 >> + return; > > when do we hit that?
When user makes inspector window too small. Checked to avoid division by zero.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1139 >> + context.clearRect(0, 0, width, height); > > this seems redundant, assigning to width/height should take care of this.
Done.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1143 >> + var delta = endTime - startTime; > > we call this timeSpan elsewhere
ok
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1144 >> + var step = delta / width; > > scale?
ok
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1150 >> + return value < task.endTime ? -1 : 1; > > just return value - task.endTime
No. We need to avoid returning zero.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1153 >> + var taskIndex = insertionIndexForObjectInListSortedByFunction(startTime, tasks, compareEndTime); > > Aren't tasks already sorted?
They are. That is why binary search works fine =)
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1154 >> + if (taskIndex == tasks.length) { > > == => ===
fixed
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1155 >> + context.clearRect(0, 0, width, height); > > redundant
fixed
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1195 >> + context.putImageData(imageData, 0, 0); > > This looks a bit cryptic. Any reasons not to use higher-level calls, like lineTo()?
Simplified a bit. Pixel manipulation seems to be appropriate for a pixel-sized graphics. I'm OK to rewrite it to higher-level calls, when design is approved.
eustas.bug
Comment 5
2012-06-05 09:03:00 PDT
Created
attachment 145811
[details]
Updated demo screenshot
eustas.bug
Comment 6
2012-06-05 09:06:50 PDT
Created
attachment 145812
[details]
Patch
James Robinson
Comment 7
2012-06-05 11:26:08 PDT
Comment on
attachment 145812
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=145812&action=review
> Source/WebKit/chromium/public/WebDevToolsAgent.h:87 > + // Instrumentation method that marks beginning of task processing
Could you put these before the static functions? Can you have multiple agents in a process (I think yes)? If so, are these calls made on each agent?
> Source/WebKit/chromium/public/WebDevToolsAgentClient.h:65 > + virtual void startMessageLoopMonitoring() { } > + virtual void stopMessageLoopMonitoring() { }
could you put these closer to the WebKitClientMessageLoop code (assuming it's related) and document what these functions do, please?
Andrey Kosyakov
Comment 8
2012-06-05 11:34:20 PDT
Comment on
attachment 145812
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=145812&action=review
> Source/WebCore/inspector/front-end/TimelinePanel.js:1092 > + if (!record || !record["data"])
No need to check for record.
> Source/WebCore/inspector/front-end/TimelinePanel.js:1096 > + if (!tasks || !tasks.length)
task.length check appears redundant now.
Andrey Kosyakov
Comment 9
2012-06-05 11:40:47 PDT
> > when do we hit that? > > When user makes inspector window too small. > Checked to avoid division by zero.
x / 0 === Infinity in JS, so I think it's probably redundant.
> I'm OK to rewrite it to higher-level calls, when design is approved.
Speaking of the appearance, I would vote for moving the line to the lower border of time scale and making it black. Something like 10ms ___ _ _ ___ 20ms ___ _ _ 30ms etc. Alternatively, it may be represented as darker background areas taking full height of time scale. Pavel, WDYT?
eustas.bug
Comment 10
2012-06-06 01:21:05 PDT
Created
attachment 145958
[details]
Yet another message loop bar appearance.
Pavel Feldman
Comment 11
2012-06-06 02:08:33 PDT
> Alternatively, it may be represented as darker background areas taking full height of time scale. > > Pavel, WDYT?
I like the dark background idea. So that there is a sequence of white balloons on dark background. Those balloons represent CPU activity and contain existing bars within. I would even paint main timeline area accordingly (with dark gaps), not sure how feasible that is though. Such not ation would apply to all modes which is a plus.
eustas.bug
Comment 12
2012-06-06 03:17:58 PDT
Comment on
attachment 145812
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=145812&action=review
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1092 >> + if (!record || !record["data"]) > > No need to check for record.
OK
>> Source/WebCore/inspector/front-end/TimelinePanel.js:1096 >> + if (!tasks || !tasks.length) > > task.length check appears redundant now.
Removed
>> Source/WebKit/chromium/public/WebDevToolsAgent.h:87 >> + // Instrumentation method that marks beginning of task processing > > Could you put these before the static functions? > > Can you have multiple agents in a process (I think yes)? If so, are these calls made on each agent?
Done. I've attached 3 diagrams that demonstrate that there is an implicit 1-to-1 relationship between WebDevToolsAgent and WebDevToolsAgentClient. So the contract for these new methods is: WebDevToolsAgentClient is controlling the notifications subscription for corresponding WebDevToolsAgent. Some commentaries on diagrams: 1) WebView has an implicit contract to hold both WebDevToolsAgent and WebDevToolsAgentClient references. 2) Implementation of WebDevToolsAgent holds reference to WebDevToolsAgentClient. 3) Implicit contract is turned to explicit in chromium: WebDevToolsAgentClient implementation has access to corresponding WebDevToolsAgent.
>> Source/WebKit/chromium/public/WebDevToolsAgentClient.h:65 >> + virtual void stopMessageLoopMonitoring() { } > > could you put these closer to the WebKitClientMessageLoop code (assuming it's related) and document what these functions do, please?
Done.
eustas.bug
Comment 13
2012-06-06 03:19:22 PDT
Created
attachment 145975
[details]
Diagram1: WebView has an implicit contract to hold both WebDevToolsAgent and WebDevToolsAgentClient references
eustas.bug
Comment 14
2012-06-06 03:20:42 PDT
Created
attachment 145976
[details]
Diagram 2: Implementation of WebDevToolsAgent holds reference to WebDevToolsAgentClient
eustas.bug
Comment 15
2012-06-06 03:22:19 PDT
Created
attachment 145977
[details]
Diagram 3: Implicit contract is turned to explicit in chromium: WebDevToolsAgentClient implementation has access to corresponding WebDevToolsAgent.
eustas.bug
Comment 16
2012-06-06 03:30:53 PDT
Created
attachment 145980
[details]
Patch
eustas.bug
Comment 17
2012-06-06 07:32:05 PDT
Created
attachment 146022
[details]
UI: take 4
eustas.bug
Comment 18
2012-06-06 07:32:44 PDT
Created
attachment 146023
[details]
UI: take 5
Andrey Kosyakov
Comment 19
2012-06-06 07:34:27 PDT
(In reply to
comment #18
)
> UI: take 5
take 4 is my favorite so far. How would it look if we're zoomed in close enough to see individual events?
eustas.bug
Comment 20
2012-06-06 07:37:48 PDT
Created
attachment 146025
[details]
UI: take 5, close-up
eustas.bug
Comment 21
2012-06-06 07:55:00 PDT
Created
attachment 146033
[details]
UI: take 6
eustas.bug
Comment 22
2012-06-06 07:55:39 PDT
Created
attachment 146034
[details]
UI: take 6, close-up
eustas.bug
Comment 23
2012-06-06 08:10:30 PDT
Created
attachment 146035
[details]
UI: take 6 in light-blue
eustas.bug
Comment 24
2012-06-06 08:11:16 PDT
Created
attachment 146036
[details]
UI: take 6 in light-blue, close-up
Pavel Feldman
Comment 25
2012-06-06 09:03:20 PDT
Light blue is definitely wrong. It is also not clear whether gray area is "busy" or "idle" time. Even when I know that it is one of the two, I can't decide which one it is. We know for sure that idle time can't intersect with any of the bars. From the mocks,
https://bug-88325-attachments.webkit.org/attachment.cgi?id=146025
seems most reasonable, but I would 1) draw a solid gray spanning line above the chunks ans 2) remove the garbage dots that appear on that bar.
eustas.bug
Comment 26
2012-06-07 00:52:52 PDT
Created
attachment 146223
[details]
UI: take 7: something between 4 and 5 with removed garbage dots
eustas.bug
Comment 27
2012-06-07 00:53:37 PDT
Created
attachment 146224
[details]
UI: take 7, close-up
Timothy Hatcher
Comment 28
2012-06-07 10:27:44 PDT
All I see is a trail of pixel poop. How is the user suppose to comprehend what this is?
Nat Duca
Comment 29
2012-06-07 10:39:01 PDT
(In reply to
comment #25
)
> From the mocks,
https://bug-88325-attachments.webkit.org/attachment.cgi?id=146025
seems most reasonable, but I would 1) draw a solid gray spanning line above the chunks ans 2) remove the garbage dots that appear on that bar.
So... crazy question man asks "why not just put an event into the lower half of the timeline?" Assume this for a moment: * real_events= array of [start, finish, name] times * message_loop_events = array of [start,finish] times Roughly, go through each real event. For each real event, find out what message_loop event it is inside. If the real event is more than 75% of the message loop event, delete the message loop event. Otherwise, create two "unknown work" events that cover the non-instrumented time and add them to the timeline. E.g.: real_events= [0,9,x], [20,22,y] message_loop_events = [0,10], [20, 30], [35,40] Result: timeline_events= [0,9,x],[20,22,y],[22,30,unknown],[35,40,unknown] And, don't show anything up in the top graph.
James Robinson
Comment 30
2012-06-07 12:28:34 PDT
Could you split the code changes out to a separate bug from the UI discussion? I have more feedback to provide on some of the wiring but not so much about the UI.
eustas.bug
Comment 31
2012-06-08 02:27:07 PDT
(In reply to
comment #30
)
> Could you split the code changes out to a separate bug from the UI discussion? I have more feedback to provide on some of the wiring but not so much about the UI.
Done. See:
https://bugs.webkit.org/show_bug.cgi?id=88639
eustas.bug
Comment 32
2012-06-08 07:27:11 PDT
Created
attachment 146562
[details]
Screenshot: close view on "unknown" tasks
eustas.bug
Comment 33
2012-06-08 07:28:01 PDT
Created
attachment 146563
[details]
Screenshot: "unknown" tasks pollute timeline
eustas.bug
Comment 34
2012-06-08 07:28:57 PDT
Created
attachment 146564
[details]
Screenshot: same data, with switched off "unknown" category
eustas.bug
Comment 35
2012-06-08 07:35:43 PDT
(In reply to
comment #29
)
> (In reply to
comment #25
) > > From the mocks,
https://bug-88325-attachments.webkit.org/attachment.cgi?id=146025
seems most reasonable, but I would 1) draw a solid gray spanning line above the chunks ans 2) remove the garbage dots that appear on that bar. > > So... crazy question man asks "why not just put an event into the lower half of the timeline?" > > Assume this for a moment: > * real_events= array of [start, finish, name] times > * message_loop_events = array of [start,finish] times > > Roughly, go through each real event. For each real event, find out what message_loop event it is inside. If the real event is more than 75% of the message loop event, delete the message loop event. Otherwise, create two "unknown work" events that cover the non-instrumented time and add them to the timeline. > > E.g.: > real_events= [0,9,x], [20,22,y] > message_loop_events = [0,10], [20, 30], [35,40] > > Result: > timeline_events= [0,9,x],[20,22,y],[22,30,unknown],[35,40,unknown] > > And, don't show anything up in the top graph.
Done. But we have a problem here: a lot of small "unknown" tasks pollute timeline (see screenshots). They appear, because these message loops have "content" represented on timeline, that way "unknown" time is just 100%. We can't just filter them out, because we may get to situation, when reasonable amount of CPU time is spent in a ton of tiny message loops. The only solution I see - turn-off "unknown" category by default.
Nat Duca
Comment 36
2012-06-08 12:09:53 PDT
> We can't just filter them out, because we may get to situation, when reasonable amount of CPU time is spent in a ton of tiny message loops.
Understood. I wonder if you can coalesce... e.g. "[0,1][1.05->2]" --> "[0,2]"?
> The only solution I see - turn-off "unknown" category by default.
That seems okay to me. Or, if timeline could show more than 1 event on a row, that would work too ... part of your issue is that timeline is very inefficient in its use of vertical space.
Pavel Feldman
Comment 37
2012-06-14 01:53:08 PDT
Comment on
attachment 145980
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=145980&action=review
Clearing r? - it has been partially landed.
> Source/WebCore/ChangeLog:6 > + Reviewed by NOBODY (OOPS!).
Please explain what is happening in the change.
eustas.bug
Comment 38
2012-06-15 10:21:26 PDT
Created
attachment 147848
[details]
Patch
eustas.bug
Comment 39
2012-06-15 10:22:58 PDT
(In reply to
comment #38
)
> Created an attachment (id=147848) [details] > Patch
A partial patch: this functionality should be disabled by default, and enabled with "experiment" settings checkbox.
eustas.bug
Comment 40
2012-06-15 10:23:35 PDT
Created
attachment 147849
[details]
Demo screenshot
eustas.bug
Comment 41
2012-06-18 14:54:48 PDT
Created
attachment 148176
[details]
Patch
eustas.bug
Comment 42
2012-06-29 03:00:56 PDT
Created
attachment 150126
[details]
Patch
eustas.bug
Comment 43
2012-07-03 09:09:30 PDT
Created
attachment 150623
[details]
Patch Rebased
Andrey Kosyakov
Comment 44
2012-07-03 10:20:06 PDT
Comment on
attachment 150623
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=150623&action=review
> Source/WebCore/inspector/front-end/Settings.js:190 > + this.mainThreadMonitoring = this._createExperiment("mainThreadMonitoring", "Main thread monitoring");
"Show CPU activity in Timeline"?
> Source/WebCore/inspector/front-end/TimelinePanel.js:511 > + this._mainThreadTasks.push({startTime: record.startTime / 1000, endTime: record.endTime / 1000});
Please use WebInspector.TimelineModel.{start,end}TimeInSeconds()
> Source/WebCore/inspector/front-end/TimelinePanel.js:769 > + _refreshCpuBars: function()
Here and below, Cpu => CPU
> Source/WebCore/inspector/front-end/TimelinePanel.js:773 > + var startTime = this._calculator.computeTime(0); > + var endTime = this._calculator.computeTime(width);
this._overviewPane.window{Start,End}Time()?
> Source/WebCore/inspector/front-end/TimelinePanel.js:801 > + var left = Math.max(0, this._calculator.computePosition(task.startTime) + WebInspector.TimelinePanel.barOffset); > + var right = Math.min(width, this._calculator.computePosition(task.endTime) + WebInspector.TimelineCalculator._minWidth + WebInspector.TimelinePanel.barOffset);
barOffset is apparently only used here, so please define as a local const.
> Source/WebCore/inspector/front-end/TimelinePanel.js:809 > + } else { > + lastElement.style.width = (lastRight - lastLeft) + "px"; > + }
We don't use else after flow control statements (e.g. continue). Also, curly braces are redundant.
> Source/WebCore/inspector/front-end/TimelinePanel.js:833 > + _enableMainThreadMonitoringExperiment: function()
So you're looking to rename this method once it graduates out of experimental?
> Source/WebCore/inspector/front-end/TimelinePanel.js:835 > + this._headerLineCount = 2;
++this._headerLineCount?
> Source/WebCore/inspector/front-end/TimelinePanel.js:840 > + cpuBarsLabel.appendChild(document.createTextNode("CPU"));
cpuBarsLabel.textContent = ...? Also, please use UIString for that.
> Source/WebCore/inspector/front-end/TimelinePanel.js:845 > + container.style.height = headerHeight + WebInspector.TimelinePanel.headerMargin + "px"; > + this._timelineGrid.dividersLabelBarElement.style.height = headerHeight + WebInspector.TimelinePanel.headerMargin + "px";
headerMargin is apparently only used here -- please define it as a local const.
> Source/WebCore/inspector/front-end/TimelinePanel.js:846 > + this._itemsGraphsElement.style.top = headerHeight + WebInspector.TimelinePanel.headerBorderWidth + "px";
ditto for headerBorderWidth
> Source/WebCore/inspector/front-end/TimelinePanel.js:951 > + computeTime: function(position)
I think this is confusing -- we have a few implementation of calculator, and you're just adding to one, and only use this method in one place.
> Source/WebCore/inspector/front-end/TimelinePanel.js:999 > + this.clientWidth = clientWidth;
This also looks like abuse of calculator class.
> Source/WebCore/inspector/front-end/timelinePanel.css:632 > + font-family: monospace;
Consider using monospace class instead.
> Source/WebCore/inspector/front-end/timelinePanel.css:634 > + font-size: 9px; > + line-height: 7px;
line-height < font-size looks fishy. is this intended?
> Source/WebCore/inspector/front-end/timelinePanel.css:640 > + z-index: 350;
Is this necessary?
eustas.bug
Comment 45
2012-07-04 00:27:48 PDT
Comment on
attachment 150623
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=150623&action=review
>> Source/WebCore/inspector/front-end/Settings.js:190 >> + this.mainThreadMonitoring = this._createExperiment("mainThreadMonitoring", "Main thread monitoring"); > > "Show CPU activity in Timeline"?
OK
>> Source/WebCore/inspector/front-end/TimelinePanel.js:511 >> + this._mainThreadTasks.push({startTime: record.startTime / 1000, endTime: record.endTime / 1000}); > > Please use WebInspector.TimelineModel.{start,end}TimeInSeconds()
Sure.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:769 >> + _refreshCpuBars: function() > > Here and below, Cpu => CPU
Done (for acronyms in the middle of name).
>> Source/WebCore/inspector/front-end/TimelinePanel.js:773 >> + var endTime = this._calculator.computeTime(width); > > this._overviewPane.window{Start,End}Time()?
No, because: this._overviewPane.windowStartTime() == this._calculator.computeTime(this._expandOffset) != this._calculator.computeTime(0)
>> Source/WebCore/inspector/front-end/TimelinePanel.js:801 >> + var right = Math.min(width, this._calculator.computePosition(task.endTime) + WebInspector.TimelineCalculator._minWidth + WebInspector.TimelinePanel.barOffset); > > barOffset is apparently only used here, so please define as a local const.
OK.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:809 >> + } > > We don't use else after flow control statements (e.g. continue). Also, curly braces are redundant.
Fixed.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:833 >> + _enableMainThreadMonitoringExperiment: function() > > So you're looking to rename this method once it graduates out of experimental?
Fixed.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:835 >> + this._headerLineCount = 2; > > ++this._headerLineCount?
OK.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:840 >> + cpuBarsLabel.appendChild(document.createTextNode("CPU")); > > cpuBarsLabel.textContent = ...? Also, please use UIString for that.
Done.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:845 >> + this._timelineGrid.dividersLabelBarElement.style.height = headerHeight + WebInspector.TimelinePanel.headerMargin + "px"; > > headerMargin is apparently only used here -- please define it as a local const.
Fixed.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:846 >> + this._itemsGraphsElement.style.top = headerHeight + WebInspector.TimelinePanel.headerBorderWidth + "px"; > > ditto for headerBorderWidth
Fixed.
>> Source/WebCore/inspector/front-end/TimelinePanel.js:951 >> + computeTime: function(position) > > I think this is confusing -- we have a few implementation of calculator, and you're just adding to one, and only use this method in one place.
Why don't we have common interface / super type then? As I see, all calculators have methods that are used for specific purposes.
>> Source/WebCore/inspector/front-end/timelinePanel.css:632 >> + font-family: monospace; > > Consider using monospace class instead.
No. monospace overrides font size and definitely wins in selector matching.
>> Source/WebCore/inspector/front-end/timelinePanel.css:634 >> + line-height: 7px; > > line-height < font-size looks fishy. is this intended?
Sure. font-size = |font ascending| + |font descending| > |font cap height| Actually text is 5px height + 2 * 1px padding = 7px line height.
>> Source/WebCore/inspector/front-end/timelinePanel.css:640 >> + z-index: 350; > > Is this necessary?
Otherwise it will be hidden by bars.
eustas.bug
Comment 46
2012-07-04 01:01:50 PDT
Created
attachment 150731
[details]
Patch
Andrey Kosyakov
Comment 47
2012-07-04 02:58:19 PDT
Comment on
attachment 150731
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=150731&action=review
> Source/WebCore/inspector/front-end/TimelinePanel.js:513 > + if (record.type === WebInspector.TimelineModel.RecordType.Program) > + this._mainThreadTasks.push({ > + startTime: WebInspector.TimelineModel.startTimeInSeconds(record), > + endTime: WebInspector.TimelineModel.endTimeInSeconds(record) > + });
This spans multiple lines, so needs {} around the statement.
> Source/WebCore/inspector/front-end/TimelinePanel.js:777 > + var startTime = this._calculator.computeTime(0); > + var endTime = this._calculator.computeTime(width);
thought we agreed that we should not put additional methods on the calculator.
eustas.bug
Comment 48
2012-07-04 02:58:47 PDT
Created
attachment 150749
[details]
Patch
eustas.bug
Comment 49
2012-07-04 03:06:17 PDT
Created
attachment 150751
[details]
Patch
eustas.bug
Comment 50
2012-07-04 03:07:22 PDT
Comment on
attachment 150731
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=150731&action=review
>> Source/WebCore/inspector/front-end/TimelinePanel.js:513 >> + }); > > This spans multiple lines, so needs {} around the statement.
Fixed
>> Source/WebCore/inspector/front-end/TimelinePanel.js:777 >> + var endTime = this._calculator.computeTime(width); > > thought we agreed that we should not put additional methods on the calculator.
Fixed.
eustas.bug
Comment 51
2012-07-11 05:53:34 PDT
Created
attachment 151692
[details]
Patch
eustas.bug
Comment 52
2012-07-12 02:10:48 PDT
Created
attachment 151890
[details]
Patch fixed-frame-dividers
Andrey Kosyakov
Comment 53
2012-07-12 05:04:48 PDT
Comment on
attachment 151890
[details]
Patch LGTM
Pavel Feldman
Comment 54
2012-07-12 08:18:58 PDT
Comment on
attachment 151890
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=151890&action=review
> Source/WebCore/inspector/front-end/TimelinePanel.js:375 > + /** @const */ var frameContainerBorderWidth = 1;
/** @const */ const frameContainerBorderWidth = 1;
> Source/WebCore/inspector/front-end/TimelinePanel.js:812 > + if (Math.ceil(lastRight) >= Math.floor(left)) {
We may end up with as many chunks as pixels. You should introduce the minimal chunk width of 3px and make sure that gaps are longer than 3px as well. Or alternatively you could render it all using canvas!
eustas.bug
Comment 55
2012-07-12 22:16:27 PDT
Comment on
attachment 151890
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=151890&action=review
>> Source/WebCore/inspector/front-end/TimelinePanel.js:812 >> + if (Math.ceil(lastRight) >= Math.floor(left)) { > > We may end up with as many chunks as pixels. You should introduce the minimal chunk width of 3px and make sure that gaps are longer than 3px as well. Or alternatively you could render it all using canvas!
Actually: 1) this line ensures that we may end up with half that number, because we create new chunk only when ceil(current) < floor(next), so there more than one pixel between chunks; 2) previous line (right =...) mimics main timeline bars appearance, so minimal width is 3 px. As a consequence, at most pixelWidth / 4 chunks will be displayed.
Pavel Feldman
Comment 56
2012-07-12 23:21:46 PDT
> Actually: > 1) this line ensures that we may end up with half that number, because we create new chunk only when ceil(current) < floor(next), so there more than one pixel between chunks;
In case current and next are integers, and current is 3 and next is 4, we will hit a chunk per pixel. Event half of the pixels is too much (1400 chunks on retina display?). I think I am just looking for the ways of making it more obvious from the code. Today, I need to think for quite some time before I figure out what the actual threshold is. Having it stated in a declarative manner would be great.
> 2) previous line (right =...) mimics main timeline bars appearance, so minimal width is 3 px. > > As a consequence, at most pixelWidth / 4 chunks will be displayed.
Exactly, I don't want it to be a consequence, but rather a clearly stated fact in the code.
eustas.bug
Comment 57
2012-07-13 03:04:32 PDT
(In reply to
comment #56
)
> > Actually: > > 1) this line ensures that we may end up with half that number, because we create new chunk only when ceil(current) < floor(next), so there more than one pixel between chunks; > > In case current and next are integers, and current is 3 and next is 4, we will hit a chunk per pixel. Event half of the pixels is too much (1400 chunks on retina display?). I think I am just looking for the ways of making it more obvious from the code. Today, I need to think for quite some time before I figure out what the actual threshold is. Having it stated in a declarative manner would be great. > > > 2) previous line (right =...) mimics main timeline bars appearance, so minimal width is 3 px. > > > > As a consequence, at most pixelWidth / 4 chunks will be displayed. > > Exactly, I don't want it to be a consequence, but rather a clearly stated fact in the code.
On retina display we will have the same number of "pixels" -> no more than 320 chunks. Extracted explicit gap constant, PTAL.
eustas.bug
Comment 58
2012-07-13 03:06:34 PDT
Created
attachment 152202
[details]
Patch
eustas.bug
Comment 59
2012-07-13 04:23:21 PDT
Created
attachment 152216
[details]
Patch fixed-nits
Andrey Kosyakov
Comment 60
2012-07-16 01:55:25 PDT
Committed
r122706
: <
http://trac.webkit.org/changeset/122706
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug