Added GetCpuTime to base/ to get total CPU time consumed by process for perf tests.
BUG=webrtc:7095 Review-Url: https://codereview.webrtc.org/2695743003 Cr-Commit-Position: refs/heads/master@{#16665}
This commit is contained in:
parent
c7bf32a110
commit
3ff474b72b
@ -682,6 +682,8 @@ if (rtc_include_tests) {
|
||||
sources = [
|
||||
# Also use this as a convenient dumping ground for misc files that are
|
||||
# included by multiple targets below.
|
||||
"cpu_time.cc",
|
||||
"cpu_time.h",
|
||||
"fakeclock.cc",
|
||||
"fakeclock.h",
|
||||
"fakenetwork.h",
|
||||
@ -763,6 +765,7 @@ if (rtc_include_tests) {
|
||||
"bytebuffer_unittest.cc",
|
||||
"byteorder_unittest.cc",
|
||||
"copyonwritebuffer_unittest.cc",
|
||||
"cpu_time_unittest.cc",
|
||||
"criticalsection_unittest.cc",
|
||||
"event_tracer_unittest.cc",
|
||||
"event_unittest.cc",
|
||||
|
||||
114
webrtc/base/cpu_time.cc
Normal file
114
webrtc/base/cpu_time.cc
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/base/cpu_time.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/timeutils.h"
|
||||
|
||||
#if defined(WEBRTC_LINUX)
|
||||
#include <time.h>
|
||||
#elif defined(WEBRTC_MAC)
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/times.h>
|
||||
#include <mach/thread_info.h>
|
||||
#include <mach/thread_act.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <unistd.h>
|
||||
#elif defined(WEBRTC_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
namespace {
|
||||
// FILETIME resolution is 100 nanosecs.
|
||||
const int64_t kNanosecsPerFiletime = 100;
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
namespace rtc {
|
||||
|
||||
int64_t GetProcessCpuTimeNanos() {
|
||||
#if defined(WEBRTC_LINUX)
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
|
||||
return ts.tv_sec * kNumNanosecsPerSec + ts.tv_nsec;
|
||||
} else {
|
||||
LOG_ERR(LS_ERROR) << "clock_gettime() failed.";
|
||||
}
|
||||
#elif defined(WEBRTC_MAC)
|
||||
struct rusage rusage;
|
||||
if (getrusage(RUSAGE_SELF, &rusage) == 0) {
|
||||
return rusage.ru_utime.tv_sec * kNumNanosecsPerSec +
|
||||
rusage.ru_utime.tv_usec * kNumNanosecsPerMicrosec;
|
||||
} else {
|
||||
LOG_ERR(LS_ERROR) << "getrusage() failed.";
|
||||
}
|
||||
#elif defined(WEBRTC_WIN)
|
||||
FILETIME createTime;
|
||||
FILETIME exitTime;
|
||||
FILETIME kernelTime;
|
||||
FILETIME userTime;
|
||||
if (GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime,
|
||||
&userTime) != 0) {
|
||||
return ((static_cast<uint64_t>(userTime.dwHighDateTime) << 32) +
|
||||
userTime.dwLowDateTime) *
|
||||
kNanosecsPerFiletime;
|
||||
} else {
|
||||
LOG_ERR(LS_ERROR) << "GetProcessTimes() failed.";
|
||||
}
|
||||
#else
|
||||
// Not implemented yet.
|
||||
static_assert(
|
||||
false, "GetProcessCpuTimeNanos() platform support not yet implemented.");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t GetThreadCpuTimeNanos() {
|
||||
#if defined(WEBRTC_LINUX)
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) {
|
||||
return ts.tv_sec * kNumNanosecsPerSec + ts.tv_nsec;
|
||||
} else {
|
||||
LOG_ERR(LS_ERROR) << "clock_gettime() failed.";
|
||||
}
|
||||
#elif defined(WEBRTC_MAC)
|
||||
thread_basic_info_data_t info;
|
||||
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
||||
if (thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)&info,
|
||||
&count) == KERN_SUCCESS) {
|
||||
return info.user_time.seconds * kNumNanosecsPerSec +
|
||||
info.user_time.microseconds * kNumNanosecsPerMicrosec;
|
||||
} else {
|
||||
LOG_ERR(LS_ERROR) << "thread_info() failed.";
|
||||
}
|
||||
#elif defined(WEBRTC_WIN)
|
||||
FILETIME createTime;
|
||||
FILETIME exitTime;
|
||||
FILETIME kernelTime;
|
||||
FILETIME userTime;
|
||||
if (GetThreadTimes(GetCurrentThread(), &createTime, &exitTime, &kernelTime,
|
||||
&userTime) != 0) {
|
||||
return ((static_cast<uint64_t>(userTime.dwHighDateTime) << 32) +
|
||||
userTime.dwLowDateTime) *
|
||||
kNanosecsPerFiletime;
|
||||
} else {
|
||||
LOG_ERR(LS_ERROR) << "GetThreadTimes() failed.";
|
||||
}
|
||||
#else
|
||||
// Not implemented yet.
|
||||
static_assert(
|
||||
false, "GetProcessCpuTimeNanos() platform support not yet implemented.");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
28
webrtc/base/cpu_time.h
Normal file
28
webrtc/base/cpu_time.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_CPU_TIME_H_
|
||||
#define WEBRTC_BASE_CPU_TIME_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Returns total CPU time of a current process in nanoseconds.
|
||||
// Time base is unknown, therefore use only to calculate deltas.
|
||||
int64_t GetProcessCpuTimeNanos();
|
||||
|
||||
// Returns total CPU time of a current thread in nanoseconds.
|
||||
// Time base is unknown, therefore use only to calculate deltas.
|
||||
int64_t GetThreadCpuTimeNanos();
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_CPU_TIME_H_
|
||||
108
webrtc/base/cpu_time_unittest.cc
Normal file
108
webrtc/base/cpu_time_unittest.cc
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include "webrtc/base/cpu_time.h"
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
#include "webrtc/base/timeutils.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
#include "webrtc/system_wrappers/include/cpu_info.h"
|
||||
|
||||
namespace {
|
||||
const int kAllowedErrorMillisecs = 30;
|
||||
const int kProcessingTimeMillisecs = 300;
|
||||
|
||||
// Consumes approximately kProcessingTimeMillisecs of CPU time.
|
||||
bool WorkingFunction(void* counter_pointer) {
|
||||
int64_t* counter = reinterpret_cast<int64_t*>(counter_pointer);
|
||||
*counter = 0;
|
||||
int64_t stop_time = rtc::SystemTimeNanos() +
|
||||
kProcessingTimeMillisecs * rtc::kNumNanosecsPerMillisec;
|
||||
while (rtc::SystemTimeNanos() < stop_time) {
|
||||
(*counter)++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace rtc {
|
||||
|
||||
TEST(GetProcessCpuTimeTest, SingleThread) {
|
||||
int64_t start_time_nanos = GetProcessCpuTimeNanos();
|
||||
int64_t counter;
|
||||
WorkingFunction(reinterpret_cast<void*>(&counter));
|
||||
EXPECT_GT(counter, 0);
|
||||
int64_t duration_nanos = GetProcessCpuTimeNanos() - start_time_nanos;
|
||||
// Should be about kProcessingTimeMillisecs.
|
||||
EXPECT_NEAR(duration_nanos,
|
||||
kProcessingTimeMillisecs * kNumNanosecsPerMillisec,
|
||||
kAllowedErrorMillisecs * kNumNanosecsPerMillisec);
|
||||
}
|
||||
|
||||
TEST(GetProcessCpuTimeTest, TwoThreads) {
|
||||
int64_t start_time_nanos = GetProcessCpuTimeNanos();
|
||||
int64_t counter1;
|
||||
int64_t counter2;
|
||||
PlatformThread thread1(WorkingFunction, reinterpret_cast<void*>(&counter1),
|
||||
"Thread1");
|
||||
PlatformThread thread2(WorkingFunction, reinterpret_cast<void*>(&counter2),
|
||||
"Thread2");
|
||||
thread1.Start();
|
||||
thread2.Start();
|
||||
thread1.Stop();
|
||||
thread2.Stop();
|
||||
|
||||
EXPECT_GE(counter1, 0);
|
||||
EXPECT_GE(counter2, 0);
|
||||
int64_t duration_nanos = GetProcessCpuTimeNanos() - start_time_nanos;
|
||||
const uint32_t kWorkingThreads = 2;
|
||||
uint32_t used_cores =
|
||||
std::min(webrtc::CpuInfo::DetectNumberOfCores(), kWorkingThreads);
|
||||
// Two working threads for kProcessingTimeMillisecs consume double CPU time
|
||||
// if there are at least 2 cores.
|
||||
EXPECT_NEAR(duration_nanos,
|
||||
used_cores * kProcessingTimeMillisecs * kNumNanosecsPerMillisec,
|
||||
used_cores * kAllowedErrorMillisecs * kNumNanosecsPerMillisec);
|
||||
}
|
||||
|
||||
TEST(GetThreadCpuTimeTest, SingleThread) {
|
||||
int64_t start_times_nanos = GetThreadCpuTimeNanos();
|
||||
int64_t counter;
|
||||
WorkingFunction(reinterpret_cast<void*>(&counter));
|
||||
EXPECT_GT(counter, 0);
|
||||
int64_t duration_nanos = GetThreadCpuTimeNanos() - start_times_nanos;
|
||||
EXPECT_NEAR(duration_nanos,
|
||||
kProcessingTimeMillisecs * kNumNanosecsPerMillisec,
|
||||
kAllowedErrorMillisecs * kNumNanosecsPerMillisec);
|
||||
}
|
||||
|
||||
TEST(GetThreadCpuTimeTest, TwoThreads) {
|
||||
int64_t start_time_nanos = GetThreadCpuTimeNanos();
|
||||
int64_t counter1;
|
||||
int64_t counter2;
|
||||
PlatformThread thread1(WorkingFunction, reinterpret_cast<void*>(&counter1),
|
||||
"Thread1");
|
||||
PlatformThread thread2(WorkingFunction, reinterpret_cast<void*>(&counter2),
|
||||
"Thread2");
|
||||
thread1.Start();
|
||||
thread2.Start();
|
||||
thread1.Stop();
|
||||
thread2.Stop();
|
||||
|
||||
EXPECT_GE(counter1, 0);
|
||||
EXPECT_GE(counter2, 0);
|
||||
int64_t duration_nanos = GetThreadCpuTimeNanos() - start_time_nanos;
|
||||
// This thread didn't do any work.
|
||||
EXPECT_NEAR(duration_nanos, 0,
|
||||
kAllowedErrorMillisecs * kNumNanosecsPerMillisec);
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
Loading…
x
Reference in New Issue
Block a user