1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/swap_metrics.h" 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string> 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <vector> 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/shell.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/file_util.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/files/file_path.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/metrics/histogram.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_number_conversions.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_util.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/stringprintf.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/synchronization/cancellation_flag.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/sys_info.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/threading/sequenced_worker_pool.h" 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/browser.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/browser_list.h" 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/tabs/tab_strip_model.h" 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/browser_thread.h" 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/events/event.h" 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing base::FilePath; 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace chromeos { 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Time delays for metrics collections, starting after an interesting UI event. 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Times are relative to the UI event. Start with zero to record the initial 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// state of the metrics immediately. 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kMetricsDelayMs[] = { 0, 100, 300, 1000, 3000 }; 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/////////////////////////////////////////////////////////////////////////////// 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Runs in the blocking thread pool to load metrics and record them. 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Reads data about CPU utilization and swap activity from the /proc and /sys 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// file systems. Owned by SwapMetrics on the UI thread. 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass SwapMetrics::Backend : public base::RefCountedThreadSafe<Backend> { 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch explicit Backend(const std::string& reason); 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Records one set of statistics for |time_index| after the interesting 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // event. May trigger another delayed task to record more statistics. 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void RecordMetricsOnBlockingPool(size_t time_index); 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Sets the thread-safe cancellation flag. 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void CancelOnUIThread() { cancelled_.Set(); } 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch friend class base::RefCountedThreadSafe<Backend>; 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~Backend(); 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Extracts a field value from a list of name-value pairs 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // in a file (typically a /proc or /sys file). Returns false 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // if the field is not found, or for other errors. 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool GetFieldFromKernelOutput(const std::string& path, 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& field, 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int64* value); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Reads a file whose content is a single line, and returns its content as a 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // list of tokens. |expected_tokens_count| is the expected number of tokens. 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // |delimiters| is a string containing characters that may appear between 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // tokens. Returns true on success, false otherwise. 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool TokenizeOneLineFile(const std::string& path, 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t expected_tokens_count, 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& delimiters, 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<std::string>* tokens); 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Retrieve various system metrics. Return true on success. 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool GetMeminfoField(const std::string& field, int64* value); 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool GetUptime(double* uptime_secs, double* idle_time_secs); 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool GetPageFaults(int64* page_faults); 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Record histogram samples. 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void RecordFaultsHistogramSample(int faults, 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& reason, 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int swap_group, 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int time_index); 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void RecordCpuHistogramSample(int cpu, 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& reason, 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int swap_group, 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int time_index); 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Cancellation flag that can be written from the UI thread (which owns this 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // object) and read from any thread. 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::CancellationFlag cancelled_; 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Data initialized once and shared by all instances of this class. 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static bool first_time_; 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static int64 swap_total_kb_; 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static int number_of_cpus_; 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Values at the beginning of each sampling interval. 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double last_uptime_secs_; 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double last_idle_time_secs_; 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int64 last_page_faults_; 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Swap group for a set of samples, chosen at the beginning of the set. 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int swap_group_; 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Reason for sampling. 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string reason_; 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DISALLOW_COPY_AND_ASSIGN(Backend); 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool SwapMetrics::Backend::first_time_ = true; 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint64 SwapMetrics::Backend::swap_total_kb_ = 0; 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint SwapMetrics::Backend::number_of_cpus_ = 0; 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSwapMetrics::Backend::Backend(const std::string& reason) 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : last_uptime_secs_(0.0), 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch last_idle_time_secs_(0.0), 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch last_page_faults_(0), 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch swap_group_(0), 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch reason_(reason) { 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSwapMetrics::Backend::~Backend() { 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::Backend::RecordMetricsOnBlockingPool(size_t time_index) { 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Another UI event might have occurred. Don't run this metrics collection 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // and don't post another task. This object's refcount will drop and it will 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // be deleted when the next backend is created on the UI thread. 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (cancelled_.IsSet()) 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DVLOG(1) << "RecordMetricsInBlockingPool " << time_index; 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // At init time, get the number of cpus and the total swap. The number of cpus 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // is necessary because the idle time reported is the sum of the idle 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // times of all cpus. 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // When an event occurs: 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // - At time t_0, save the initial values for uptime, idle_time, page_faults, 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // and swap used. 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // - At time t_i, compute cpu utilization as a fraction (1 = fully utilized): 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // utilization = 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // 1 - (idle_time_i - idle_time_0) / (uptime_i - uptime_0) / ncpus 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // then UMA-report it in the right swap group. Do the same for page faults. 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (first_time_) { 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch first_time_ = false; 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch number_of_cpus_ = base::SysInfo::NumberOfProcessors(); 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Avoid divide by zero in case of errors. 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (number_of_cpus_ == 0) 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch number_of_cpus_ = 1; 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetMeminfoField("SwapTotal:", &swap_total_kb_); 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (time_index == 0) { 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Record baseline data. 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetUptime(&last_uptime_secs_, &last_idle_time_secs_); 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetPageFaults(&last_page_faults_); 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int64 swap_free_kb = 0; 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetMeminfoField("SwapFree:", &swap_free_kb); 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int swap_percent = swap_total_kb_ > 0 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ? (swap_total_kb_ - swap_free_kb) * 100 / swap_total_kb_ 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : 0; 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (swap_percent < 10) 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch swap_group_ = 0; 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else if (swap_percent < 30) 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch swap_group_ = 1; 177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else if (swap_percent < 60) 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch swap_group_ = 2; 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch swap_group_ = 3; 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int64 page_faults = 0; 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double idle_time_secs = 0.0; 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double uptime_secs = 0.0; 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetUptime(&uptime_secs, &idle_time_secs); 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetPageFaults(&page_faults); 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double delta_time_secs = uptime_secs - last_uptime_secs_; 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Unexpected, but not worth agonizing over it. 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (delta_time_secs == 0) 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int cpu = (1.0 - (idle_time_secs - last_idle_time_secs_) / 193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delta_time_secs / number_of_cpus_) * 100; 194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int faults_per_sec = (page_faults - last_page_faults_) / delta_time_secs; 195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordCpuHistogramSample(cpu, reason_, swap_group_, time_index); 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordFaultsHistogramSample(faults_per_sec, reason_, 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch swap_group_, time_index); 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch last_uptime_secs_ = uptime_secs; 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch last_page_faults_ = page_faults; 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch last_idle_time_secs_ = idle_time_secs; 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Check if another metrics recording is needed. 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (++time_index >= arraysize(kMetricsDelayMs)) 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PostTaskRecordMetrics( 209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<Backend>(this), 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch time_index, 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kMetricsDelayMs[time_index] - kMetricsDelayMs[time_index - 1]); 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::Backend::RecordFaultsHistogramSample( 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int faults, 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& reason, 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int swap_group, 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int time_index) { 219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string name = 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::StringPrintf("Platform.SwapJank.%s.Faults.Swap%d.Time%d", 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch reason.c_str(), 222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch swap_group, 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch time_index); 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int kMinimumBucket = 10; 225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int kMaximumBucket = 200000; 226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const size_t kBucketCount = 50; 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::HistogramBase* counter = 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Histogram::FactoryGet(name, 229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kMinimumBucket, 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kMaximumBucket, 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kBucketCount, 232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Histogram::kUmaTargetedHistogramFlag); 233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch counter->Add(faults); 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::Backend::RecordCpuHistogramSample(int cpu, 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& reason, 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int swap_group, 239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int time_index) { 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string name = 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::StringPrintf("Platform.SwapJank.%s.Cpu.Swap%d.Time%d", 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch reason.c_str(), 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch swap_group, 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch time_index); 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int kMinimumBucket = 0; 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int kMaximumBucket = 101; 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const size_t kBucketCount = 102; 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::HistogramBase* counter = base::LinearHistogram::FactoryGet( 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch name, 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kMinimumBucket, 251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kMaximumBucket, 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kBucketCount, 253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Histogram::kUmaTargetedHistogramFlag); 254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch counter->Add(cpu); 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Extracts a field value from a list of name-value pairs 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in a file (typically a /proc or /sys file). Returns false 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// if the field is not found, or for other errors. 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool SwapMetrics::Backend::GetFieldFromKernelOutput(const std::string& path, 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& field, 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int64* value) { 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string file_content; 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!file_util::ReadFileToString(FilePath(path), &file_content)) { 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "Cannot read " << path; 266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<std::string> lines; 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t line_count = Tokenize(file_content, "\n", &lines); 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (line_count < 2) { 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "Error breaking " << path << " into lines"; 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < line_count; ++i) { 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<std::string> tokens; 276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t token_count = Tokenize(lines[i], " ", &tokens); 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (token_count < 2) { 278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "Unexpected line: " << lines[i]; 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (tokens[0].compare(field) != 0) 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!base::StringToInt64(tokens[1], value)) { 284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "Cannot convert " << tokens[1] << " to int"; 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "could not find field " << field; 290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool SwapMetrics::Backend::TokenizeOneLineFile(const std::string& path, 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t expected_tokens_count, 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& delimiters, 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<std::string>* 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch tokens) { 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string file_content; 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!file_util::ReadFileToString(FilePath(path), &file_content)) { 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "cannot read " << path; 301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t tokens_count = Tokenize(file_content, delimiters, tokens); 304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (tokens_count != expected_tokens_count) { 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "unexpected content of " << path << ": " << file_content; 306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool SwapMetrics::Backend::GetMeminfoField(const std::string& name, 312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int64* value) { 313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return GetFieldFromKernelOutput("/proc/meminfo", name, value); 314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool SwapMetrics::Backend::GetUptime(double* uptime_secs, 317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double* idle_time_secs) { 318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get the time since boot. 319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const char kUptimePath[] = "/proc/uptime"; 320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<std::string> tokens; 321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!TokenizeOneLineFile(kUptimePath, 2, " \n", &tokens)) 322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!base::StringToDouble(tokens[0], uptime_secs)) { 325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "cannot convert " << tokens[0] << " to double"; 326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get the idle time since boot. The number available in /proc/stat is more 330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // precise, but this one should be good enough. 331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!base::StringToDouble(tokens[1], idle_time_secs)) { 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "cannot convert " << tokens[0] << " to double"; 333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool SwapMetrics::Backend::GetPageFaults(int64* page_faults) { 339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get number of page faults. 340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return GetFieldFromKernelOutput("/proc/vmstat", "pgmajfault", page_faults); 341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/////////////////////////////////////////////////////////////////////////////// 344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSwapMetrics::SwapMetrics() : browser_(NULL) { 346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ash::Shell::GetInstance()->AddPreTargetHandler(this); 347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BrowserList::AddObserver(this); 348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSwapMetrics::~SwapMetrics() { 3517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (backend_.get()) 352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch backend_->CancelOnUIThread(); 353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ash::Shell::GetInstance()->RemovePreTargetHandler(this); 354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BrowserList::RemoveObserver(this); 355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetBrowser(NULL); 356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::OnBrowserRemoved(Browser* browser) { 359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (browser_ == browser) 360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetBrowser(NULL); 361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::OnBrowserSetLastActive(Browser* browser) { 364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (browser && browser->type() == Browser::TYPE_TABBED) 365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetBrowser(browser); 366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else 367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SetBrowser(NULL); 368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::ActiveTabChanged(content::WebContents* old_contents, 371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::WebContents* new_contents, 372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int index, 373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int reason) { 374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only measure tab switches, not tabs being replaced with new contents. 375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (reason != TabStripModelObserver::CHANGE_REASON_USER_GESTURE) 376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DVLOG(1) << "ActiveTabChanged"; 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StartMetricsCollection("TabSwitch"); 379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This exists primarily for debugging on desktop builds. 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::OnMouseEvent(ui::MouseEvent* event) { 383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (event->type() != ui::ET_MOUSEWHEEL) 384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DVLOG(1) << "OnMouseEvent"; 386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StartMetricsCollection("Scroll"); 387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::OnScrollEvent(ui::ScrollEvent* event) { 390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (event->type() != ui::ET_SCROLL && 391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch event->type() != ui::ET_SCROLL_FLING_START) 392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DVLOG(1) << "OnScrollEvent"; 394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StartMetricsCollection("Scroll"); 395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::PostTaskRecordMetrics(scoped_refptr<Backend> backend, 399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t time_index, 400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int delay_ms) { 401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Don't block shutdown on these tasks, as UMA will be disappearing. 402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<base::TaskRunner> runner = 403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::BrowserThread::GetBlockingPool()-> 404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetTaskRunnerWithShutdownBehavior( 405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch runner->PostDelayedTask( 407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FROM_HERE, 408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&SwapMetrics::Backend::RecordMetricsOnBlockingPool, 409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch backend, 410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch time_index), 411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeDelta::FromMilliseconds(delay_ms)); 412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::StartMetricsCollection(const std::string& reason) { 415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Cancel any existing metrics run. 4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (backend_.get()) 417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch backend_->CancelOnUIThread(); 418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch backend_ = new Backend(reason); 419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PostTaskRecordMetrics(backend_, 0, kMetricsDelayMs[0]); 420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SwapMetrics::SetBrowser(Browser* browser) { 423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (browser_ == browser) 424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (browser_) 426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch browser_->tab_strip_model()->RemoveObserver(this); 427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch browser_ = browser; 428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (browser_) 429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch browser_->tab_strip_model()->AddObserver(this); 430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace chromeos 433