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;
};