| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Dumps CPU and IO stats to a file at a regular interval. | |
| 6 // | |
| 7 // Output may be post processed by host to get top/iotop style information. | |
| 8 | |
| 9 #include <signal.h> | |
| 10 #include <unistd.h> | |
| 11 | |
| 12 #include <fstream> | |
| 13 #include <string> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "base/command_line.h" | |
| 17 #include "base/file_util.h" | |
| 18 #include "base/strings/string_split.h" | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 const char kIOStatsPath[] = "/proc/diskstats"; | |
| 23 const char kCPUStatsPath[] = "/proc/stat"; | |
| 24 | |
| 25 class DeviceStatsMonitor { | |
| 26 public: | |
| 27 explicit DeviceStatsMonitor(const std::string& out_path) | |
| 28 : out_path_(out_path), | |
| 29 record_(true) { | |
| 30 CHECK(!out_path_.empty()); | |
| 31 samples_.reserve(1024 * 1024); | |
| 32 } | |
| 33 | |
| 34 // Records stats continuously at |hz| cycles per second util | |
| 35 // StopRecordingAndDumpStats() is called. | |
| 36 // | |
| 37 // Yes, this buffers everything in memory, so it cannot be used for extended | |
| 38 // durations without OOM. But that beats writing during the trace which | |
| 39 // would affect the results. | |
| 40 void Start(int hz) { | |
| 41 const int sample_interval = 1000000 / hz; | |
| 42 const base::FilePath io_stats_path(kIOStatsPath); | |
| 43 const base::FilePath cpu_stats_path(kCPUStatsPath); | |
| 44 std::string out; | |
| 45 while (record_) { | |
| 46 out.clear(); | |
| 47 CHECK(base::ReadFileToString(io_stats_path, &out)); | |
| 48 CHECK(base::ReadFileToString(cpu_stats_path, &out)); | |
| 49 samples_.push_back(out); | |
| 50 usleep(sample_interval); | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 // Stops recording and saves samples to file. | |
| 55 void StopAndDumpStats() { | |
| 56 record_ = false; | |
| 57 usleep(250 * 1000); | |
| 58 std::ofstream out_stream; | |
| 59 out_stream.open(out_path_.value().c_str(), std::ios::out); | |
| 60 for (std::vector<std::string>::const_iterator i = samples_.begin(); | |
| 61 i != samples_.end(); ++i) { | |
| 62 out_stream << i->c_str() << std::endl; | |
| 63 } | |
| 64 out_stream.close(); | |
| 65 } | |
| 66 | |
| 67 private: | |
| 68 const base::FilePath out_path_; | |
| 69 std::vector<std::string> samples_; | |
| 70 bool record_; | |
| 71 | |
| 72 DISALLOW_COPY_AND_ASSIGN(DeviceStatsMonitor); | |
| 73 }; | |
| 74 | |
| 75 DeviceStatsMonitor* g_device_stats_monitor = NULL; | |
| 76 | |
| 77 void SigTermHandler(int unused) { | |
| 78 printf("Stopping device stats monitor\n"); | |
| 79 g_device_stats_monitor->StopAndDumpStats(); | |
| 80 } | |
| 81 | |
| 82 } // namespace | |
| 83 | |
| 84 int main(int argc, char** argv) { | |
| 85 const int kDefaultHz = 20; | |
| 86 | |
| 87 CommandLine command_line(argc, argv); | |
| 88 CommandLine::StringVector args = command_line.GetArgs(); | |
| 89 if (command_line.HasSwitch("h") || command_line.HasSwitch("help") || | |
| 90 args.size() != 1) { | |
| 91 printf("Usage: %s OUTPUT_FILE\n" | |
| 92 " --hz=HZ Number of samples/second. default=%d\n", | |
| 93 argv[0], kDefaultHz); | |
| 94 return 1; | |
| 95 } | |
| 96 | |
| 97 int hz = command_line.HasSwitch("hz") ? | |
| 98 atoi(command_line.GetSwitchValueNative("hz").c_str()) : | |
| 99 kDefaultHz; | |
| 100 | |
| 101 printf("Starting device stats monitor\n"); | |
| 102 g_device_stats_monitor = new DeviceStatsMonitor(args[0]); | |
| 103 signal(SIGTERM, SigTermHandler); | |
| 104 g_device_stats_monitor->Start(hz); | |
| 105 delete g_device_stats_monitor; | |
| 106 | |
| 107 return 0; | |
| 108 } | |
| OLD | NEW |