Title: [138004] trunk/Source/WebCore
Revision
138004
Author
[email protected]
Date
2012-12-18 03:43:35 -0800 (Tue, 18 Dec 2012)

Log Message

Web Inspector: Calculate "idle" time for CPU profiles.
https://bugs.webkit.org/show_bug.cgi?id=103120

Patch by Eugene Klyuchnikov <[email protected]> on 2012-12-18
Reviewed by Pavel Feldman.

CPU profiles contain a very confusing "(program)" item.
It is time when there is no JS stack.
That could be either idle time, or time when browser is doing something.

To split "(program)" item to idle and really program time we are to
calculate idle time during profiling.

* bindings/js/ScriptProfile.cpp: Added "idleTime" getter.
* bindings/js/ScriptProfile.h: Ditto.
* bindings/js/ScriptProfiler.h:
Added getter of thread-local map of currently written profiles.
* bindings/v8/ScriptProfile.cpp: Added "idleTime" getter.
* bindings/v8/ScriptProfile.h: Ditto.
* bindings/v8/ScriptProfiler.cpp:
(WebCore::ScriptProfiler::start): Put profile name to map.
(WebCore::ScriptProfiler::stop): Remove profile name from map;
pass idleTime to profile constructor.
* bindings/v8/ScriptProfiler.h:
Added getter of thread-local map of currently written profiles.
* inspector/Inspector.json: Added "idleTime" field to profile.
* inspector/InspectorController.cpp: Pass hooks to profiler agent.
* inspector/InspectorProfilerAgent.cpp:
Add idle time to currently written profiles.
* inspector/InspectorProfilerAgent.h:
Added member to hold reference to map of currently written profiles.
* inspector/InspectorTimelineAgent.h:
Cleanup.
* inspector/ScriptProfile.idl:
Add "idleTime" member.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (138003 => 138004)


--- trunk/Source/WebCore/ChangeLog	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/ChangeLog	2012-12-18 11:43:35 UTC (rev 138004)
@@ -1,3 +1,40 @@
+2012-12-18  Eugene Klyuchnikov  <[email protected]>
+
+        Web Inspector: Calculate "idle" time for CPU profiles.
+        https://bugs.webkit.org/show_bug.cgi?id=103120
+
+        Reviewed by Pavel Feldman.
+
+        CPU profiles contain a very confusing "(program)" item.
+        It is time when there is no JS stack.
+        That could be either idle time, or time when browser is doing something.
+
+        To split "(program)" item to idle and really program time we are to
+        calculate idle time during profiling.
+
+        * bindings/js/ScriptProfile.cpp: Added "idleTime" getter.
+        * bindings/js/ScriptProfile.h: Ditto.
+        * bindings/js/ScriptProfiler.h:
+        Added getter of thread-local map of currently written profiles.
+        * bindings/v8/ScriptProfile.cpp: Added "idleTime" getter.
+        * bindings/v8/ScriptProfile.h: Ditto.
+        * bindings/v8/ScriptProfiler.cpp:
+        (WebCore::ScriptProfiler::start): Put profile name to map.
+        (WebCore::ScriptProfiler::stop): Remove profile name from map;
+        pass idleTime to profile constructor.
+        * bindings/v8/ScriptProfiler.h:
+        Added getter of thread-local map of currently written profiles.
+        * inspector/Inspector.json: Added "idleTime" field to profile.
+        * inspector/InspectorController.cpp: Pass hooks to profiler agent.
+        * inspector/InspectorProfilerAgent.cpp:
+        Add idle time to currently written profiles.
+        * inspector/InspectorProfilerAgent.h:
+        Added member to hold reference to map of currently written profiles.
+        * inspector/InspectorTimelineAgent.h:
+        Cleanup.
+        * inspector/ScriptProfile.idl:
+        Add "idleTime" member.
+
 2012-12-17  Yury Semikhatsky  <[email protected]>
 
         Web Inspector: MediaQueryList listener silently catches errors

Modified: trunk/Source/WebCore/bindings/js/ScriptProfile.cpp (138003 => 138004)


--- trunk/Source/WebCore/bindings/js/ScriptProfile.cpp	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/bindings/js/ScriptProfile.cpp	2012-12-18 11:43:35 UTC (rev 138004)
@@ -75,6 +75,11 @@
     return 0;
 }
 
