Linux logs were not displaying time at ms resolution.
Review URL: https://webrtc-codereview.appspot.com/267012 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1644 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
a8084b07e3
commit
0e7c060256
127
src/system_wrappers/source/cpu_measurement_harness.cc
Normal file
127
src/system_wrappers/source/cpu_measurement_harness.cc
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 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 "system_wrappers/interface/cpu_wrapper.h"
|
||||||
|
#include "system_wrappers/interface/event_wrapper.h"
|
||||||
|
#include "system_wrappers/interface/scoped_ptr.h"
|
||||||
|
#include "system_wrappers/source/cpu_measurement_harness.h"
|
||||||
|
|
||||||
|
const int kCpuCheckPeriodMs = 100;
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
CpuMeasurementHarness* CpuMeasurementHarness::Create(
|
||||||
|
CpuTarget* target,
|
||||||
|
int work_period_ms,
|
||||||
|
int work_iterations_per_period,
|
||||||
|
int duration_ms) {
|
||||||
|
if (target == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (work_period_ms > duration_ms) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (work_period_ms < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (duration_ms < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (work_iterations_per_period < 1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return new CpuMeasurementHarness(target, work_period_ms,
|
||||||
|
work_iterations_per_period, duration_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
CpuMeasurementHarness::CpuMeasurementHarness(CpuTarget* target,
|
||||||
|
int work_period_ms,
|
||||||
|
int work_iterations_per_period,
|
||||||
|
int duration_ms)
|
||||||
|
: cpu_target_(target),
|
||||||
|
work_period_ms_(work_period_ms),
|
||||||
|
work_iterations_per_period_(work_iterations_per_period),
|
||||||
|
duration_ms_(duration_ms),
|
||||||
|
cpu_sum_(0),
|
||||||
|
cpu_iterations_(0),
|
||||||
|
cpu_(CpuWrapper::CreateCpu()),
|
||||||
|
event_(EventWrapper::Create()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CpuMeasurementHarness::~CpuMeasurementHarness() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CpuMeasurementHarness::Run() {
|
||||||
|
if (!WaitForCpuInit()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// No need for precision. Run for approximately the asked for duration.
|
||||||
|
// TODO(hellner): very low prio if at all, the actual duration of the test
|
||||||
|
// will be longer if calling DoWork() is not negligable and/or called many
|
||||||
|
// times. It may make sense to compensate for drift here. This will,
|
||||||
|
// however, only add complexity with minimal gains. Perhaps renaming the
|
||||||
|
// duration_ms_ to something more fuzzy is a better idea. However, the name
|
||||||
|
// would be very convoluted if it is to be self documenting.
|
||||||
|
int elapsed_time_ms = 0;
|
||||||
|
int last_measured_time = 0;
|
||||||
|
while (elapsed_time_ms < duration_ms_) {
|
||||||
|
if (((elapsed_time_ms - last_measured_time) / kCpuCheckPeriodMs) >= 1) {
|
||||||
|
last_measured_time = elapsed_time_ms;
|
||||||
|
Measure();
|
||||||
|
}
|
||||||
|
if (!DoWork()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
event_->Wait(work_period_ms_);
|
||||||
|
elapsed_time_ms += work_period_ms_;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CpuMeasurementHarness::AverageCpu() {
|
||||||
|
if (cpu_iterations_ == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert(cpu_sum_ >= 0);
|
||||||
|
assert(cpu_iterations_ >= 0);
|
||||||
|
return cpu_sum_ / cpu_iterations_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CpuMeasurementHarness::WaitForCpuInit() {
|
||||||
|
bool cpu_usage_available = false;
|
||||||
|
int num_iterations = 0;
|
||||||
|
// Initializing the CPU measurements may take a couple of seconds on Windows.
|
||||||
|
// Since the initialization is lazy we need to wait until it is completed.
|
||||||
|
// Should not take more than 10000 ms.
|
||||||
|
while (!cpu_usage_available && (++num_iterations < 10000)) {
|
||||||
|
event_->Wait(1);
|
||||||
|
cpu_usage_available = cpu_->CpuUsage() != -1;
|
||||||
|
}
|
||||||
|
return cpu_usage_available;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CpuMeasurementHarness::Measure() {
|
||||||
|
WebRtc_UWord32 num_cores = 0;
|
||||||
|
WebRtc_UWord32* cores = NULL;
|
||||||
|
// Return the average CPU for now.
|
||||||
|
cpu_sum_ = cpu_->CpuUsageMultiCore(num_cores, cores);
|
||||||
|
++cpu_iterations_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CpuMeasurementHarness::DoWork() {
|
||||||
|
for (int i = 0; i < work_iterations_per_period_; ++i) {
|
||||||
|
if (!cpu_target_->DoWork()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
66
src/system_wrappers/source/cpu_measurement_harness.h
Normal file
66
src/system_wrappers/source/cpu_measurement_harness.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 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 SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
|
||||||
|
#define SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
|
||||||
|
|
||||||
|
#include "system_wrappers/interface/scoped_ptr.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
class CpuWrapper;
|
||||||
|
class EventWrapper;
|
||||||
|
class ThreadWrapper;
|
||||||
|
|
||||||
|
// This abstract class provides an interface that should be passed to
|
||||||
|
// CpuMeasurementHarness. CpuMeasurementHarness will call it with the
|
||||||
|
// frequency requested and measure the CPU usage for all calls.
|
||||||
|
class CpuTarget {
|
||||||
|
public:
|
||||||
|
// Callback function for which the CPU usage should be calculated.
|
||||||
|
virtual bool DoWork() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CpuTarget() {}
|
||||||
|
virtual ~CpuTarget() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CpuMeasurementHarness {
|
||||||
|
public:
|
||||||
|
static CpuMeasurementHarness* Create(CpuTarget* target,
|
||||||
|
int work_period_ms,
|
||||||
|
int work_iterations_per_period,
|
||||||
|
int duration_ms);
|
||||||
|
~CpuMeasurementHarness();
|
||||||
|
bool Run();
|
||||||
|
int AverageCpu();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CpuMeasurementHarness(CpuTarget* target, int work_period_ms,
|
||||||
|
int work_iterations_per_period, int duration_ms);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool WaitForCpuInit();
|
||||||
|
void Measure();
|
||||||
|
bool DoWork();
|
||||||
|
|
||||||
|
CpuTarget* cpu_target_;
|
||||||
|
const int work_period_ms_;
|
||||||
|
const int work_iterations_per_period_;
|
||||||
|
const int duration_ms_;
|
||||||
|
int cpu_sum_;
|
||||||
|
int cpu_iterations_;
|
||||||
|
scoped_ptr<CpuWrapper> cpu_;
|
||||||
|
scoped_ptr<EventWrapper> event_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
|
@ -159,6 +159,8 @@
|
|||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'cpu_wrapper_unittest.cc',
|
'cpu_wrapper_unittest.cc',
|
||||||
|
'cpu_measurement_harness.h',
|
||||||
|
'cpu_measurement_harness.cc',
|
||||||
'list_unittest.cc',
|
'list_unittest.cc',
|
||||||
'map_unittest.cc',
|
'map_unittest.cc',
|
||||||
'data_log_unittest.cc',
|
'data_log_unittest.cc',
|
||||||
@ -166,6 +168,7 @@
|
|||||||
'data_log_helpers_unittest.cc',
|
'data_log_helpers_unittest.cc',
|
||||||
'data_log_c_helpers_unittest.c',
|
'data_log_c_helpers_unittest.c',
|
||||||
'data_log_c_helpers_unittest.h',
|
'data_log_c_helpers_unittest.h',
|
||||||
|
'trace_unittest.cc',
|
||||||
],
|
],
|
||||||
'conditions': [
|
'conditions': [
|
||||||
['enable_data_logging==1', {
|
['enable_data_logging==1', {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Use of this source code is governed by a BSD-style license
|
* 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
|
* that can be found in the LICENSE file in the root of the source
|
||||||
@ -14,6 +14,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#ifdef WEBRTC_ANDROID
|
#ifdef WEBRTC_ANDROID
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@ -38,8 +39,9 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
TracePosix::TracePosix()
|
TracePosix::TracePosix()
|
||||||
{
|
{
|
||||||
_prevAPITickCount = time(NULL);
|
struct timeval systemTimeHighRes;
|
||||||
_prevTickCount = _prevAPITickCount;
|
gettimeofday(&systemTimeHighRes, 0);
|
||||||
|
_prevAPITickCount = _prevTickCount = systemTimeHighRes.tv_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
TracePosix::~TracePosix()
|
TracePosix::~TracePosix()
|
||||||
@ -50,53 +52,43 @@ TracePosix::~TracePosix()
|
|||||||
WebRtc_Word32 TracePosix::AddTime(char* traceMessage,
|
WebRtc_Word32 TracePosix::AddTime(char* traceMessage,
|
||||||
const TraceLevel level) const
|
const TraceLevel level) const
|
||||||
{
|
{
|
||||||
time_t dwCurrentTimeInSeconds = time(NULL);
|
struct timeval systemTimeHighRes;
|
||||||
struct tm systemTime;
|
if (gettimeofday(&systemTimeHighRes, 0) == -1)
|
||||||
gmtime_r(&dwCurrentTimeInSeconds, &systemTime);
|
|
||||||
|
|
||||||
if(level == kTraceApiCall)
|
|
||||||
{
|
{
|
||||||
WebRtc_UWord32 dwDeltaTime = dwCurrentTimeInSeconds - _prevTickCount;
|
return -1;
|
||||||
_prevTickCount = dwCurrentTimeInSeconds;
|
|
||||||
|
|
||||||
if(_prevTickCount == 0)
|
|
||||||
{
|
|
||||||
dwDeltaTime = 0;
|
|
||||||
}
|
|
||||||
if(dwDeltaTime > 0x0fffffff)
|
|
||||||
{
|
|
||||||
// Either wraparound or data race.
|
|
||||||
dwDeltaTime = 0;
|
|
||||||
}
|
|
||||||
if(dwDeltaTime > 99999)
|
|
||||||
{
|
|
||||||
dwDeltaTime = 99999;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.tm_hour,
|
|
||||||
systemTime.tm_min, systemTime.tm_sec, 0,
|
|
||||||
static_cast<unsigned long>(dwDeltaTime));
|
|
||||||
} else {
|
|
||||||
WebRtc_UWord32 dwDeltaTime = dwCurrentTimeInSeconds - _prevAPITickCount;
|
|
||||||
_prevAPITickCount = dwCurrentTimeInSeconds;
|
|
||||||
if(_prevAPITickCount == 0)
|
|
||||||
{
|
|
||||||
dwDeltaTime = 0;
|
|
||||||
}
|
|
||||||
if(dwDeltaTime > 0x0fffffff)
|
|
||||||
{
|
|
||||||
// Either wraparound or data race.
|
|
||||||
dwDeltaTime = 0;
|
|
||||||
}
|
|
||||||
if(dwDeltaTime > 99999)
|
|
||||||
{
|
|
||||||
dwDeltaTime = 99999;
|
|
||||||
}
|
|
||||||
sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.tm_hour,
|
|
||||||
systemTime.tm_min, systemTime.tm_sec, 0,
|
|
||||||
static_cast<unsigned long>(dwDeltaTime));
|
|
||||||
}
|
}
|
||||||
// Messages is 22 characters.
|
const struct tm* systemTime =
|
||||||
|
localtime(&systemTimeHighRes.tv_sec);
|
||||||
|
|
||||||
|
const WebRtc_UWord32 ms_time = systemTimeHighRes.tv_usec / 1000;
|
||||||
|
WebRtc_UWord32 prevTickCount = 0;
|
||||||
|
if (level == kTraceApiCall)
|
||||||
|
{
|
||||||
|
prevTickCount = _prevTickCount;
|
||||||
|
_prevTickCount = ms_time;
|
||||||
|
} else {
|
||||||
|
prevTickCount = _prevAPITickCount;
|
||||||
|
_prevAPITickCount = ms_time;
|
||||||
|
}
|
||||||
|
WebRtc_UWord32 dwDeltaTime = ms_time - prevTickCount;
|
||||||
|
if (prevTickCount == 0)
|
||||||
|
{
|
||||||
|
dwDeltaTime = 0;
|
||||||
|
}
|
||||||
|
if (dwDeltaTime > 0x0fffffff)
|
||||||
|
{
|
||||||
|
// Either wraparound or data race.
|
||||||
|
dwDeltaTime = 0;
|
||||||
|
}
|
||||||
|
if(dwDeltaTime > 99999)
|
||||||
|
{
|
||||||
|
dwDeltaTime = 99999;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime->tm_hour,
|
||||||
|
systemTime->tm_min, systemTime->tm_sec, ms_time,
|
||||||
|
static_cast<unsigned long>(dwDeltaTime));
|
||||||
|
// Messages are 22 characters.
|
||||||
return 22;
|
return 22;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
57
src/system_wrappers/source/trace_unittest.cc
Normal file
57
src/system_wrappers/source/trace_unittest.cc
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 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 "system_wrappers/interface/trace.h"
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "system_wrappers/source/cpu_measurement_harness.h"
|
||||||
|
#include "testsupport/fileutils.h"
|
||||||
|
|
||||||
|
using webrtc::CpuMeasurementHarness;
|
||||||
|
using webrtc::Trace;
|
||||||
|
using webrtc::kTraceWarning;
|
||||||
|
using webrtc::kTraceUtility;
|
||||||
|
|
||||||
|
class Logger : public webrtc::CpuTarget {
|
||||||
|
public:
|
||||||
|
Logger() {
|
||||||
|
Trace::CreateTrace();
|
||||||
|
std::string trace_file = webrtc::test::OutputPath() +
|
||||||
|
"trace_unittest.txt";
|
||||||
|
Trace::SetTraceFile(trace_file.c_str());
|
||||||
|
Trace::SetLevelFilter(webrtc::kTraceAll);
|
||||||
|
}
|
||||||
|
virtual ~Logger() {
|
||||||
|
Trace::ReturnTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool DoWork() {
|
||||||
|
// Use input paremeters to WEBRTC_TRACE that are not likely to be removed
|
||||||
|
// in future code. E.g. warnings will likely be kept and this file is in
|
||||||
|
// utility so it should use kTraceUtility.
|
||||||
|
WEBRTC_TRACE(kTraceWarning, kTraceUtility, 0, "Log line");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This test is disabled because it measures CPU usage. This is flaky because
|
||||||
|
// the CPU usage for a machine may spike due to OS or other application.
|
||||||
|
TEST(TraceTest, DISABLED_CpuUsage) {
|
||||||
|
Logger logger;
|
||||||
|
const int periodicity_ms = 1;
|
||||||
|
const int iterations_per_period = 10;
|
||||||
|
const int duration_ms = 1000;
|
||||||
|
CpuMeasurementHarness* cpu_harness =
|
||||||
|
CpuMeasurementHarness::Create(&logger, periodicity_ms,
|
||||||
|
iterations_per_period, duration_ms);
|
||||||
|
cpu_harness->Run();
|
||||||
|
const int average_cpu = cpu_harness->AverageCpu();
|
||||||
|
EXPECT_GE(5, average_cpu);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user