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 |