+double ScriptProfile::idleTime() const
+{
+    return 0.0;
+}
+
 #if ENABLE(INSPECTOR)
 static PassRefPtr<InspectorObject> buildInspectorObjectFor(const JSC::ProfileNode* node)
 {

Modified: trunk/Source/WebCore/bindings/js/ScriptProfile.h (138003 => 138004)


--- trunk/Source/WebCore/bindings/js/ScriptProfile.h	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/bindings/js/ScriptProfile.h	2012-12-18 11:43:35 UTC (rev 138004)
@@ -51,6 +51,7 @@
     unsigned int uid() const;
     ScriptProfileNode* head() const;
     PassRefPtr<ScriptProfileNode> bottomUpHead() const;
+    double idleTime() const;
 
 #if ENABLE(INSPECTOR)
     PassRefPtr<InspectorObject> buildInspectorObjectForHead() const;

Modified: trunk/Source/WebCore/bindings/js/ScriptProfiler.h (138003 => 138004)


--- trunk/Source/WebCore/bindings/js/ScriptProfiler.h	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/bindings/js/ScriptProfiler.h	2012-12-18 11:43:35 UTC (rev 138004)
@@ -80,6 +80,7 @@
     static void visitExternalArrays(ExternalArrayVisitor*) { }
     static void collectBindingMemoryInfo(MemoryInstrumentation*) { }
     static size_t profilerSnapshotsSize() { return 0; }
+    static HashMap<String, double>* currentProfileNameIdleTimeMap() { return 0; }
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/ScriptProfile.cpp (138003 => 138004)


--- trunk/Source/WebCore/bindings/v8/ScriptProfile.cpp	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfile.cpp	2012-12-18 11:43:35 UTC (rev 138004)
@@ -65,6 +65,11 @@
     return ScriptProfileNode::create(m_profile->GetBottomUpRoot());
 }
 
