Changeset 266388 in webkit
- Timestamp:
- Sep 1, 2020 1:55:06 AM (4 years ago)
- Location:
- trunk/Source
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r266359 r266388 1 2020-09-01 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [Linux] Web Inspector: show per thread cpu usage 4 https://bugs.webkit.org/show_bug.cgi?id=215883 5 6 Reviewed by Adrian Perez de Castro. 7 8 Remove platform specific getter machThread() and add thread() to return the Thread instead. The caller knows how 9 to get the machThread or id from a Thread. 10 11 * runtime/SamplingProfiler.cpp: 12 (JSC::SamplingProfiler::reportTopBytecodes): 13 (JSC::SamplingProfiler::machThread): Deleted. 14 * runtime/SamplingProfiler.h: 15 (JSC::SamplingProfiler::thread): 16 1 17 2020-08-31 Yusuke Suzuki <ysuzuki@apple.com> 2 18 -
trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp
r264736 r266388 1142 1142 } 1143 1143 1144 #if OS(DARWIN) 1145 mach_port_t SamplingProfiler::machThread() 1146 { 1147 if (!m_thread) 1148 return MACH_PORT_NULL; 1149 1150 return m_thread->machThread(); 1151 } 1152 #endif 1144 Thread* SamplingProfiler::thread() const 1145 { 1146 return m_thread.get(); 1147 } 1153 1148 1154 1149 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/SamplingProfiler.h
r261233 r266388 194 194 JS_EXPORT_PRIVATE void reportTopBytecodes(PrintStream&); 195 195 196 #if OS(DARWIN) 197 JS_EXPORT_PRIVATE mach_port_t machThread(); 198 #endif 196 JS_EXPORT_PRIVATE Thread* thread() const; 199 197 200 198 private: -
trunk/Source/WTF/ChangeLog
r266354 r266388 1 2020-09-01 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [Linux] Web Inspector: show per thread cpu usage 4 https://bugs.webkit.org/show_bug.cgi?id=215883 5 6 Reviewed by Adrian Perez de Castro. 7 8 Add API to get the thread ID in Linux platform. 9 10 * wtf/Threading.cpp: 11 (WTF::Thread::initializeInThread): 12 * wtf/Threading.h: 13 (WTF::Thread::id const): 14 * wtf/ThreadingPrimitives.h: 15 * wtf/posix/ThreadingPOSIX.cpp: 16 (WTF::Thread::currentID): 17 1 18 2020-08-31 Alex Christensen <achristensen@webkit.org> 2 19 -
trunk/Source/WTF/wtf/Threading.cpp
r265735 r266388 147 147 } 148 148 #endif 149 150 #if OS(LINUX) 151 m_id = currentID(); 152 #endif 149 153 } 150 154 -
trunk/Source/WTF/wtf/Threading.h
r263635 r266388 158 158 159 159 #if USE(PTHREADS) 160 #if OS(LINUX) 161 WTF_EXPORT_PRIVATE static ThreadIdentifier currentID(); 162 ThreadIdentifier id() const { return m_id; } 163 #endif 160 164 WTF_EXPORT_PRIVATE bool signal(int signalNumber); 161 165 #endif … … 330 334 mach_port_t m_platformThread { MACH_PORT_NULL }; 331 335 #elif USE(PTHREADS) 336 #if OS(LINUX) 337 ThreadIdentifier m_id { 0 }; 338 #endif 332 339 PlatformRegisters* m_platformRegisters { nullptr }; 333 340 unsigned m_suspendCount { 0 }; -
trunk/Source/WTF/wtf/ThreadingPrimitives.h
r253730 r266388 58 58 using PlatformCondition = pthread_cond_t; 59 59 using ThreadSpecificKey = pthread_key_t; 60 #if OS(LINUX) 61 using ThreadIdentifier = pid_t; 62 #endif 60 63 #elif OS(WINDOWS) 61 64 using ThreadIdentifier = uint32_t; -
trunk/Source/WTF/wtf/posix/ThreadingPOSIX.cpp
r265383 r266388 69 69 #endif 70 70 71 #if OS(LINUX) 72 #include <sys/syscall.h> 73 #endif 74 71 75 namespace WTF { 72 76 … … 187 191 #endif 188 192 } 193 194 #if OS(LINUX) 195 ThreadIdentifier Thread::currentID() 196 { 197 return static_cast<ThreadIdentifier>(syscall(SYS_gettid)); 198 } 199 #endif 189 200 190 201 void Thread::initializeCurrentThreadEvenIfNonWTFCreated() -
trunk/Source/WebCore/ChangeLog
r266387 r266388 1 2020-09-01 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [Linux] Web Inspector: show per thread cpu usage 4 https://bugs.webkit.org/show_bug.cgi?id=215883 5 6 Reviewed by Adrian Perez de Castro. 7 8 Get per thread CPU usage and information to fill ResourceUsageData in Linux. 9 10 * page/ResourceUsageThread.h: 11 * page/cocoa/ResourceUsageThreadCocoa.mm: 12 (WebCore::ResourceUsageThread::platformSaveStateBeforeStarting): Update to new API in SamplingProfiler. 13 * page/linux/ResourceUsageThreadLinux.cpp: 14 (WebCore::ResourceUsageThread::platformSaveStateBeforeStarting): Initialize m_samplingProfilerThreadID. 15 (WebCore::threadInfoMap): 16 (WebCore::threadCPUUsage): 17 (WebCore::collectCPUUsage): 18 (WebCore::ResourceUsageThread::platformCollectCPUData): 19 (WebCore::cpuUsage): Deleted. 20 1 21 2020-08-31 Myles C. Maxfield <mmaxfield@apple.com> 2 22 -
trunk/Source/WebCore/page/ResourceUsageThread.h
r247815 r266388 89 89 JSC::VM* m_vm { nullptr }; 90 90 91 #if ENABLE(SAMPLING_PROFILER) && OS(DARWIN) 91 #if ENABLE(SAMPLING_PROFILER) 92 #if OS(DARWIN) 92 93 mach_port_t m_samplingProfilerMachThread { MACH_PORT_NULL }; 94 #elif OS(LINUX) 95 pid_t m_samplingProfilerThreadID { 0 }; 96 #endif 93 97 #endif 94 98 -
trunk/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm
r260682 r266388 137 137 { 138 138 #if ENABLE(SAMPLING_PROFILER) 139 m_samplingProfilerMachThread = m_vm->samplingProfiler() ? m_vm->samplingProfiler()->machThread() : MACH_PORT_NULL; 139 m_samplingProfilerMachThread = MACH_PORT_NULL; 140 141 if (auto* profiler = m_vm->samplingProfiler()) { 142 if (auto* thread = profiler->thread()) 143 m_samplingProfilerMachThread = thread->machThread(); 144 } 140 145 #endif 141 146 } -
trunk/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp
r241739 r266388 1 1 /* 2 * Copyright (C) 2017 Igalia S.L.2 * Copyright (C) 2017, 2020 Igalia S.L. 3 3 * Copyright (C) 2018 Apple Inc. All rights reserved. 4 4 * … … 30 30 #if ENABLE(RESOURCE_USAGE) && OS(LINUX) 31 31 32 #include "WorkerThread.h" 32 33 #include <JavaScriptCore/GCActivityCallback.h> 34 #include <JavaScriptCore/SamplingProfiler.h> 33 35 #include <JavaScriptCore/VM.h> 34 36 #include <errno.h> … … 39 41 #include <sys/types.h> 40 42 #include <unistd.h> 43 #include <wtf/Threading.h> 41 44 #include <wtf/linux/CurrentProcessMemoryStatus.h> 42 45 … … 91 94 } 92 95 93 static float cpuUsage() 94 { 95 float period = cpuPeriod(); 96 if (!period) 97 return -1; 98 99 int fd = open("/proc/self/stat", O_RDONLY); 96 void ResourceUsageThread::platformSaveStateBeforeStarting() 97 { 98 #if ENABLE(SAMPLING_PROFILER) 99 m_samplingProfilerThreadID = 0; 100 101 if (auto* profiler = m_vm->samplingProfiler()) { 102 if (auto* thread = profiler->thread()) 103 m_samplingProfilerThreadID = thread->id(); 104 } 105 #endif 106 } 107 108 struct ThreadInfo { 109 Optional<String> name; 110 Optional<float> cpuUsage; 111 unsigned long long previousUtime { 0 }; 112 unsigned long long previousStime { 0 }; 113 }; 114 115 static HashMap<pid_t, ThreadInfo>& threadInfoMap() 116 { 117 static LazyNeverDestroyed<HashMap<pid_t, ThreadInfo>> map; 118 static std::once_flag flag; 119 std::call_once(flag, [&] { 120 map.construct(); 121 }); 122 return map; 123 } 124 125 static bool threadCPUUsage(pid_t id, float period, ThreadInfo& info) 126 { 127 String path = makeString("/proc/self/task/", id, "/stat"); 128 int fd = open(path.utf8().data(), O_RDONLY); 100 129 if (fd < 0) 101 return -1;130 return false; 102 131 103 132 static const ssize_t maxBufferLength = BUFSIZ - 1; … … 111 140 if (errno != EINTR) { 112 141 close(fd); 113 return -1;142 return false; 114 143 } 115 144 continue; … … 124 153 buffer[totalBytesRead] = '\0'; 125 154 126 // Skip pid and processname.127 char* position = str rchr(buffer, ')');155 // Skip tid and name. 156 char* position = strchr(buffer, ')'); 128 157 if (!position) 129 return -1; 158 return false; 159 160 if (!info.name) { 161 char* name = strchr(buffer, '('); 162 if (!name) 163 return false; 164 name++; 165 info.name = String::fromUTF8(name, position - name); 166 } 130 167 131 168 // Move after state. … … 140 177 } 141 178 142 static unsigned long long previousUtime = 0;143 static unsigned long long previousStime = 0;144 179 unsigned long long utime = strtoull(position, &position, 10); 145 180 unsigned long long stime = strtoull(position, &position, 10); 146 float usage = (utime + stime - (previousUtime + previousStime)) / period * 100.0; 147 previousUtime = utime; 148 previousStime = stime; 149 150 return clampTo<float>(usage, 0, 100); 151 } 152 153 void ResourceUsageThread::platformSaveStateBeforeStarting() 154 { 181 float usage = (utime + stime - (info.previousUtime + info.previousStime)) / period * 100.0; 182 info.previousUtime = utime; 183 info.previousStime = stime; 184 185 info.cpuUsage = clampTo<float>(usage, 0, 100); 186 return true; 187 } 188 189 static void collectCPUUsage(float period) 190 { 191 DIR* dir = opendir("/proc/self/task"); 192 if (!dir) { 193 threadInfoMap().clear(); 194 return; 195 } 196 197 HashSet<pid_t> previousTasks; 198 for (const auto& key : threadInfoMap().keys()) 199 previousTasks.add(key); 200 201 struct dirent* dp; 202 while ((dp = readdir(dir))) { 203 String name = String::fromUTF8(dp->d_name); 204 if (name == "." || name == "..") 205 continue; 206 207 bool ok; 208 pid_t id = name.toIntStrict(&ok); 209 if (!ok) 210 continue; 211 212 auto& info = threadInfoMap().add(id, ThreadInfo()).iterator->value; 213 if (!threadCPUUsage(id, period, info)) 214 threadInfoMap().remove(id); 215 216 previousTasks.remove(id); 217 } 218 closedir(dir); 219 220 threadInfoMap().removeIf([&](auto& entry) { 221 return previousTasks.contains(entry.key); 222 }); 155 223 } 156 224 157 225 void ResourceUsageThread::platformCollectCPUData(JSC::VM*, ResourceUsageData& data) 158 226 { 159 data.cpu = cpuUsage(); 160 161 // FIXME: Exclude the ResourceUsage thread. 162 // FIXME: Exclude the SamplingProfiler thread. 163 // FIXME: Classify usage per thread. 164 data.cpuExcludingDebuggerThreads = data.cpu; 227 float period = cpuPeriod(); 228 if (!period) { 229 data.cpu = 0; 230 data.cpuExcludingDebuggerThreads = 0; 231 return; 232 } 233 234 collectCPUUsage(period); 235 236 pid_t resourceUsageThreadID = Thread::currentID(); 237 238 HashSet<pid_t> knownWebKitThreads; 239 { 240 auto locker = holdLock(Thread::allThreadsMutex()); 241 for (auto* thread : Thread::allThreads(locker)) { 242 if (auto id = thread->id()) 243 knownWebKitThreads.add(id); 244 } 245 } 246 247 HashMap<pid_t, String> knownWorkerThreads; 248 { 249 LockHolder lock(WorkerThread::workerThreadsMutex()); 250 for (auto* thread : WorkerThread::workerThreads(lock)) { 251 // Ignore worker threads that have not been fully started yet. 252 if (!thread->thread()) 253 continue; 254 255 if (auto id = thread->thread()->id()) 256 knownWorkerThreads.set(id, thread->identifier().isolatedCopy()); 257 } 258 } 259 260 auto isDebuggerThread = [&](pid_t id) -> bool { 261 if (id == resourceUsageThreadID) 262 return true; 263 #if ENABLE(SAMPLING_PROFILER) 264 if (id == m_samplingProfilerThreadID) 265 return true; 266 #endif 267 return false; 268 }; 269 270 auto isWebKitThread = [&](pid_t id, const String& name) -> bool { 271 if (knownWebKitThreads.contains(id)) 272 return true; 273 274 // The bmalloc scavenger thread is below WTF. Detect it by its name. 275 if (name == "BMScavenger") 276 return true; 277 278 return false; 279 }; 280 281 for (const auto& it : threadInfoMap()) { 282 if (!it.value.cpuUsage) 283 continue; 284 285 float cpuUsage = it.value.cpuUsage.value(); 286 pid_t id = it.key; 287 data.cpu += cpuUsage; 288 if (isDebuggerThread(id)) 289 continue; 290 291 data.cpuExcludingDebuggerThreads += cpuUsage; 292 293 if (getpid() == id) 294 data.cpuThreads.append(ThreadCPUInfo { "Main Thread"_s, { }, cpuUsage, ThreadCPUInfo::Type::Main}); 295 else { 296 String threadIdentifier = knownWorkerThreads.get(id); 297 bool isWorkerThread = !threadIdentifier.isEmpty(); 298 String name = it.value.name.valueOr(emptyString()); 299 ThreadCPUInfo::Type type = (isWorkerThread || isWebKitThread(id, name)) ? ThreadCPUInfo::Type::WebKit : ThreadCPUInfo::Type::Unknown; 300 data.cpuThreads.append(ThreadCPUInfo { name, threadIdentifier, cpuUsage, type }); 301 } 302 } 165 303 } 166 304
Note: See TracChangeset
for help on using the changeset viewer.