Diff
Modified: releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/ChangeLog (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/ChangeLog 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/ChangeLog 2020-09-04 11:16:19 UTC (rev 266590)
@@ -1,3 +1,19 @@
+2020-09-01 Carlos Garcia Campos <[email protected]>
+
+ [Linux] Web Inspector: show per thread cpu usage
+ https://bugs.webkit.org/show_bug.cgi?id=215883
+
+ Reviewed by Adrian Perez de Castro.
+
+ Remove platform specific getter machThread() and add thread() to return the Thread instead. The caller knows how
+ to get the machThread or id from a Thread.
+
+ * runtime/SamplingProfiler.cpp:
+ (JSC::SamplingProfiler::reportTopBytecodes):
+ (JSC::SamplingProfiler::machThread): Deleted.
+ * runtime/SamplingProfiler.h:
+ (JSC::SamplingProfiler::thread):
+
2020-08-14 Caio Lima <[email protected]>
[ARMv7][JSC] Conservative GC is not considering `r7` as a root
Modified: releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/runtime/SamplingProfiler.cpp (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/runtime/SamplingProfiler.cpp 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/runtime/SamplingProfiler.cpp 2020-09-04 11:16:19 UTC (rev 266590)
@@ -1141,15 +1141,10 @@
}
}
-#if OS(DARWIN)
-mach_port_t SamplingProfiler::machThread()
+Thread* SamplingProfiler::thread() const
{
- if (!m_thread)
- return MACH_PORT_NULL;
-
- return m_thread->machThread();
+ return m_thread.get();
}
-#endif
} // namespace JSC
Modified: releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/runtime/SamplingProfiler.h (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/runtime/SamplingProfiler.h 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/_javascript_Core/runtime/SamplingProfiler.h 2020-09-04 11:16:19 UTC (rev 266590)
@@ -193,9 +193,7 @@
JS_EXPORT_PRIVATE void reportTopBytecodes();
JS_EXPORT_PRIVATE void reportTopBytecodes(PrintStream&);
-#if OS(DARWIN)
- JS_EXPORT_PRIVATE mach_port_t machThread();
-#endif
+ JS_EXPORT_PRIVATE Thread* thread() const;
private:
void createThreadIfNecessary(const AbstractLocker&);
Modified: releases/WebKitGTK/webkit-2.30/Source/WTF/ChangeLog (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WTF/ChangeLog 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WTF/ChangeLog 2020-09-04 11:16:19 UTC (rev 266590)
@@ -1,3 +1,20 @@
+2020-09-01 Carlos Garcia Campos <[email protected]>
+
+ [Linux] Web Inspector: show per thread cpu usage
+ https://bugs.webkit.org/show_bug.cgi?id=215883
+
+ Reviewed by Adrian Perez de Castro.
+
+ Add API to get the thread ID in Linux platform.
+
+ * wtf/Threading.cpp:
+ (WTF::Thread::initializeInThread):
+ * wtf/Threading.h:
+ (WTF::Thread::id const):
+ * wtf/ThreadingPrimitives.h:
+ * wtf/posix/ThreadingPOSIX.cpp:
+ (WTF::Thread::currentID):
+
2020-08-27 Carlos Garcia Campos <[email protected]>
[GTK] Include the run loop source name in frame rendering timeline
Modified: releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/Threading.cpp (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/Threading.cpp 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/Threading.cpp 2020-09-04 11:16:19 UTC (rev 266590)
@@ -138,6 +138,10 @@
m_currentAtomStringTable = &sharedStringTable.get();
}
#endif
+
+#if OS(LINUX)
+ m_id = currentID();
+#endif
}
void Thread::entryPoint(NewThreadContext* newThreadContext)
Modified: releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/Threading.h (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/Threading.h 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/Threading.h 2020-09-04 11:16:19 UTC (rev 266590)
@@ -157,6 +157,10 @@
WTF_EXPORT_PRIVATE size_t getRegisters(PlatformRegisters&);
#if USE(PTHREADS)
+#if OS(LINUX)
+ WTF_EXPORT_PRIVATE static ThreadIdentifier currentID();
+ ThreadIdentifier id() const { return m_id; }
+#endif
WTF_EXPORT_PRIVATE bool signal(int signalNumber);
#endif
@@ -329,6 +333,9 @@
#elif OS(DARWIN)
mach_port_t m_platformThread { MACH_PORT_NULL };
#elif USE(PTHREADS)
+#if OS(LINUX)
+ ThreadIdentifier m_id { 0 };
+#endif
PlatformRegisters* m_platformRegisters { nullptr };
unsigned m_suspendCount { 0 };
#endif
Modified: releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/ThreadingPrimitives.h (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/ThreadingPrimitives.h 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/ThreadingPrimitives.h 2020-09-04 11:16:19 UTC (rev 266590)
@@ -57,6 +57,9 @@
using PlatformMutex = pthread_mutex_t;
using PlatformCondition = pthread_cond_t;
using ThreadSpecificKey = pthread_key_t;
+#if OS(LINUX)
+using ThreadIdentifier = pid_t;
+#endif
#elif OS(WINDOWS)
using ThreadIdentifier = uint32_t;
using PlatformThreadHandle = HANDLE;
Modified: releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/posix/ThreadingPOSIX.cpp (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/posix/ThreadingPOSIX.cpp 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WTF/wtf/posix/ThreadingPOSIX.cpp 2020-09-04 11:16:19 UTC (rev 266590)
@@ -68,6 +68,10 @@
#include <mach/thread_switch.h>
#endif
+#if OS(LINUX)
+#include <sys/syscall.h>
+#endif
+
namespace WTF {
static Lock globalSuspendLock;
@@ -187,6 +191,13 @@
#endif
}
+#if OS(LINUX)
+ThreadIdentifier Thread::currentID()
+{
+ return static_cast<ThreadIdentifier>(syscall(SYS_gettid));
+}
+#endif
+
void Thread::initializeCurrentThreadEvenIfNonWTFCreated()
{
#if !OS(DARWIN)
Modified: releases/WebKitGTK/webkit-2.30/Source/WebCore/ChangeLog (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WebCore/ChangeLog 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WebCore/ChangeLog 2020-09-04 11:16:19 UTC (rev 266590)
@@ -1,3 +1,23 @@
+2020-09-01 Carlos Garcia Campos <[email protected]>
+
+ [Linux] Web Inspector: show per thread cpu usage
+ https://bugs.webkit.org/show_bug.cgi?id=215883
+
+ Reviewed by Adrian Perez de Castro.
+
+ Get per thread CPU usage and information to fill ResourceUsageData in Linux.
+
+ * page/ResourceUsageThread.h:
+ * page/cocoa/ResourceUsageThreadCocoa.mm:
+ (WebCore::ResourceUsageThread::platformSaveStateBeforeStarting): Update to new API in SamplingProfiler.
+ * page/linux/ResourceUsageThreadLinux.cpp:
+ (WebCore::ResourceUsageThread::platformSaveStateBeforeStarting): Initialize m_samplingProfilerThreadID.
+ (WebCore::threadInfoMap):
+ (WebCore::threadCPUUsage):
+ (WebCore::collectCPUUsage):
+ (WebCore::ResourceUsageThread::platformCollectCPUData):
+ (WebCore::cpuUsage): Deleted.
+
2020-08-27 Carlos Garcia Campos <[email protected]>
[GTK] Include the run loop source name in frame rendering timeline
Modified: releases/WebKitGTK/webkit-2.30/Source/WebCore/page/ResourceUsageThread.h (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WebCore/page/ResourceUsageThread.h 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WebCore/page/ResourceUsageThread.h 2020-09-04 11:16:19 UTC (rev 266590)
@@ -88,9 +88,13 @@
// They should ensure their use of the VM is thread safe.
JSC::VM* m_vm { nullptr };
-#if ENABLE(SAMPLING_PROFILER) && OS(DARWIN)
+#if ENABLE(SAMPLING_PROFILER)
+#if OS(DARWIN)
mach_port_t m_samplingProfilerMachThread { MACH_PORT_NULL };
+#elif OS(LINUX)
+ pid_t m_samplingProfilerThreadID { 0 };
#endif
+#endif
};
Modified: releases/WebKitGTK/webkit-2.30/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm 2020-09-04 11:16:19 UTC (rev 266590)
@@ -136,7 +136,12 @@
void ResourceUsageThread::platformSaveStateBeforeStarting()
{
#if ENABLE(SAMPLING_PROFILER)
- m_samplingProfilerMachThread = m_vm->samplingProfiler() ? m_vm->samplingProfiler()->machThread() : MACH_PORT_NULL;
+ m_samplingProfilerMachThread = MACH_PORT_NULL;
+
+ if (auto* profiler = m_vm->samplingProfiler()) {
+ if (auto* thread = profiler->thread())
+ m_samplingProfilerMachThread = thread->machThread();
+ }
#endif
}
Modified: releases/WebKitGTK/webkit-2.30/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp (266589 => 266590)
--- releases/WebKitGTK/webkit-2.30/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp 2020-09-04 11:16:11 UTC (rev 266589)
+++ releases/WebKitGTK/webkit-2.30/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp 2020-09-04 11:16:19 UTC (rev 266590)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Igalia S.L.
+ * Copyright (C) 2017, 2020 Igalia S.L.
* Copyright (C) 2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,9 @@
#if ENABLE(RESOURCE_USAGE) && OS(LINUX)
+#include "WorkerThread.h"
#include <_javascript_Core/GCActivityCallback.h>
+#include <_javascript_Core/SamplingProfiler.h>
#include <_javascript_Core/VM.h>
#include <errno.h>
#include <fcntl.h>
@@ -38,6 +40,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <wtf/Threading.h>
#include <wtf/linux/CurrentProcessMemoryStatus.h>
namespace WebCore {
@@ -90,15 +93,41 @@
return static_cast<float>(period) / cpuCount;
}
-static float cpuUsage()
+void ResourceUsageThread::platformSaveStateBeforeStarting()
{
- float period = cpuPeriod();
- if (!period)
- return -1;
+#if ENABLE(SAMPLING_PROFILER)
+ m_samplingProfilerThreadID = 0;
- int fd = open("/proc/self/stat", O_RDONLY);
+ if (auto* profiler = m_vm->samplingProfiler()) {
+ if (auto* thread = profiler->thread())
+ m_samplingProfilerThreadID = thread->id();
+ }
+#endif
+}
+
+struct ThreadInfo {
+ Optional<String> name;
+ Optional<float> cpuUsage;
+ unsigned long long previousUtime { 0 };
+ unsigned long long previousStime { 0 };
+};
+
+static HashMap<pid_t, ThreadInfo>& threadInfoMap()
+{
+ static LazyNeverDestroyed<HashMap<pid_t, ThreadInfo>> map;
+ static std::once_flag flag;
+ std::call_once(flag, [&] {
+ map.construct();
+ });
+ return map;
+}
+
+static bool threadCPUUsage(pid_t id, float period, ThreadInfo& info)
+{
+ String path = makeString("/proc/self/task/", id, "/stat");
+ int fd = open(path.utf8().data(), O_RDONLY);
if (fd < 0)
- return -1;
+ return false;
static const ssize_t maxBufferLength = BUFSIZ - 1;
char buffer[BUFSIZ];
@@ -110,7 +139,7 @@
if (bytesRead < 0) {
if (errno != EINTR) {
close(fd);
- return -1;
+ return false;
}
continue;
}
@@ -123,11 +152,19 @@
close(fd);
buffer[totalBytesRead] = '\0';
- // Skip pid and process name.
- char* position = strrchr(buffer, ')');
+ // Skip tid and name.
+ char* position = strchr(buffer, ')');
if (!position)
- return -1;
+ return false;
+ if (!info.name) {
+ char* name = strchr(buffer, '(');
+ if (!name)
+ return false;
+ name++;
+ info.name = String::fromUTF8(name, position - name);
+ }
+
// Move after state.
position += 4;
@@ -139,29 +176,130 @@
position++;
}
- static unsigned long long previousUtime = 0;
- static unsigned long long previousStime = 0;
unsigned long long utime = strtoull(position, &position, 10);
unsigned long long stime = strtoull(position, &position, 10);
- float usage = (utime + stime - (previousUtime + previousStime)) / period * 100.0;
- previousUtime = utime;
- previousStime = stime;
+ float usage = (utime + stime - (info.previousUtime + info.previousStime)) / period * 100.0;
+ info.previousUtime = utime;
+ info.previousStime = stime;
- return clampTo<float>(usage, 0, 100);
+ info.cpuUsage = clampTo<float>(usage, 0, 100);
+ return true;
}
-void ResourceUsageThread::platformSaveStateBeforeStarting()
+static void collectCPUUsage(float period)
{
+ DIR* dir = opendir("/proc/self/task");
+ if (!dir) {
+ threadInfoMap().clear();
+ return;
+ }
+
+ HashSet<pid_t> previousTasks;
+ for (const auto& key : threadInfoMap().keys())
+ previousTasks.add(key);
+
+ struct dirent* dp;
+ while ((dp = readdir(dir))) {
+ String name = String::fromUTF8(dp->d_name);
+ if (name == "." || name == "..")
+ continue;
+
+ bool ok;
+ pid_t id = name.toIntStrict(&ok);
+ if (!ok)
+ continue;
+
+ auto& info = threadInfoMap().add(id, ThreadInfo()).iterator->value;
+ if (!threadCPUUsage(id, period, info))
+ threadInfoMap().remove(id);
+
+ previousTasks.remove(id);
+ }
+ closedir(dir);
+
+ threadInfoMap().removeIf([&](auto& entry) {
+ return previousTasks.contains(entry.key);
+ });
}
void ResourceUsageThread::platformCollectCPUData(JSC::VM*, ResourceUsageData& data)
{
- data.cpu = cpuUsage();
+ float period = cpuPeriod();
+ if (!period) {
+ data.cpu = 0;
+ data.cpuExcludingDebuggerThreads = 0;
+ return;
+ }
- // FIXME: Exclude the ResourceUsage thread.
- // FIXME: Exclude the SamplingProfiler thread.
- // FIXME: Classify usage per thread.
- data.cpuExcludingDebuggerThreads = data.cpu;
+ collectCPUUsage(period);
+
+ pid_t resourceUsageThreadID = Thread::currentID();
+
+ HashSet<pid_t> knownWebKitThreads;
+ {
+ auto locker = holdLock(Thread::allThreadsMutex());
+ for (auto* thread : Thread::allThreads(locker)) {
+ if (auto id = thread->id())
+ knownWebKitThreads.add(id);
+ }
+ }
+
+ HashMap<pid_t, String> knownWorkerThreads;
+ {
+ LockHolder lock(WorkerThread::workerThreadsMutex());
+ for (auto* thread : WorkerThread::workerThreads(lock)) {
+ // Ignore worker threads that have not been fully started yet.
+ if (!thread->thread())
+ continue;
+
+ if (auto id = thread->thread()->id())
+ knownWorkerThreads.set(id, thread->identifier().isolatedCopy());
+ }
+ }
+
+ auto isDebuggerThread = [&](pid_t id) -> bool {
+ if (id == resourceUsageThreadID)
+ return true;
+#if ENABLE(SAMPLING_PROFILER)
+ if (id == m_samplingProfilerThreadID)
+ return true;
+#endif
+ return false;
+ };
+
+ auto isWebKitThread = [&](pid_t id, const String& name) -> bool {
+ if (knownWebKitThreads.contains(id))
+ return true;
+
+ // The bmalloc scavenger thread is below WTF. Detect it by its name.
+ if (name == "BMScavenger")
+ return true;
+
+ return false;
+ };
+
+ for (const auto& it : threadInfoMap()) {
+ if (!it.value.cpuUsage)
+ continue;
+
+ float cpuUsage = it.value.cpuUsage.value();
+ pid_t id = it.key;
+ data.cpu += cpuUsage;
+ if (isDebuggerThread(id))
+ continue;
+
+ data.cpuExcludingDebuggerThreads += cpuUsage;
+
+ if (getpid() == id)
+ data.cpuThreads.append(ThreadCPUInfo { "Main Thread"_s, { }, cpuUsage, ThreadCPUInfo::Type::Main});
+ else {
+ String threadIdentifier = knownWorkerThreads.get(id);
+ bool isWorkerThread = !threadIdentifier.isEmpty();
+ String name = it.value.name.valueOr(emptyString());
+ ThreadCPUInfo::Type type = (isWorkerThread || isWebKitThread(id, name)) ? ThreadCPUInfo::Type::WebKit : ThreadCPUInfo::Type::Unknown;
+ data.cpuThreads.append(ThreadCPUInfo { name, threadIdentifier, cpuUsage, type });
+ }
+ }
}
void ResourceUsageThread::platformCollectMemoryData(JSC::VM* vm, ResourceUsageData& data)