mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 16:25:38 +00:00
d5e552f528
clang's -Wmissing-prototypes option identifies global functions that can be made static (because they're only called from one compilation unit) or removed (if they're never called). xpcom/base/Logging.cpp:85:13 [-Wmissing-prototypes] no previous prototype for function 'ToLogStr' xpcom/base/Logging.cpp:132:13 [-Wmissing-prototypes] no previous prototype for function 'ExpandPIDMarker' xpcom/base/LogModulePrefWatcher.cpp:37:6 [-Wmissing-prototypes] no previous prototype for function 'ResetExistingPrefs' xpcom/base/LogModulePrefWatcher.cpp:109:6 [-Wmissing-prototypes] no previous prototype for function 'LoadExistingPrefs' xpcom/base/nsCycleCollector.cpp:212:6 [-Wmissing-prototypes] no previous prototype for function 'SuspectUsingNurseryPurpleBuffer' xpcom/components/nsComponentManager.cpp:421:31 [-Wmissing-prototypes] no previous prototype for function 'begin' xpcom/components/nsComponentManager.cpp:427:31 [-Wmissing-prototypes] no previous prototype for function 'end' xpcom/ds/Dafsa.cpp:23:6 [-Wmissing-prototypes] no previous prototype for function 'GetNextOffset' xpcom/ds/Dafsa.cpp:55:6 [-Wmissing-prototypes] no previous prototype for function 'IsEOL' xpcom/ds/Dafsa.cpp:62:6 [-Wmissing-prototypes] no previous prototype for function 'IsMatch' xpcom/ds/Dafsa.cpp:70:6 [-Wmissing-prototypes] no previous prototype for function 'IsEndCharMatch' xpcom/ds/Dafsa.cpp:78:6 [-Wmissing-prototypes] no previous prototype for function 'GetReturnValue' xpcom/ds/Dafsa.cpp:91:5 [-Wmissing-prototypes] no previous prototype for function 'LookupString' xpcom/io/CocoaFileUtils.mm:195:13 [-Wmissing-prototypes] no previous prototype for function 'GetQuarantinePropKey' xpcom/io/CocoaFileUtils.mm:203:24 [-Wmissing-prototypes] no previous prototype for function 'CreateQuarantineDictionary' xpcom/rust/gtest/bench-collections/Bench.cpp:65:11 [-Wmissing-prototypes] no previous prototype for function 'MyRand' xpcom/rust/gtest/bench-collections/Bench.cpp:85:6 [-Wmissing-prototypes] no previous prototype for function 'Bench_Cpp_unordered_set' xpcom/rust/gtest/bench-collections/Bench.cpp:125:6 [-Wmissing-prototypes] no previous prototype for function 'Bench_Cpp_PLDHashTable' xpcom/rust/gtest/bench-collections/Bench.cpp:166:6 [-Wmissing-prototypes] no previous prototype for function 'Bench_Cpp_MozHashSet' xpcom/tests/gtest/TestAtoms.cpp:114:6 [-Wmissing-prototypes] no previous prototype for function 'isStaticAtom' xpcom/tests/gtest/TestCallTemplates.cpp:72:6 [-Wmissing-prototypes] no previous prototype for function 'JustTestingCompilation' xpcom/tests/gtest/TestCOMPtr.cpp:87:10 [-Wmissing-prototypes] no previous prototype for function 'CreateIFoo' xpcom/tests/gtest/TestCOMPtr.cpp:98:6 [-Wmissing-prototypes] no previous prototype for function 'set_a_IFoo' xpcom/tests/gtest/TestCOMPtr.cpp:105:16 [-Wmissing-prototypes] no previous prototype for function 'return_a_IFoo' xpcom/tests/gtest/TestCOMPtr.cpp:164:10 [-Wmissing-prototypes] no previous prototype for function 'CreateIBar' xpcom/tests/gtest/TestCOMPtr.cpp:175:6 [-Wmissing-prototypes] no previous prototype for function 'AnIFooPtrPtrContext' xpcom/tests/gtest/TestCOMPtr.cpp:177:6 [-Wmissing-prototypes] no previous prototype for function 'AVoidPtrPtrContext' xpcom/tests/gtest/TestCOMPtr.cpp:179:6 [-Wmissing-prototypes] no previous prototype for function 'AnISupportsPtrPtrContext' xpcom/tests/gtest/TestCOMPtr.cpp:263:6 [-Wmissing-prototypes] no previous prototype for function 'Comparison' xpcom/tests/gtest/TestCOMPtr.cpp:298:6 [-Wmissing-prototypes] no previous prototype for function 'DontAddRef' xpcom/tests/gtest/TestCRT.cpp:17:5 [-Wmissing-prototypes] no previous prototype for function 'sign' xpcom/tests/gtest/TestDeadlockDetector.cpp:62:6 [-Wmissing-prototypes] no previous prototype for function 'DisableCrashReporter' xpcom/tests/gtest/TestDeadlockDetector.cpp:74:5 [-Wmissing-prototypes] no previous prototype for function 'Sanity_Child' xpcom/tests/gtest/TestDeadlockDetector.cpp:95:5 [-Wmissing-prototypes] no previous prototype for function 'Sanity2_Child' xpcom/tests/gtest/TestDeadlockDetector.cpp:159:5 [-Wmissing-prototypes] no previous prototype for function 'Sanity4_Child' xpcom/tests/gtest/TestDeadlockDetector.cpp:182:5 [-Wmissing-prototypes] no previous prototype for function 'Sanity5_Child' xpcom/tests/gtest/TestDeadlockDetector.cpp:303:5 [-Wmissing-prototypes] no previous prototype for function 'ContentionNoDeadlock_Child' xpcom/tests/gtest/TestHashtables.cpp:88:6 [-Wmissing-prototypes] no previous prototype for function 'testTHashtable' xpcom/tests/gtest/TestHashtables.cpp:205:10 [-Wmissing-prototypes] no previous prototype for function 'CreateIFoo' xpcom/tests/gtest/TestMoveString.cpp:25:6 [-Wmissing-prototypes] no previous prototype for function 'SetAsOwned' xpcom/tests/gtest/TestMoveString.cpp:34:6 [-Wmissing-prototypes] no previous prototype for function 'ExpectTruncated' xpcom/tests/gtest/TestMoveString.cpp:40:6 [-Wmissing-prototypes] no previous prototype for function 'ExpectNew' xpcom/tests/gtest/TestMruCache.cpp:52:11 [-Wmissing-prototypes] no previous prototype for function 'MakeStringKey' xpcom/tests/gtest/TestMultiplexInputStream.cpp:106:34 [-Wmissing-prototypes] no previous prototype for function 'CreateStreamHelper' xpcom/tests/gtest/TestNonBlockingAsyncInputStream.cpp:62:10 [-Wmissing-prototypes] no previous prototype for function 'ReadSegmentsFunction' xpcom/tests/gtest/TestNsDeque.cpp:240:6 [-Wmissing-prototypes] no previous prototype for function 'CheckIfQueueEmpty' xpcom/tests/gtest/TestNsRefPtr.cpp:105:10 [-Wmissing-prototypes] no previous prototype for function 'CreateFoo' xpcom/tests/gtest/TestNsRefPtr.cpp:116:6 [-Wmissing-prototypes] no previous prototype for function 'set_a_Foo' xpcom/tests/gtest/TestNsRefPtr.cpp:123:13 [-Wmissing-prototypes] no previous prototype for function 'return_a_Foo' xpcom/tests/gtest/TestNsRefPtr.cpp:391:6 [-Wmissing-prototypes] no previous prototype for function 'AnFooPtrPtrContext' xpcom/tests/gtest/TestNsRefPtr.cpp:392:6 [-Wmissing-prototypes] no previous prototype for function 'AVoidPtrPtrContext' xpcom/tests/gtest/TestPLDHash.cpp:33:6 [-Wmissing-prototypes] no previous prototype for function 'TestCrashyOperation' xpcom/tests/gtest/TestPipes.cpp:98:10 [-Wmissing-prototypes] no previous prototype for function 'TestPipe' xpcom/tests/gtest/TestPipes.cpp:212:10 [-Wmissing-prototypes] no previous prototype for function 'TestShortWrites' xpcom/tests/gtest/TestPipes.cpp:354:6 [-Wmissing-prototypes] no previous prototype for function 'RunTests' xpcom/tests/gtest/TestPLDHash.cpp:90:6 [-Wmissing-prototypes] no previous prototype for function 'InitCapacityOk_InitialLengthTooBig' xpcom/tests/gtest/TestPLDHash.cpp:95:6 [-Wmissing-prototypes] no previous prototype for function 'InitCapacityOk_InitialEntryStoreTooBig' xpcom/tests/gtest/TestPLDHash.cpp:102:6 [-Wmissing-prototypes] no previous prototype for function 'InitCapacityOk_EntrySizeTooBig' xpcom/tests/gtest/TestSlicedInputStream.cpp:111:20 [-Wmissing-prototypes] no previous prototype for function 'CreateSeekableStreams' xpcom/tests/gtest/TestSlicedInputStream.cpp:125:20 [-Wmissing-prototypes] no previous prototype for function 'CreateNonSeekableStreams' xpcom/tests/gtest/TestStrings.cpp:471:6 [-Wmissing-prototypes] no previous prototype for function 'test_assign_helper' xpcom/tests/gtest/TestTArray.cpp:60:22 [-Wmissing-prototypes] no previous prototype for function 'DummyArray' xpcom/tests/gtest/TestTArray.cpp:72:22 [-Wmissing-prototypes] no previous prototype for function 'FakeHugeArray' xpcom/tests/gtest/TestThrottledEventQueue.cpp:96:6 [-Wmissing-prototypes] no previous prototype for function 'Enqueue' xpcom/threads/BlockingResourceBase.cpp:86:6 [-Wmissing-prototypes] no previous prototype for function 'PrintCycle' xpcom/threads/CPUUsageWatcher.cpp:41:10 [-Wmissing-prototypes] no previous prototype for function 'GetMicroseconds' xpcom/threads/CPUUsageWatcher.cpp:46:10 [-Wmissing-prototypes] no previous prototype for function 'GetMicroseconds' xpcom/threads/CPUUsageWatcher.cpp:51:40 [-Wmissing-prototypes] no previous prototype for function 'GetProcessCPUStats' xpcom/threads/CPUUsageWatcher.cpp:80:40 [-Wmissing-prototypes] no previous prototype for function 'GetGlobalCPUStats' xpcom/threads/nsTimerImpl.cpp:196:21 [-Wmissing-prototypes] no previous prototype for function 'GetTimerFiringsLog' Differential Revision: https://phabricator.services.mozilla.com/D23264 --HG-- extra : rebase_source : e03df033209e0a08fc263603e78bc16a09467f15 extra : source : 3beec9fbfdedf346fff85309029e7805717958ac
253 lines
7.6 KiB
C++
253 lines
7.6 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/CPUUsageWatcher.h"
|
|
|
|
#include "prsystem.h"
|
|
|
|
#ifdef XP_MACOSX
|
|
# include <sys/resource.h>
|
|
# include <mach/clock.h>
|
|
# include <mach/mach_host.h>
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
|
|
#ifdef CPU_USAGE_WATCHER_ACTIVE
|
|
|
|
// Even if the machine only has one processor, tolerate up to 50%
|
|
// external CPU usage.
|
|
static const float kTolerableExternalCPUUsageFloor = 0.5f;
|
|
|
|
struct CPUStats {
|
|
// The average CPU usage time, which can be summed across all cores in the
|
|
// system, or averaged between them. Whichever it is, it needs to be in the
|
|
// same units as updateTime.
|
|
uint64_t usageTime;
|
|
// A monotonically increasing value in the same units as usageTime, which can
|
|
// be used to determine the percentage of active vs idle time
|
|
uint64_t updateTime;
|
|
};
|
|
|
|
# ifdef XP_MACOSX
|
|
|
|
static const uint64_t kMicrosecondsPerSecond = 1000000LL;
|
|
static const uint64_t kNanosecondsPerMicrosecond = 1000LL;
|
|
static const uint64_t kCPUCheckInterval = kMicrosecondsPerSecond / 2LL;
|
|
|
|
static uint64_t GetMicroseconds(timeval time) {
|
|
return ((uint64_t)time.tv_sec) * kMicrosecondsPerSecond +
|
|
(uint64_t)time.tv_usec;
|
|
}
|
|
|
|
static uint64_t GetMicroseconds(mach_timespec_t time) {
|
|
return ((uint64_t)time.tv_sec) * kMicrosecondsPerSecond +
|
|
((uint64_t)time.tv_nsec) / kNanosecondsPerMicrosecond;
|
|
}
|
|
|
|
static Result<CPUStats, CPUUsageWatcherError> GetProcessCPUStats(
|
|
int32_t numCPUs) {
|
|
CPUStats result = {};
|
|
rusage usage;
|
|
int32_t rusageResult = getrusage(RUSAGE_SELF, &usage);
|
|
if (rusageResult == -1) {
|
|
return Err(GetProcessTimesError);
|
|
}
|
|
result.usageTime =
|
|
GetMicroseconds(usage.ru_utime) + GetMicroseconds(usage.ru_stime);
|
|
|
|
clock_serv_t realtimeClock;
|
|
kern_return_t errorResult =
|
|
host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &realtimeClock);
|
|
if (errorResult != KERN_SUCCESS) {
|
|
return Err(GetProcessTimesError);
|
|
}
|
|
mach_timespec_t time;
|
|
errorResult = clock_get_time(realtimeClock, &time);
|
|
if (errorResult != KERN_SUCCESS) {
|
|
return Err(GetProcessTimesError);
|
|
}
|
|
result.updateTime = GetMicroseconds(time);
|
|
|
|
// getrusage will give us the sum of the values across all
|
|
// of our cores. Divide by the number of CPUs to get an average.
|
|
result.usageTime /= numCPUs;
|
|
return result;
|
|
}
|
|
|
|
static Result<CPUStats, CPUUsageWatcherError> GetGlobalCPUStats() {
|
|
CPUStats result = {};
|
|
host_cpu_load_info_data_t loadInfo;
|
|
mach_msg_type_number_t loadInfoCount = HOST_CPU_LOAD_INFO_COUNT;
|
|
kern_return_t statsResult =
|
|
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO,
|
|
(host_info_t)&loadInfo, &loadInfoCount);
|
|
if (statsResult != KERN_SUCCESS) {
|
|
return Err(HostStatisticsError);
|
|
}
|
|
|
|
result.usageTime = loadInfo.cpu_ticks[CPU_STATE_USER] +
|
|
loadInfo.cpu_ticks[CPU_STATE_NICE] +
|
|
loadInfo.cpu_ticks[CPU_STATE_SYSTEM];
|
|
result.updateTime = result.usageTime + loadInfo.cpu_ticks[CPU_STATE_IDLE];
|
|
return result;
|
|
}
|
|
|
|
# endif // XP_MACOSX
|
|
|
|
# ifdef XP_WIN
|
|
|
|
// A FILETIME represents the number of 100-nanosecond ticks since 1/1/1601 UTC
|
|
static const uint64_t kFILETIMETicksPerSecond = 10000000;
|
|
static const uint64_t kCPUCheckInterval = kFILETIMETicksPerSecond / 2;
|
|
|
|
uint64_t FiletimeToInteger(FILETIME filetime) {
|
|
return ((uint64_t)filetime.dwLowDateTime) | (uint64_t)filetime.dwHighDateTime
|
|
<< 32;
|
|
}
|
|
|
|
Result<CPUStats, CPUUsageWatcherError> GetProcessCPUStats(int32_t numCPUs) {
|
|
CPUStats result = {};
|
|
FILETIME creationFiletime;
|
|
FILETIME exitFiletime;
|
|
FILETIME kernelFiletime;
|
|
FILETIME userFiletime;
|
|
bool success = GetProcessTimes(GetCurrentProcess(), &creationFiletime,
|
|
&exitFiletime, &kernelFiletime, &userFiletime);
|
|
if (!success) {
|
|
return Err(GetProcessTimesError);
|
|
}
|
|
|
|
result.usageTime =
|
|
FiletimeToInteger(kernelFiletime) + FiletimeToInteger(userFiletime);
|
|
|
|
FILETIME nowFiletime;
|
|
GetSystemTimeAsFileTime(&nowFiletime);
|
|
result.updateTime = FiletimeToInteger(nowFiletime);
|
|
|
|
result.usageTime /= numCPUs;
|
|
|
|
return result;
|
|
}
|
|
|
|
Result<CPUStats, CPUUsageWatcherError> GetGlobalCPUStats() {
|
|
CPUStats result = {};
|
|
FILETIME idleFiletime;
|
|
FILETIME kernelFiletime;
|
|
FILETIME userFiletime;
|
|
bool success = GetSystemTimes(&idleFiletime, &kernelFiletime, &userFiletime);
|
|
|
|
if (!success) {
|
|
return Err(GetSystemTimesError);
|
|
}
|
|
|
|
result.usageTime =
|
|
FiletimeToInteger(kernelFiletime) + FiletimeToInteger(userFiletime);
|
|
result.updateTime = result.usageTime + FiletimeToInteger(idleFiletime);
|
|
|
|
return result;
|
|
}
|
|
|
|
# endif // XP_WIN
|
|
|
|
Result<Ok, CPUUsageWatcherError> CPUUsageWatcher::Init() {
|
|
mNumCPUs = PR_GetNumberOfProcessors();
|
|
if (mNumCPUs <= 0) {
|
|
mExternalUsageThreshold = 1.0f;
|
|
return Err(GetNumberOfProcessorsError);
|
|
}
|
|
mExternalUsageThreshold =
|
|
std::max(1.0f - 1.0f / (float)mNumCPUs, kTolerableExternalCPUUsageFloor);
|
|
|
|
CPUStats processTimes;
|
|
MOZ_TRY_VAR(processTimes, GetProcessCPUStats(mNumCPUs));
|
|
mProcessUpdateTime = processTimes.updateTime;
|
|
mProcessUsageTime = processTimes.usageTime;
|
|
|
|
CPUStats globalTimes;
|
|
MOZ_TRY_VAR(globalTimes, GetGlobalCPUStats());
|
|
mGlobalUpdateTime = globalTimes.updateTime;
|
|
mGlobalUsageTime = globalTimes.usageTime;
|
|
|
|
mInitialized = true;
|
|
|
|
CPUUsageWatcher* self = this;
|
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
"CPUUsageWatcher::Init",
|
|
[=]() { BackgroundHangMonitor::RegisterAnnotator(*self); }));
|
|
|
|
return Ok();
|
|
}
|
|
|
|
void CPUUsageWatcher::Uninit() {
|
|
if (mInitialized) {
|
|
BackgroundHangMonitor::UnregisterAnnotator(*this);
|
|
}
|
|
mInitialized = false;
|
|
}
|
|
|
|
Result<Ok, CPUUsageWatcherError> CPUUsageWatcher::CollectCPUUsage() {
|
|
if (!mInitialized) {
|
|
return Ok();
|
|
}
|
|
|
|
mExternalUsageRatio = 0.0f;
|
|
|
|
CPUStats processTimes;
|
|
MOZ_TRY_VAR(processTimes, GetProcessCPUStats(mNumCPUs));
|
|
CPUStats globalTimes;
|
|
MOZ_TRY_VAR(globalTimes, GetGlobalCPUStats());
|
|
|
|
uint64_t processUsageDelta = processTimes.usageTime - mProcessUsageTime;
|
|
uint64_t processUpdateDelta = processTimes.updateTime - mProcessUpdateTime;
|
|
float processUsageNormalized =
|
|
processUsageDelta > 0
|
|
? (float)processUsageDelta / (float)processUpdateDelta
|
|
: 0.0f;
|
|
|
|
uint64_t globalUsageDelta = globalTimes.usageTime - mGlobalUsageTime;
|
|
uint64_t globalUpdateDelta = globalTimes.updateTime - mGlobalUpdateTime;
|
|
float globalUsageNormalized =
|
|
globalUsageDelta > 0 ? (float)globalUsageDelta / (float)globalUpdateDelta
|
|
: 0.0f;
|
|
|
|
mProcessUsageTime = processTimes.usageTime;
|
|
mProcessUpdateTime = processTimes.updateTime;
|
|
mGlobalUsageTime = globalTimes.usageTime;
|
|
mGlobalUpdateTime = globalTimes.updateTime;
|
|
|
|
mExternalUsageRatio =
|
|
std::max(0.0f, globalUsageNormalized - processUsageNormalized);
|
|
|
|
return Ok();
|
|
}
|
|
|
|
void CPUUsageWatcher::AnnotateHang(BackgroundHangAnnotations& aAnnotations) {
|
|
if (!mInitialized) {
|
|
return;
|
|
}
|
|
|
|
if (mExternalUsageRatio > mExternalUsageThreshold) {
|
|
aAnnotations.AddAnnotation(NS_LITERAL_STRING("ExternalCPUHigh"), true);
|
|
}
|
|
}
|
|
|
|
#else // !CPU_USAGE_WATCHER_ACTIVE
|
|
|
|
Result<Ok, CPUUsageWatcherError> CPUUsageWatcher::Init() { return Ok(); }
|
|
|
|
void CPUUsageWatcher::Uninit() {}
|
|
|
|
Result<Ok, CPUUsageWatcherError> CPUUsageWatcher::CollectCPUUsage() {
|
|
return Ok();
|
|
}
|
|
|
|
void CPUUsageWatcher::AnnotateHang(BackgroundHangAnnotations& aAnnotations) {}
|
|
|
|
#endif // CPU_USAGE_WATCHER_ACTIVE
|
|
|
|
} // namespace mozilla
|