| Index: base/profiler/cpu_profiler.cc | 
| diff --git a/base/profiler/cpu_profiler.cc b/base/profiler/cpu_profiler.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..e664ca94967f55d773e122a2ad3b4f29c62d5900 | 
| --- /dev/null | 
| +++ b/base/profiler/cpu_profiler.cc | 
| @@ -0,0 +1,165 @@ | 
| +// Copyright 2015 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "base/profiler/cpu_profiler.h" | 
| + | 
| +#include <stddef.h> | 
| + | 
| +#include "base/debug/stack_trace.h" | 
| +#include "base/metrics/field_trial.h" | 
| +#include "base/strings/string_number_conversions.h" | 
| +#include "base/threading/thread_id_name_manager.h" | 
| +#include "base/time/time.h" | 
| +#include "base/timer/elapsed_timer.h" | 
| + | 
| +namespace base { | 
| + | 
| +namespace { | 
| + | 
| +const char kMode[] = "Mode"; | 
| +const char kInitialDelay[] = "InitialDelay"; | 
| +const char kNumberOfBursts[] = "NumberOfBursts"; | 
| +const char kBurstIdleTime[] = "IdleTime"; | 
| +const char kNumberOfSamples[] = "NumberOfSamples"; | 
| +const char kSamplingSleepTime[] = "SamplingSleepTime"; | 
| + | 
| +}  // namespace | 
| + | 
| +CpuProfiler* CpuProfiler::g_instance_ = NULL; | 
| + | 
| +SamplingThread::SamplingThread() | 
| +    : thread_running_(false), | 
| +      waitable_event_(false, false) { | 
| +} | 
| + | 
| +SamplingThread::~SamplingThread() {} | 
| + | 
| +void SamplingThread::ThreadMain() { | 
| +  PlatformThread::SetName("Chrome_CPUProfilerThread"); | 
| +  thread_running_ = true; | 
| + | 
| +  CpuProfiler* instance = CpuProfiler::GetInstance(); | 
| +  if (instance->GetStringParam(kMode) == "bursts") { | 
| +    int64 initial_delay = instance->GetInt64Param(kInitialDelay); | 
| +    int number_of_bursts = instance->GetIntParam(kNumberOfBursts); | 
| +    int64 burst_idle_time = instance->GetInt64Param(kBurstIdleTime); | 
| +    int number_of_samples = instance->GetIntParam(kNumberOfSamples); | 
| +    int64 sampling_sleep_time = instance->GetInt64Param(kSamplingSleepTime); | 
| + | 
| +    if (waitable_event_.TimedWait(TimeDelta::FromMicroseconds(initial_delay))) | 
| +      return; | 
| +    for (int i = 0; i < number_of_bursts; i++) { | 
| +      int64 delta = 0; | 
| +      for (int j = 0; ; j++) { | 
| +        base::ElapsedTimer time; | 
| +        GetSamples(); | 
| +        delta = time.Elapsed().InMicroseconds(); | 
| +        if (j == (number_of_samples - 1)) | 
| +          break; | 
| +        if (delta < sampling_sleep_time) { | 
| +          if (waitable_event_.TimedWait( | 
| +              TimeDelta::FromMicroseconds(sampling_sleep_time - delta))) | 
| +            return; | 
| +        } else { | 
| +          if (waitable_event_.TimedWait( | 
| +              TimeDelta::FromMicroseconds(sampling_sleep_time))) | 
| +            return; | 
| +        } | 
| +      } | 
| +      if (waitable_event_.TimedWait( | 
| +          TimeDelta::FromMicroseconds(burst_idle_time - delta))) | 
| +        return; | 
| +    } | 
| +  } | 
| +} | 
| + | 
| +void SamplingThread::Stop() { | 
| +  waitable_event_.Signal(); | 
| +} | 
| + | 
| +void SamplingThread::GetSamples() { | 
| +  CpuProfiler* instance = CpuProfiler::GetInstance(); | 
| +  instance->OnTimer(); | 
| +} | 
| + | 
| +// static | 
| +void CpuProfiler::Initialize(const std::map<std::string, std::string>& params) { | 
| +  if (!CpuProfiler::IsPlatformSupported()) | 
| +    return; | 
| + | 
| +  CpuProfiler* instance = CpuProfiler::GetInstance(); | 
| + | 
| +  // temp code ================== | 
| +  Map default_params; | 
| +  default_params[kMode] = "bursts"; | 
| +  default_params[kInitialDelay] = "2000000"; // 2 sec | 
| +  default_params[kNumberOfBursts] = "10"; | 
| +  default_params[kBurstIdleTime] = "10000000"; // 10 sec | 
| +  default_params[kNumberOfSamples] = "20"; | 
| +  default_params[kSamplingSleepTime] = "50000"; // 10 ms | 
| + | 
| +  if (params.empty()) | 
| +    instance->SetParams(default_params); | 
| +  else | 
| +  // end temp code ================== | 
| +    instance->SetParams(params); | 
| + | 
| +  instance->sampling_thread_.reset(new SamplingThread()); | 
| +  if (!PlatformThread::Create( | 
| +           0, instance->sampling_thread_.get(), | 
| +           &instance->sampling_thread_handle_)) { | 
| +        LOG(ERROR) << "failed to create thread"; | 
| +  } | 
| +} | 
| + | 
| +// static | 
| +CpuProfiler* CpuProfiler::GetInstance() { | 
| +  if (!g_instance_) { | 
| +    g_instance_ = new CpuProfiler(); | 
| +  } | 
| +  return g_instance_; | 
| +} | 
| + | 
| +// static | 
| +void CpuProfiler::Stop() { | 
| +  CpuProfiler* instance = CpuProfiler::GetInstance(); | 
| +  if (instance && instance->sampling_thread_) | 
| +    instance->sampling_thread_->Stop(); | 
| +} | 
| + | 
| + | 
| +std::string CpuProfiler::GetStringParam(const std::string& key) { | 
| +  const Map::const_iterator entry = params_.find(key); | 
| +  if (entry != params_.end()) { | 
| +    return entry->second; | 
| +  } | 
| +  return ""; | 
| +} | 
| + | 
| +int CpuProfiler::GetIntParam(const std::string& key) { | 
| +  const Map::const_iterator entry = params_.find(key); | 
| +  if (entry != params_.end()) { | 
| +    int output; | 
| +    if (base::StringToInt(entry->second, &output)) | 
| +      return output; | 
| +  } | 
| +  return 0; | 
| +} | 
| + | 
| +int64 CpuProfiler::GetInt64Param(const std::string& key) { | 
| +  const Map::const_iterator entry = params_.find(key); | 
| +  if (entry != params_.end()) { | 
| +    int64 output; | 
| +    if (base::StringToInt64(entry->second, &output)) | 
| +      return output; | 
| +  } | 
| +  return 0; | 
| +} | 
| + | 
| +void CpuProfiler::SetParams( | 
| +    const std::map<std::string, std::string>& params) { | 
| +  params_ = params; | 
| +} | 
| + | 
| +} | 
|  |