Title: [266590] releases/WebKitGTK/webkit-2.30/Source
Revision
266590
Author
[email protected]
Date
2020-09-04 04:16:19 -0700 (Fri, 04 Sep 2020)

Log Message

Merge r266388 - [Linux] Web Inspector: show per thread cpu usage
https://bugs.webkit.org/show_bug.cgi?id=215883

Reviewed by Adrian Perez de Castro.

Source/_javascript_Core:

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):

Source/WebCore:

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.

Source/WTF:

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):

Modified Paths

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)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to