+double ScriptProfile::idleTime() const
+{
+    return m_idleTime;
+}
+
 #if ENABLE(INSPECTOR)
 static PassRefPtr<InspectorObject> buildInspectorObjectFor(const v8::CpuProfileNode* node)
 {

Modified: trunk/Source/WebCore/bindings/v8/ScriptProfile.h (138003 => 138004)


--- trunk/Source/WebCore/bindings/v8/ScriptProfile.h	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfile.h	2012-12-18 11:43:35 UTC (rev 138004)
@@ -47,9 +47,9 @@
 
 class ScriptProfile : public RefCounted<ScriptProfile> {
 public:
-    static PassRefPtr<ScriptProfile> create(const v8::CpuProfile* profile)
+    static PassRefPtr<ScriptProfile> create(const v8::CpuProfile* profile, double idleTime)
     {
-        return adoptRef(new ScriptProfile(profile));
+        return adoptRef(new ScriptProfile(profile, idleTime));
     }
     virtual ~ScriptProfile();
 
@@ -57,6 +57,7 @@
     unsigned int uid() const;
     PassRefPtr<ScriptProfileNode> head() const;
     PassRefPtr<ScriptProfileNode> bottomUpHead() const;
+    double idleTime() const;
 
 #if ENABLE(INSPECTOR)
     PassRefPtr<InspectorObject> buildInspectorObjectForHead() const;
@@ -64,11 +65,13 @@
 #endif
 
 private:
-    ScriptProfile(const v8::CpuProfile* profile)
+    ScriptProfile(const v8::CpuProfile* profile, double idleTime)
         : m_profile(profile)
+        , m_idleTime(idleTime)
     {}
 
     const v8::CpuProfile* m_profile;
+    double m_idleTime;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp (138003 => 138004)


--- trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp	2012-12-18 11:43:35 UTC (rev 138004)
@@ -45,10 +45,19 @@
 
 #include <v8-profiler.h>
 
+#include <wtf/ThreadSpecific.h>
+
 namespace WebCore {
 
+typedef HashMap<String, double> ProfileNameIdleTimeMap;
+
 void ScriptProfiler::start(ScriptState* state, const String& title)
 {
+    ProfileNameIdleTimeMap* profileNameIdleTimeMap = ScriptProfiler::currentProfileNameIdleTimeMap();
+    if (profileNameIdleTimeMap->contains(title))
+        return;
+    profileNameIdleTimeMap->add(title, 0);
+
     v8::HandleScope hs;
     v8::CpuProfiler::StartProfiling(deprecatedV8String(title));
 }
@@ -71,7 +80,16 @@
     const v8::CpuProfile* profile = "" ?
         v8::CpuProfiler::StopProfiling(deprecatedV8String(title), state->context()->GetSecurityToken()) :
         v8::CpuProfiler::StopProfiling(deprecatedV8String(title));
-    return profile ? ScriptProfile::create(profile) : 0;
+
+    double idleTime = 0.0;
+    ProfileNameIdleTimeMap* profileNameIdleTimeMap = ScriptProfiler::currentProfileNameIdleTimeMap();
+    ProfileNameIdleTimeMap::iterator profileIdleTime = profileNameIdleTimeMap->find(title);
+    if (profileIdleTime != profileNameIdleTimeMap->end()) {
+        idleTime = profileIdleTime->value * 1000.0;
+        profileNameIdleTimeMap->remove(profileIdleTime);
+    }
+
+    return profile ? ScriptProfile::create(profile, idleTime) : 0;
 }
 
 PassRefPtr<ScriptProfile> ScriptProfiler::stopForPage(Page*, const String& title)
@@ -263,6 +281,12 @@
     return v8::HeapProfiler::GetMemorySizeUsedByProfiler();
 }
 
+ProfileNameIdleTimeMap* ScriptProfiler::currentProfileNameIdleTimeMap()
+{
+    AtomicallyInitializedStatic(WTF::ThreadSpecific<ProfileNameIdleTimeMap>*, map = new WTF::ThreadSpecific<ProfileNameIdleTimeMap>);
+    return *map;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INSPECTOR)

Modified: trunk/Source/WebCore/bindings/v8/ScriptProfiler.h (138003 => 138004)


--- trunk/Source/WebCore/bindings/v8/ScriptProfiler.h	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfiler.h	2012-12-18 11:43:35 UTC (rev 138004)
@@ -84,6 +84,7 @@
     static void visitExternalArrays(ExternalArrayVisitor*);
     static void collectBindingMemoryInfo(MemoryInstrumentation*);
     static size_t profilerSnapshotsSize();
+    static HashMap<String, double>* currentProfileNameIdleTimeMap();
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/Inspector.json (138003 => 138004)


--- trunk/Source/WebCore/inspector/Inspector.json	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/inspector/Inspector.json	2012-12-18 11:43:35 UTC (rev 138004)
@@ -2980,7 +2980,8 @@
                 "description": "Profile.",
                 "properties": [
                     { "name": "head", "type": "object", "optional": true },
-                    { "name": "bottomUpHead", "type": "object", "optional": true }
+                    { "name": "bottomUpHead", "type": "object", "optional": true },
+                    { "name": "idleTime", "type": "number", "optional": true }
                 ]
             },
             {

Modified: trunk/Source/WebCore/inspector/InspectorController.cpp (138003 => 138004)


--- trunk/Source/WebCore/inspector/InspectorController.cpp	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/inspector/InspectorController.cpp	2012-12-18 11:43:35 UTC (rev 138004)
@@ -413,12 +413,18 @@
 {
     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
         timelineAgent->willProcessTask();
+#if ENABLE(_javascript__DEBUGGER)
+    m_profilerAgent->willProcessTask();
+#endif
 }
 
 void InspectorController::didProcessTask()
 {
     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
         timelineAgent->didProcessTask();
+#if ENABLE(_javascript__DEBUGGER)
+    m_profilerAgent->didProcessTask();
+#endif
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/InspectorProfilerAgent.cpp (138003 => 138004)


--- trunk/Source/WebCore/inspector/InspectorProfilerAgent.cpp	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/inspector/InspectorProfilerAgent.cpp	2012-12-18 11:43:35 UTC (rev 138004)
@@ -52,6 +52,7 @@
 #include "ScriptProfiler.h"
 #include "WebCoreMemoryInstrumentation.h"
 #include "WorkerScriptDebugServer.h"
+#include <wtf/CurrentTime.h>
 #include <wtf/MemoryInstrumentationHashMap.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/text/StringConcatenate.h>
@@ -133,11 +134,13 @@
     , m_injectedScriptManager(injectedScriptManager)
     , m_frontend(0)
     , m_enabled(false)
-    , m_recordingUserInitiatedProfile(false)
+    , m_recordingCPUProfile(false)
     , m_headersRequested(false)
     , m_currentUserInitiatedProfileNumber(-1)
     , m_nextUserInitiatedProfileNumber(1)
     , m_nextUserInitiatedHeapSnapshotNumber(1)
+    , m_profileNameIdleTimeMap(ScriptProfiler::currentProfileNameIdleTimeMap())
+    , m_previousTaskEndTime(0.0)
 {
     m_instrumentingAgents->setInspectorProfilerAgent(this);
 }
@@ -294,6 +297,7 @@
         profileObject->setHead(it->value->buildInspectorObjectForHead());
         if (it->value->bottomUpHead())
             profileObject->setBottomUpHead(it->value->buildInspectorObjectForBottomUpHead());
+        profileObject->setIdleTime(it->value->idleTime());
     } else if (type == HeapProfileType) {
         HeapSnapshotsMap::iterator it = m_snapshots.find(uid);
         if (it == m_snapshots.end()) {
@@ -376,13 +380,13 @@
 
 void InspectorProfilerAgent::start(ErrorString*)
 {
-    if (m_recordingUserInitiatedProfile)
+    if (m_recordingCPUProfile)
         return;
     if (!enabled()) {
         enable(true);
         PageScriptDebugServer::shared().recompileAllJSFunctions(0);
     }
-    m_recordingUserInitiatedProfile = true;
+    m_recordingCPUProfile = true;
     String title = getCurrentUserInitiatedProfileName(true);
     startProfiling(title);
     addStartProfilingMessageToConsole(title, 0, String());
@@ -392,9 +396,9 @@
 
 void InspectorProfilerAgent::stop(ErrorString*)
 {
-    if (!m_recordingUserInitiatedProfile)
+    if (!m_recordingCPUProfile)
         return;
-    m_recordingUserInitiatedProfile = false;
+    m_recordingCPUProfile = false;
     String title = getCurrentUserInitiatedProfileName();
     RefPtr<ScriptProfile> profile = ""
     if (profile)
@@ -497,6 +501,27 @@
     info.addMember(m_snapshots);
 }
 
+void InspectorProfilerAgent::willProcessTask()
+{
+    if (!m_profileNameIdleTimeMap || !m_profileNameIdleTimeMap->size())
+        return;
+    if (!m_previousTaskEndTime)
+        return;
+
+    double idleTime = WTF::monotonicallyIncreasingTime() - m_previousTaskEndTime;
+    m_previousTaskEndTime = 0.0;
+    ProfileNameIdleTimeMap::iterator end = m_profileNameIdleTimeMap->end();
+    for (ProfileNameIdleTimeMap::iterator it = m_profileNameIdleTimeMap->begin(); it != end; ++it)
+        it->value += idleTime;
+}
+
+void InspectorProfilerAgent::didProcessTask()
+{
+    if (!m_profileNameIdleTimeMap || !m_profileNameIdleTimeMap->size())
+        return;
+    m_previousTaskEndTime = WTF::monotonicallyIncreasingTime();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(_javascript__DEBUGGER) && ENABLE(INSPECTOR)

Modified: trunk/Source/WebCore/inspector/InspectorProfilerAgent.h (138003 => 138004)


--- trunk/Source/WebCore/inspector/InspectorProfilerAgent.h	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/inspector/InspectorProfilerAgent.h	2012-12-18 11:43:35 UTC (rev 138004)
@@ -102,6 +102,9 @@
 
     virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
 
+    void willProcessTask();
+    void didProcessTask();
+
 protected:
     InspectorProfilerAgent(InstrumentingAgents*, InspectorConsoleAgent*, InspectorState*, InjectedScriptManager*);
     virtual void startProfiling(const String& title) = 0;
@@ -121,13 +124,17 @@
     InjectedScriptManager* m_injectedScriptManager;
     InspectorFrontend::Profiler* m_frontend;
     bool m_enabled;
-    bool m_recordingUserInitiatedProfile;
+    bool m_recordingCPUProfile;
     bool m_headersRequested;
     int m_currentUserInitiatedProfileNumber;
     unsigned m_nextUserInitiatedProfileNumber;
     unsigned m_nextUserInitiatedHeapSnapshotNumber;
     ProfilesMap m_profiles;
     HeapSnapshotsMap m_snapshots;
+
+    typedef HashMap<String, double> ProfileNameIdleTimeMap;
+    ProfileNameIdleTimeMap* m_profileNameIdleTimeMap;
+    double m_previousTaskEndTime;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.h (138003 => 138004)


--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.h	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.h	2012-12-18 11:43:35 UTC (rev 138004)
@@ -153,11 +153,12 @@
     void willFireAnimationFrame(int callbackId, Frame*);
     void didFireAnimationFrame();
 
-    virtual void didGC(double, double, size_t);
-
     void willProcessTask();
     void didProcessTask();
 
+    // ScriptGCEventListener methods.
+    virtual void didGC(double, double, size_t);
+
     // PlatformInstrumentationClient methods.
     virtual void willDecodeImage(const String& imageType) OVERRIDE;
     virtual void didDecodeImage() OVERRIDE;

Modified: trunk/Source/WebCore/inspector/ScriptProfile.idl (138003 => 138004)


--- trunk/Source/WebCore/inspector/ScriptProfile.idl	2012-12-18 10:47:41 UTC (rev 138003)
+++ trunk/Source/WebCore/inspector/ScriptProfile.idl	2012-12-18 11:43:35 UTC (rev 138004)
@@ -33,5 +33,6 @@
     readonly attribute DOMString title;
     readonly attribute unsigned long uid;
     readonly attribute ScriptProfileNode head;
+    readonly attribute double idleTime;
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to