Ignore:
Timestamp:
Apr 23, 2009, 8:47:50 PM (16 years ago)
Author:
[email protected]
Message:

BUG 24604: WebKit profiler reports incorrect total times

JavaScriptCore:

2009-04-23 Francisco Tolmasky <[email protected]>

BUG 24604: WebKit profiler reports incorrect total times
<https://bugs.webkit.org/show_bug.cgi?id=24604>

Reviewed by Timothy Hatcher and Kevin McCullough.

  • JavaScriptCore.exp:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • profiler/CallIdentifier.h: (JSC::CallIdentifier::Hash::hash): (JSC::CallIdentifier::Hash::equal): (JSC::CallIdentifier::hash): (WTF::):
  • profiler/HeavyProfile.cpp: Removed.
  • profiler/HeavyProfile.h: Removed.
  • profiler/Profile.cpp: No more need for TreeProfile/HeavyProfile (JSC::Profile::create):
  • profiler/Profile.h:
  • profiler/ProfileNode.cpp:
  • profiler/ProfileNode.h:
  • profiler/TreeProfile.cpp: Removed.
  • profiler/TreeProfile.h: Removed.

WebCore:

2009-04-23 Francisco Tolmasky <[email protected]>

BUG 24604: WebKit profiler reports incorrect total times
<https://bugs.webkit.org/show_bug.cgi?id=24604>

Reviewed by Timothy Hatcher and Kevin McCullough.

Made it so that most of the profiler functions now match the behavior of Shark. Most notably, in the
heavy view, child nodes now represent the statistics of the root node. Each root node of heavy view
displays flattened statistics for a particular function that ran during the profile, and each child
of these root nodes represents a callpath that lead to it. Thus, the statistics for each of these child
nodes should show how much of the root nodes values came from it. For example, if you had the following to
stacks take place during the profile:

A ->calls 1 times-> B ->calls 2 times-> C
D ->calls 4 times-> C

The tree for the C root node would look like this:

C -> B -> A

-> D

The number of calls values would look like this:

C (6) -> B (2) -> A(2)

-> D (4)

What this means is that "2 of the total 6 C calls came from B", "2 of the total C calls came from A", and
"4 of the total C calls came from D". Notice that the "A ->calls 2 time->" is completely ignored. This becomes
particularly tricky during recursive calls, because each child note can represent multiple possible paths. This
is the reason that we would get things like 40000% previously with recursion.

This is also the way gprof works, and as close as we can get to Shark's behavior (Shark is not instrumented so it
can't know exactly how many calls came from where, etc).

  • English.lproj/localizedStrings.js: Added "Average" for average times in the profile.
  • inspector/JavaScriptProfile.cpp: (WebCore::ProfileClass):
  • inspector/JavaScriptProfileNode.cpp: (WebCore::getParent): (WebCore::getHead): (WebCore::getCallUID): (WebCore::ProfileNodeClass):
  • inspector/front-end/BottomUpProfileDataGridTree.js: Added. (WebInspector.BottomUpProfileDataGridTree): (WebInspector.BottomUpProfileDataGridTree.prototype.focus): (WebInspector.BottomUpProfileDataGridNode): (WebInspector.BottomUpProfileDataGridNode.prototype._takePropertiesFromProfileDataGridNode): (WebInspector.BottomUpProfileDataGridNode.prototype._keepOnlyChild): (WebInspector.BottomUpProfileDataGridNode.prototype._exclude): (WebInspector.BottomUpProfileDataGridNode.prototype._merge): (WebInspector.BottomUpProfileDataGridNode.prototype._populate):
  • inspector/front-end/DataGrid.js: (WebInspector.DataGrid.prototype.insertChild): (WebInspector.DataGrid.prototype.removeChild): (WebInspector.DataGrid.prototype.removeChildren): (WebInspector.DataGridNode.prototype.set hasChildren): (WebInspector.DataGridNode.prototype.get hasChildren):
  • inspector/front-end/ProfileDataGridTree.js: Added. (WebInspector.ProfileDataGridNode): (WebInspector.ProfileDataGridNode.prototype.get data.formatMilliseconds): (WebInspector.ProfileDataGridNode.prototype.get data): (WebInspector.ProfileDataGridNode.prototype.createCell): (WebInspector.ProfileDataGridNode.prototype.select): (WebInspector.ProfileDataGridNode.prototype.deselect): (WebInspector.ProfileDataGridNode.prototype.expand): (WebInspector.ProfileDataGridNode.prototype.insertChild): (WebInspector.ProfileDataGridNode.prototype.removeChild): (WebInspector.ProfileDataGridNode.prototype.removeChildren): (WebInspector.ProfileDataGridNode.prototype.findChild): (WebInspector.ProfileDataGridNode.prototype.get averageTime): (WebInspector.ProfileDataGridNode.prototype.get averagePercent): (WebInspector.ProfileDataGridNode.prototype.get selfPercent): (WebInspector.ProfileDataGridNode.prototype.get totalPercent): (WebInspector.ProfileDataGridNode.prototype._save): (WebInspector.ProfileDataGridNode.prototype._restore): (WebInspector.ProfileDataGridNode.prototype._merge): (WebInspector.ProfileDataGridTree): (WebInspector.ProfileDataGridTree.prototype.get expanded): (WebInspector.ProfileDataGridTree.prototype.appendChild): (WebInspector.ProfileDataGridTree.prototype.insertChild): (WebInspector.ProfileDataGridTree.prototype.removeChildren): (WebInspector.ProfileDataGridTree.prototype.findChild.WebInspector.ProfileDataGridNode.prototype.findChild.sort.WebInspector.ProfileDataGridNode.prototype.sort._save): (WebInspector.ProfileDataGridTree.propertyComparator.comparator): (WebInspector.ProfileDataGridTree.propertyComparator.else.comparator): (WebInspector.ProfileDataGridTree.propertyComparator):
  • inspector/front-end/ProfileView.js: (WebInspector.ProfileView): (WebInspector.ProfileView.prototype.set profile): (WebInspector.ProfileView.prototype.get bottomUpProfileDataGridTree): (WebInspector.ProfileView.prototype.get topDownProfileDataGridTree): (WebInspector.ProfileView.prototype.get currentTree): (WebInspector.ProfileView.prototype.set currentTree): (WebInspector.ProfileView.prototype.get topDownTree): (WebInspector.ProfileView.prototype.get bottomUpTree): (WebInspector.ProfileView.prototype.refresh): (WebInspector.ProfileView.prototype.refreshVisibleData): (WebInspector.ProfileView.prototype.refreshShowAsPercents): (WebInspector.ProfileView.prototype.performSearch.matchesQuery): (WebInspector.ProfileView.prototype.performSearch): (WebInspector.ProfileView.prototype._changeView): (WebInspector.ProfileView.prototype._focusClicked): (WebInspector.ProfileView.prototype._excludeClicked): (WebInspector.ProfileView.prototype._resetClicked): (WebInspector.ProfileView.prototype._sortProfile):
  • inspector/front-end/ProfilesPanel.js: (WebInspector.ProfilesPanel.prototype.showProfile): (WebInspector.ProfilesPanel.prototype.showView): (WebInspector.ProfilesPanel.prototype.searchMatchFound):
  • inspector/front-end/TopDownProfileDataGridTree.js: Added. (WebInspector.TopDownProfileDataGridNode): (WebInspector.TopDownProfileDataGridNode.prototype._populate): (WebInspector.TopDownProfileDataGridNode.prototype._exclude): (WebInspector.TopDownProfileDataGridTree): (WebInspector.TopDownProfileDataGridTree.prototype.focus): (WebInspector.TopDownProfileDataGridTree.prototype.exclude):
  • inspector/front-end/WebKit.qrc:
  • inspector/front-end/inspector.css:
  • inspector/front-end/inspector.html:

