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/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 FilePath io_stats_path(kIOStatsPath); |
| 43 const FilePath cpu_stats_path(kCPUStatsPath); |
| 44 std::string out; |
| 45 while (record_) { |
| 46 out.clear(); |
| 47 CHECK(file_util::ReadFileToString(io_stats_path, &out)); |
| 48 CHECK(file_util::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 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 |