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 #include "chrome/test/perf/perf_test.h"
6
7 #include <stdio.h>
8
9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/test/base/chrome_process_util.h"
13 #include "testing/perf/perf_test.h"
14
15 namespace perf_test {
16
PrintIOPerfInfo(const std::string & test_name,const ChromeProcessList & chrome_processes,base::ProcessId browser_pid)17 void PrintIOPerfInfo(const std::string& test_name,
18 const ChromeProcessList& chrome_processes,
19 base::ProcessId browser_pid) {
20 PrintIOPerfInfo(stdout, test_name, chrome_processes, browser_pid);
21 }
22
PrintIOPerfInfo(FILE * target,const std::string & test_name,const ChromeProcessList & chrome_processes,base::ProcessId browser_pid)23 void PrintIOPerfInfo(FILE* target,
24 const std::string& test_name,
25 const ChromeProcessList& chrome_processes,
26 base::ProcessId browser_pid) {
27 fprintf(target, "%s", IOPerfInfoToString(test_name, chrome_processes,
28 browser_pid).c_str());
29 }
30
IOPerfInfoToString(const std::string & test_name,const ChromeProcessList & chrome_processes,base::ProcessId browser_pid)31 std::string IOPerfInfoToString(const std::string& test_name,
32 const ChromeProcessList& chrome_processes,
33 base::ProcessId browser_pid) {
34 size_t read_op_b = 0;
35 size_t read_op_r = 0;
36 size_t write_op_b = 0;
37 size_t write_op_r = 0;
38 size_t other_op_b = 0;
39 size_t other_op_r = 0;
40 size_t total_op_b = 0;
41 size_t total_op_r = 0;
42
43 size_t read_byte_b = 0;
44 size_t read_byte_r = 0;
45 size_t write_byte_b = 0;
46 size_t write_byte_r = 0;
47 size_t other_byte_b = 0;
48 size_t other_byte_r = 0;
49 size_t total_byte_b = 0;
50 size_t total_byte_r = 0;
51
52 std::string output;
53 ChromeProcessList::const_iterator it;
54 for (it = chrome_processes.begin(); it != chrome_processes.end(); ++it) {
55 base::ProcessHandle process_handle;
56 if (!base::OpenProcessHandle(*it, &process_handle)) {
57 NOTREACHED();
58 return output;
59 }
60
61 // TODO(sgk): if/when base::ProcessMetrics returns real stats on mac:
62 // scoped_ptr<base::ProcessMetrics> process_metrics(
63 // base::ProcessMetrics::CreateProcessMetrics(process_handle));
64 scoped_ptr<ChromeTestProcessMetrics> process_metrics(
65 ChromeTestProcessMetrics::CreateProcessMetrics(process_handle));
66 base::IoCounters io_counters;
67 memset(&io_counters, 0, sizeof(io_counters));
68
69 if (process_metrics.get()->GetIOCounters(&io_counters)) {
70 // Print out IO performance. We assume that the values can be
71 // converted to size_t (they're reported as ULONGLONG, 64-bit numbers).
72 std::string chrome_name = (*it == browser_pid) ? "_b" : "_r";
73
74 size_t read_op = static_cast<size_t>(io_counters.ReadOperationCount);
75 size_t write_op = static_cast<size_t>(io_counters.WriteOperationCount);
76 size_t other_op = static_cast<size_t>(io_counters.OtherOperationCount);
77 size_t total_op = static_cast<size_t>(io_counters.ReadOperationCount +
78 io_counters.WriteOperationCount +
79 io_counters.OtherOperationCount);
80
81 size_t read_byte = static_cast<size_t>(io_counters.ReadTransferCount
82 / 1024);
83 size_t write_byte = static_cast<size_t>(io_counters.WriteTransferCount
84 / 1024);
85 size_t other_byte = static_cast<size_t>(io_counters.OtherTransferCount
86 / 1024);
87 size_t total_byte = static_cast<size_t>((io_counters.ReadTransferCount +
88 io_counters.WriteTransferCount +
89 io_counters.OtherTransferCount)
90 / 1024);
91
92 if (*it == browser_pid) {
93 read_op_b = read_op;
94 write_op_b = write_op;
95 other_op_b = other_op;
96 total_op_b = total_op;
97 read_byte_b = read_byte;
98 write_byte_b = write_byte;
99 other_byte_b = other_byte;
100 total_byte_b = total_byte;
101 } else {
102 read_op_r += read_op;
103 write_op_r += write_op;
104 other_op_r += other_op;
105 total_op_r += total_op;
106 read_byte_r += read_byte;
107 write_byte_r += write_byte;
108 other_byte_r += other_byte;
109 total_byte_r += total_byte;
110 }
111 }
112
113 base::CloseProcessHandle(process_handle);
114 }
115
116 std::string t_name(test_name);
117 AppendResult(output,
118 "read_op_b",
119 std::string(),
120 "r_op_b" + t_name,
121 read_op_b,
122 "ops",
123 false);
124 AppendResult(output,
125 "write_op_b",
126 std::string(),
127 "w_op_b" + t_name,
128 write_op_b,
129 "ops",
130 false);
131 AppendResult(output,
132 "other_op_b",
133 std::string(),
134 "o_op_b" + t_name,
135 other_op_b,
136 "ops",
137 false);
138 AppendResult(output,
139 "total_op_b",
140 std::string(),
141 "IO_op_b" + t_name,
142 total_op_b,
143 "ops",
144 false);
145
146 AppendResult(output,
147 "read_byte_b",
148 std::string(),
149 "r_b" + t_name,
150 read_byte_b,
151 "kb",
152 false);
153 AppendResult(output,
154 "write_byte_b",
155 std::string(),
156 "w_b" + t_name,
157 write_byte_b,
158 "kb",
159 false);
160 AppendResult(output,
161 "other_byte_b",
162 std::string(),
163 "o_b" + t_name,
164 other_byte_b,
165 "kb",
166 false);
167 AppendResult(output,
168 "total_byte_b",
169 std::string(),
170 "IO_b" + t_name,
171 total_byte_b,
172 "kb",
173 false);
174
175 AppendResult(output,
176 "read_op_r",
177 std::string(),
178 "r_op_r" + t_name,
179 read_op_r,
180 "ops",
181 false);
182 AppendResult(output,
183 "write_op_r",
184 std::string(),
185 "w_op_r" + t_name,
186 write_op_r,
187 "ops",
188 false);
189 AppendResult(output,
190 "other_op_r",
191 std::string(),
192 "o_op_r" + t_name,
193 other_op_r,
194 "ops",
195 false);
196 AppendResult(output,
197 "total_op_r",
198 std::string(),
199 "IO_op_r" + t_name,
200 total_op_r,
201 "ops",
202 false);
203
204 AppendResult(output,
205 "read_byte_r",
206 std::string(),
207 "r_r" + t_name,
208 read_byte_r,
209 "kb",
210 false);
211 AppendResult(output,
212 "write_byte_r",
213 std::string(),
214 "w_r" + t_name,
215 write_byte_r,
216 "kb",
217 false);
218 AppendResult(output,
219 "other_byte_r",
220 std::string(),
221 "o_r" + t_name,
222 other_byte_r,
223 "kb",
224 false);
225 AppendResult(output,
226 "total_byte_r",
227 std::string(),
228 "IO_r" + t_name,
229 total_byte_r,
230 "kb",
231 false);
232
233 return output;
234 }
235
PrintMemoryUsageInfo(const std::string & test_name,const ChromeProcessList & chrome_processes,base::ProcessId browser_pid)236 void PrintMemoryUsageInfo(const std::string& test_name,
237 const ChromeProcessList& chrome_processes,
238 base::ProcessId browser_pid) {
239 PrintMemoryUsageInfo(stdout, test_name, chrome_processes, browser_pid);
240 }
241
PrintMemoryUsageInfo(FILE * target,const std::string & test_name,const ChromeProcessList & chrome_processes,base::ProcessId browser_pid)242 void PrintMemoryUsageInfo(FILE* target,
243 const std::string& test_name,
244 const ChromeProcessList& chrome_processes,
245 base::ProcessId browser_pid) {
246 fprintf(target, "%s", MemoryUsageInfoToString(test_name, chrome_processes,
247 browser_pid).c_str());
248 }
249
MemoryUsageInfoToString(const std::string & test_name,const ChromeProcessList & chrome_processes,base::ProcessId browser_pid)250 std::string MemoryUsageInfoToString(const std::string& test_name,
251 const ChromeProcessList& chrome_processes,
252 base::ProcessId browser_pid) {
253 size_t browser_virtual_size = 0;
254 size_t browser_working_set_size = 0;
255 size_t renderer_virtual_size = 0;
256 size_t renderer_working_set_size = 0;
257 size_t total_virtual_size = 0;
258 size_t total_working_set_size = 0;
259 #if defined(OS_WIN)
260 size_t browser_peak_virtual_size = 0;
261 size_t browser_peak_working_set_size = 0;
262 size_t renderer_total_peak_virtual_size = 0;
263 size_t renderer_total_peak_working_set_size = 0;
264 size_t renderer_single_peak_virtual_size = 0;
265 size_t renderer_single_peak_working_set_size = 0;
266 #endif
267
268 std::string output;
269 ChromeProcessList::const_iterator it;
270 for (it = chrome_processes.begin(); it != chrome_processes.end(); ++it) {
271 base::ProcessHandle process_handle;
272 if (!base::OpenProcessHandle(*it, &process_handle)) {
273 NOTREACHED();
274 return output;
275 }
276
277 // TODO(sgk): if/when base::ProcessMetrics returns real stats on mac:
278 // scoped_ptr<base::ProcessMetrics> process_metrics(
279 // base::ProcessMetrics::CreateProcessMetrics(process_handle));
280 scoped_ptr<ChromeTestProcessMetrics> process_metrics(
281 ChromeTestProcessMetrics::CreateProcessMetrics(process_handle));
282
283 size_t current_virtual_size = process_metrics->GetPagefileUsage();
284 size_t current_working_set_size = process_metrics->GetWorkingSetSize();
285
286 if (*it == browser_pid) {
287 browser_virtual_size = current_virtual_size;
288 browser_working_set_size = current_working_set_size;
289 } else {
290 renderer_virtual_size += current_virtual_size;
291 renderer_working_set_size += current_working_set_size;
292 }
293 total_virtual_size += current_virtual_size;
294 total_working_set_size += current_working_set_size;
295
296 #if defined(OS_WIN)
297 size_t peak_virtual_size = process_metrics->GetPeakPagefileUsage();
298 size_t peak_working_set_size = process_metrics->GetPeakWorkingSetSize();
299 if (*it == browser_pid) {
300 browser_peak_virtual_size = peak_virtual_size;
301 browser_peak_working_set_size = peak_working_set_size;
302 } else {
303 if (peak_virtual_size > renderer_single_peak_virtual_size) {
304 renderer_single_peak_virtual_size = peak_virtual_size;
305 }
306 if (peak_working_set_size > renderer_single_peak_working_set_size) {
307 renderer_single_peak_working_set_size = peak_working_set_size;
308 }
309 renderer_total_peak_virtual_size += peak_virtual_size;
310 renderer_total_peak_working_set_size += peak_working_set_size;
311 }
312 #endif
313
314 base::CloseProcessHandle(process_handle);
315 }
316
317 std::string trace_name(test_name);
318 #if defined(OS_WIN)
319 AppendResult(output, "vm_peak_b", "", "vm_pk_b" + trace_name,
320 browser_peak_virtual_size, "bytes",
321 false /* not important */);
322 AppendResult(output, "ws_peak_b", "", "ws_pk_b" + trace_name,
323 browser_peak_working_set_size, "bytes",
324 false /* not important */);
325 AppendResult(output, "vm_peak_r", "", "vm_pk_r" + trace_name,
326 renderer_total_peak_virtual_size, "bytes",
327 false /* not important */);
328 AppendResult(output, "ws_peak_r", "", "ws_pk_r" + trace_name,
329 renderer_total_peak_working_set_size, "bytes",
330 false /* not important */);
331 AppendResult(output, "vm_single_peak_r", "", "vm_spk_r" + trace_name,
332 renderer_single_peak_virtual_size, "bytes",
333 false /* not important */);
334 AppendResult(output, "ws_single_peak_r", "", "ws_spk_r" + trace_name,
335 renderer_single_peak_working_set_size, "bytes",
336 false /* important */);
337 AppendResult(output, "vm_final_b", "", "vm_f_b" + trace_name,
338 browser_virtual_size, "bytes",
339 false /* not important */);
340 AppendResult(output, "ws_final_b", "", "ws_f_b" + trace_name,
341 browser_working_set_size, "bytes",
342 false /* not important */);
343 AppendResult(output, "vm_final_r", "", "vm_f_r" + trace_name,
344 renderer_virtual_size, "bytes",
345 false /* not important */);
346 AppendResult(output, "ws_final_r", "", "ws_f_r" + trace_name,
347 renderer_working_set_size, "bytes",
348 false /* not important */);
349 AppendResult(output, "vm_final_t", "", "vm_f_t" + trace_name,
350 total_virtual_size, "bytes",
351 false /* not important */);
352 AppendResult(output, "ws_final_t", "", "ws_f_t" + trace_name,
353 total_working_set_size, "bytes",
354 false /* not important */);
355 #elif defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_ANDROID)
356 AppendResult(output,
357 "vm_size_final_b",
358 std::string(),
359 "vm_size_f_b" + trace_name,
360 browser_virtual_size,
361 "bytes",
362 false /* not important */);
363 AppendResult(output,
364 "vm_rss_final_b",
365 std::string(),
366 "vm_rss_f_b" + trace_name,
367 browser_working_set_size,
368 "bytes",
369 false /* not important */);
370 AppendResult(output,
371 "vm_size_final_r",
372 std::string(),
373 "vm_size_f_r" + trace_name,
374 renderer_virtual_size,
375 "bytes",
376 false /* not important */);
377 AppendResult(output,
378 "vm_rss_final_r",
379 std::string(),
380 "vm_rss_f_r" + trace_name,
381 renderer_working_set_size,
382 "bytes",
383 false /* not important */);
384 AppendResult(output,
385 "vm_size_final_t",
386 std::string(),
387 "vm_size_f_t" + trace_name,
388 total_virtual_size,
389 "bytes",
390 false /* not important */);
391 AppendResult(output,
392 "vm_rss_final_t",
393 std::string(),
394 "vm_rss_f_t" + trace_name,
395 total_working_set_size,
396 "bytes",
397 false /* not important */);
398 #else
399 NOTIMPLEMENTED();
400 #endif
401 AppendResult(output,
402 "processes",
403 std::string(),
404 "proc_" + trace_name,
405 chrome_processes.size(),
406 "count",
407 false /* not important */);
408
409 return output;
410 }
411
412 } // namespace perf_test
413