LayoutTests:

2009-04-23 Francisco Tolmasky <[email protected]>

BUG 24604: WebKit profiler reports incorrect total times
<https://bugs.webkit.org/show_bug.cgi?id=24604>

Reviewed by Timothy Hatcher and Kevin McCullough.

Changed profile.treeProfile to just profile, since these aren't generated in C++ anymore.
Removed heavy-view test since heavy-view isn't an actual tree that is generated in C++ land anymore,
but rather just a different display of the normal treeProfile in the JS data grid.

  • fast/profiler/heavy-view-expected.txt: Removed.
  • fast/profiler/heavy-view.html: Removed.
  • fast/profiler/resources/profiler-test-JS-resources.js: profiles[i].treeProfile -> profiles[i].treeProfile (printProfilesDataWithoutTime):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/inspector/JavaScriptProfileNode.cpp

    r39670 r42808  
    4747
    4848static ProfileNodeMap& profileNodeCache()
    49 { 
     49{
    5050    DEFINE_STATIC_LOCAL(ProfileNodeMap, staticProfileNodes, ());
    5151    return staticProfileNodes;
     
    163163
    164164    JSRetainPtr<JSStringRef> pushString(Adopt, JSStringCreateWithUTF8CString("push"));
    165    
     165
    166166    JSValueRef pushProperty = JSObjectGetProperty(ctx, result, pushString.get(), exception);
    167167    if (exception && *exception)
     
    182182}
    183183
     184static JSValueRef getParent(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
     185{
     186    JSC::JSLock lock(false);
     187
     188    if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
     189        return JSValueMakeUndefined(ctx);
     190
     191    ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject));
     192    return toRef(toJS(toJS(ctx), profileNode->parent())
     193    );
     194}
     195
     196static JSValueRef getHead(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
     197{
     198    JSC::JSLock lock(false);
     199
     200    if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
     201        return JSValueMakeUndefined(ctx);
     202
     203    ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject));
     204    return toRef(toJS(toJS(ctx), profileNode->head()));
     205}
     206
    184207static JSValueRef getVisible(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
    185208{
     
    191214    ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject));
    192215    return JSValueMakeBoolean(ctx, profileNode->visible());
     216}
     217
     218static JSValueRef getCallUID(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*)
     219{
     220    JSC::JSLock lock(false);
     221
     222    if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass()))
     223        return JSValueMakeUndefined(ctx);
     224
     225    ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject));
     226    return JSValueMakeNumber(ctx, profileNode->callIdentifier().hash());
    193227}
    194228
     
    212246        { "numberOfCalls", getNumberOfCalls, 0, kJSPropertyAttributeNone },
    213247        { "children", getChildren, 0, kJSPropertyAttributeNone },
     248        { "parent", getParent, 0, kJSPropertyAttributeNone },
     249        { "head", getHead, 0, kJSClassAttributeNone },
    214250        { "visible", getVisible, 0, kJSPropertyAttributeNone },
     251        { "callUID", getCallUID, 0, kJSPropertyAttributeNone },
    215252        { 0, 0, 0, 0 }
    216253    };
Note: See TracChangeset for help on using the changeset viewer.