Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: base/memory/i_heart_windows_memory.cc

Issue 2865653003: One perf test for windows VirtualQueryEx calls.
Patch Set: add many test cases Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/BUILD.gn ('k') | base/memory/memory_uma_perftest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #include <cstdio>
2
3 #include <vector>
4
5 #include "base/command_line.h"
6 #include "base/process/launch.h"
7 #include "base/process/process.h"
8 #include "base/process/process_metrics.h"
9 #include "base/threading/platform_thread.h"
10
11 namespace {
12 using ProcessList = std::vector<base::Process*>;
13
14 void SleepForever() {
15 for (;;) {
16 base::PlatformThread::Sleep(base::TimeDelta::FromMinutes(1));
17 }
18 }
19
20 void LoadDll() {}
21
22 void CreateSharedMemoryButDontShare() {}
23
24 void ShareMeSomeMemory(int num_regions, ProcessList process_list) {
25 for (base::Process* process : process_list) {
26 CHECK(process);
27 }
28 }
29
30 void ShareMeSomeCOWsAndTouchThem(int num_regions, ProcessList process_list) {
31 for (base::Process* process : process_list) {
32 CHECK(process);
33 }
34 }
35
36 void ForceSwap() {
37 char* leak = new char[12345];
38 leak = nullptr;
39 }
40
41 struct SavedStats {
42 size_t private_bytes;
43 size_t shared_bytes;
44 uint64_t pss_bytes;
45 base::WorkingSetKBytes working_set;
46 base::CommittedKBytes committed;
47 };
48
49 void SaveStats(SavedStats* saved_stats, base::Process* process) {
50 std::unique_ptr<base::ProcessMetrics> metrics =
51 base::ProcessMetrics::CreateProcessMetrics(process->Handle());
52
53 CHECK(metrics->GetMemoryBytes(&(saved_stats->private_bytes), &(saved_stats->sh ared_bytes)));
54 CHECK(metrics->GetProportionalSetSizeBytes(&(saved_stats->pss_bytes)));
55 CHECK(metrics->GetWorkingSetKBytes(&saved_stats->working_set));
56 metrics->GetCommittedKBytes(&saved_stats->committed);
57 }
58
59 void DumpDiff(SavedStats* first, SavedStats* second) {
60 LOG(ERROR) << " - private kbytes: " << ((int64_t)second->private_bytes - (int 64_t)first->private_bytes) / 1024;
61 LOG(ERROR) << " - shared kbytes: " << ((int64_t)second->shared_bytes - (int64 _t)first->shared_bytes) / 1024;
62 LOG(ERROR) << " - pss kbytes: " << ((int64_t)second->pss_bytes - (int64_t)fir st->pss_bytes) / 1024;
63 LOG(ERROR) << " - workingset private kb: " << ((int64_t)second->working_set.p riv - (int64_t)first->working_set.priv);
64 LOG(ERROR) << " - workingset mapped kb: " << ((int64_t)second->working_set.sh areable - (int64_t)first->working_set.shareable);
65 LOG(ERROR) << " - workingset image kb: " << ((int64_t)second->working_set.sha red - (int64_t)first->working_set.shared);
66 LOG(ERROR) << " - committed private kb: " << ((int64_t)second->committed.priv - (int64_t)first->committed.priv);
67 LOG(ERROR) << " - committed mapped kb: " << ((int64_t)second->committed.mappe d - (int64_t)first->committed.mapped);
68 LOG(ERROR) << " - committed image kb: " << ((int64_t)second->committed.image - (int64_t)first->committed.image);
69 LOG(ERROR) << std::endl << std::endl;
70 }
71
72 } // namespace
73
74 void malloc1() {
75 LOG(ERROR) << "malloc 16MB, and touch every page";
76 base::Process process(base::Process::Current());
77 SavedStats first, second;
78 SaveStats(&first, &process);
79
80 char*a = (char*)malloc(16 * 1024 * 1024);
81 for (int i = 0; i < 16 * 1024 * 1024; ++i) {
82 a[i] = 'a';
83 }
84 SaveStats(&second, &process);
85
86 DumpDiff(&first, &second);
87 }
88
89 void malloc2() {
90 LOG(ERROR) << "malloc 16MB, but only touch every 16th page";
91 base::Process process(base::Process::Current());
92 SavedStats first, second;
93 SaveStats(&first, &process);
94
95 char*a = (char*)malloc(16 * 1024 * 1024);
96 for(int i = 0; i < 16 * 1024 * 1024 / (16 * 4096); ++i) {
97 a[i * 16 * 4096] = 'a';
98 }
99 SaveStats(&second, &process);
100
101 DumpDiff(&first, &second);
102 }
103
104 void malloc3() {
105 LOG(ERROR) << "malloc 16MB, touch every page, then free";
106 base::Process process(base::Process::Current());
107 SavedStats first, second;
108 SaveStats(&first, &process);
109
110 char*a = (char*)malloc(16 * 1024 * 1024);
111 for (int i = 0; i < 16 * 1024 * 1024; ++i) {
112 a[i] = 'a';
113 }
114 free(a);
115 SaveStats(&second, &process);
116
117 DumpDiff(&first, &second);
118 }
119
120 void malloc4() {
121 LOG(ERROR) << "malloc 16MB in 1024 chunks, touch every page, then free every c hunk that isn't a multiple of 16";
122 LOG(ERROR) << "I expect resident memory to hit ~4MB, but instead it stays at 1 6MB! What's going on?";
123 base::Process process(base::Process::Current());
124 SavedStats first, second;
125 std::vector<char*> chunks;
126 chunks.resize(16 * 1024);
127
128 SaveStats(&first, &process);
129 for (int i = 0; i < 16 * 1024; ++i) {
130 chunks[i] = (char*)malloc(1024);
131 chunks[i][0] = 'a';
132 }
133
134 for (int i = 0; i < 16 * 1024; ++i) {
135 if (i % 16 != 0)
136 free(chunks[i]);
137 }
138 SaveStats(&second, &process);
139
140 DumpDiff(&first, &second);
141 }
142
143 void anonymous_file_mapping1() {
144 LOG(ERROR) << "create 16MB anonymous file mapping, and touch every page";
145 base::Process process(base::Process::Current());
146 SavedStats first, second;
147 SaveStats(&first, &process);
148 HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
149 16 * 1024 * 1024, NULL);
150 char*a = (char*) MapViewOfFile(h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 16 * 10 24 *1024);
151 for (int i = 0; i < 16 * 1024 * 1024; ++i)
152 a[i] = 'a';
153 SaveStats(&second, &process);
154 DumpDiff(&first, &second);
155 }
156
157 void anonymous_file_mapping2() {
158 LOG(ERROR) << "create 16MB anonymous file mapping";
159 base::Process process(base::Process::Current());
160 SavedStats first, second;
161 SaveStats(&first, &process);
162 CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
163 16 * 1024 * 1024, NULL);
164 SaveStats(&second, &process);
165 DumpDiff(&first, &second);
166 }
167 void anonymous_file_mapping3() {
168 LOG(ERROR) << "create and map 16MB anonymous file mapping";
169 base::Process process(base::Process::Current());
170 SavedStats first, second;
171 SaveStats(&first, &process);
172 HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
173 16 * 1024 * 1024, NULL);
174 MapViewOfFile(h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 16 * 1024 *1024);
175 SaveStats(&second, &process);
176 DumpDiff(&first, &second);
177 }
178
179 void virtual_alloc1() {
180 LOG(ERROR) << "virtual_alloc 16MB";
181 base::Process process(base::Process::Current());
182 SavedStats first, second;
183 SaveStats(&first, &process);
184
185 VirtualAlloc(NULL, 16 * 1024 * 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE) ;
186 SaveStats(&second, &process);
187
188 DumpDiff(&first, &second);
189 }
190
191 void virtual_alloc2() {
192 LOG(ERROR) << "virtual_alloc 16MB, then write to 8MB of pages";
193 base::Process process(base::Process::Current());
194 SavedStats first, second;
195 SaveStats(&first, &process);
196
197 char* a = (char*)VirtualAlloc(NULL, 16 * 1024 * 1024, MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE);
198 for (int i = 0; i < 8 * 1024 * 1024; ++i) {
199 a[i] = 'a';
200 }
201 SaveStats(&second, &process);
202
203 DumpDiff(&first, &second);
204 }
205
206 void virtual_alloc3() {
207 LOG(ERROR) << "virtual_alloc 16MB, then write to 8MB of pages, then decommits 4MB of the written pages";
208 base::Process process(base::Process::Current());
209 SavedStats first, second;
210 SaveStats(&first, &process);
211
212 char* a = (char*)VirtualAlloc(NULL, 16 * 1024 * 1024, MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE);
213 for (int i = 0; i < 8 * 1024 * 1024; ++i) {
214 a[i] = 'a';
215 }
216 VirtualFree(a, 4 * 1024 * 1024, MEM_DECOMMIT);
217 SaveStats(&second, &process);
218
219 DumpDiff(&first, &second);
220 }
221
222 void virtual_alloc4() {
223 LOG(ERROR) << "virtual_alloc 16MB, then write to 8MB of pages, then reset 4MB of the written pages";
224 base::Process process(base::Process::Current());
225 SavedStats first, second;
226 SaveStats(&first, &process);
227
228 char* a = (char*)VirtualAlloc(NULL, 16 * 1024 * 1024, MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE);
229 for (int i = 0; i < 8 * 1024 * 1024; ++i) {
230 a[i] = 'a';
231 }
232 VirtualAlloc(a, 4 * 1024 * 1024, MEM_RESET, PAGE_NOACCESS);
233 SaveStats(&second, &process);
234
235 DumpDiff(&first, &second);
236 }
237
238 void virtual_alloc5() {
239 LOG(ERROR) << "virtual_alloc 16MB, then write to 8MB of pages, then discard 4M B of the written pages";
240 base::Process process(base::Process::Current());
241 SavedStats first, second;
242 SaveStats(&first, &process);
243
244 char* a = (char*)VirtualAlloc(NULL, 16 * 1024 * 1024, MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE);
245 for (int i = 0; i < 8 * 1024 * 1024; ++i) {
246 a[i] = 'a';
247 }
248 using DiscardVirtualMemoryFunction =
249 DWORD(WINAPI*)(PVOID virtualAddress, SIZE_T size);
250 DiscardVirtualMemoryFunction discard_virtual_memory =
251 reinterpret_cast<DiscardVirtualMemoryFunction>(GetProcAddress(
252 GetModuleHandle(L"Kernel32.dll"), "DiscardVirtualMemory"));
253 discard_virtual_memory(a, 4 * 1024 * 1024);
254 SaveStats(&second, &process);
255
256 DumpDiff(&first, &second);
257 }
258 void heap_alloc1() {
259 LOG(ERROR) << "HeapAlloc 16MB";
260 base::Process process(base::Process::Current());
261 SavedStats first, second;
262 SaveStats(&first, &process);
263
264 HeapAlloc(GetProcessHeap(), 0, 16 * 1024 * 1024);
265 SaveStats(&second, &process);
266
267 DumpDiff(&first, &second);
268 }
269 void heap_alloc2() {
270 LOG(ERROR) << "HeapAlloc 16MB, and touch 8MB";
271 base::Process process(base::Process::Current());
272 SavedStats first, second;
273 SaveStats(&first, &process);
274
275 char* a = (char*)HeapAlloc(GetProcessHeap(), 0, 16 * 1024 * 1024);
276 for (int i = 0; i < 8 * 1024 * 1024; ++i) {
277 a[i] = 'a';
278 }
279 SaveStats(&second, &process);
280
281 DumpDiff(&first, &second);
282 }
283 void heap_alloc3() {
284 LOG(ERROR) << "HeapAlloc 16MB, and touch 8MB, then decommit 4MB";
285 base::Process process(base::Process::Current());
286 SavedStats first, second;
287 SaveStats(&first, &process);
288
289 char* a = (char*)HeapAlloc(GetProcessHeap(), 0, 16 * 1024 * 1024);
290 for (int i = 0; i < 8 * 1024 * 1024; ++i) {
291 a[i] = 'a';
292 }
293 VirtualFree(a, 4 * 1024 * 1024, MEM_DECOMMIT);
294 SaveStats(&second, &process);
295
296 DumpDiff(&first, &second);
297 }
298
299 void leak_1gb() {
300 LOG(ERROR) << "leak 1gb";
301 base::Process process(base::Process::Current());
302 SavedStats first, second;
303 SaveStats(&first, &process);
304 char* a = (char*)malloc(1024 * 1024 * 1024);
305 for (int i = 0; i < 1024 * 1024 * 1024 / 4096; ++i)
306 a[i * 4096] = 'a';
307 SaveStats(&second, &process);
308 DumpDiff(&first, &second);
309 }
310
311 void swap1() {
312 LOG(ERROR) << "This will crash your machine. Are you sure you want to continue (y)?";
313 char dummy;
314 scanf("%c", &dummy);
315 if (dummy != 'y')
316 return;
317
318 LOG(ERROR) << "malloc 256MB, touch every page, then spawn children that consum e 64GB of memory";
319 base::Process process(base::Process::Current());
320 SavedStats first, second;
321 SaveStats(&first, &process);
322
323 char*a = (char*)malloc(256 * 1024 * 1024);
324 for (int i = 0; i < 256 * 1024 * 1024 / 4096; ++i) {
325 a[i * 4096] = 'a';
326 }
327 for (int i = 0; i < 64; ++i) {
328 base::LaunchOptions options;
329 base::CommandLine child_command(*base::CommandLine::ForCurrentProcess());
330 child_command.AppendSwitch("leak_1gb");
331 base::LaunchProcess(child_command, options);
332 }
333
334 // Wait 100 seconds for memory to blow up.
335 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(100));
336 SaveStats(&second, &process);
337 DumpDiff(&first, &second);
338 }
339
340 void swap2() {
341 LOG(ERROR) << "Spawns 256 process, each of which commits 1GB with VirtualAlloc but only makes 4MB of pages resident.";
342 for (int i = 0; i < 256; ++i) {
343 base::LaunchOptions options;
344 base::CommandLine child_command(*base::CommandLine::ForCurrentProcess());
345 child_command.AppendSwitch("swap2_child");
346 base::LaunchProcess(child_command, options);
347 }
348
349 // Wait 3 seconds for memory to blow up.
350 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(3));
351
352 LOG(ERROR) << "try to allocate 1GB using malloc";
353 char*b = (char*)malloc(1024 * 1024 * 1024);
354 CHECK(b);
355 for (int i = 0; i < 1024 * 1024 * 1024 / 4096; ++i) {
356 b[i * 4096] = 'a';
357 }
358 LOG(ERROR) << "allocated 1GB using malloc";
359
360 LOG(ERROR) << "try to allocate 1GB using virtual alloc";
361 for (int i = 0; i < 1024; i++) {
362 char* a = (char*)VirtualAlloc(NULL, 1024 * 1024, MEM_COMMIT | MEM_RESERVE, P AGE_READWRITE);
363 CHECK(a);
364 a[0] = 'a';
365 }
366 LOG(ERROR) << "allocated 1GB using virtual alloc";
367 }
368
369 void swap2_child() {
370 base::Process process(base::Process::Current());
371 SavedStats first, second;
372 SaveStats(&first, &process);
373 for (int i = 0; i < 1024; i++) {
374 char* a = (char*)VirtualAlloc(NULL, 1024 * 1024, MEM_COMMIT | MEM_RESERVE, P AGE_READWRITE);
375
376 // Occasional errors.
377 if (!a)
378 continue;
379
380 a[0] = 'a';
381 }
382 SaveStats(&second, &process);
383 DumpDiff(&first, &second);
384 }
385
386 int main(int argc, char* argv[]) {
387 base::CommandLine::Init(argc, argv);
388 const base::CommandLine& current_command =
389 *base::CommandLine::ForCurrentProcess();
390
391 if (current_command.HasSwitch("sleepy")) {
392 new char[base::Process::Current().Pid()];
393 SleepForever();
394 }
395
396 if (current_command.HasSwitch("malloc1")) {
397 malloc1();
398 SleepForever();
399 }
400
401 if (current_command.HasSwitch("malloc2")) {
402 malloc2();
403 SleepForever();
404 }
405
406 if (current_command.HasSwitch("malloc3")) {
407 malloc3();
408 SleepForever();
409 }
410
411 if (current_command.HasSwitch("malloc4")) {
412 malloc4();
413 SleepForever();
414 }
415
416 if (current_command.HasSwitch("anonymous_file_mapping1")) {
417 anonymous_file_mapping1();
418 SleepForever();
419 }
420
421 if (current_command.HasSwitch("anonymous_file_mapping2")) {
422 anonymous_file_mapping2();
423 SleepForever();
424 }
425 if (current_command.HasSwitch("anonymous_file_mapping3")) {
426 anonymous_file_mapping3();
427 SleepForever();
428 }
429 if (current_command.HasSwitch("virtual_alloc1")) {
430 virtual_alloc1();
431 SleepForever();
432 }
433 if (current_command.HasSwitch("virtual_alloc2")) {
434 virtual_alloc2();
435 SleepForever();
436 }
437 if (current_command.HasSwitch("virtual_alloc3")) {
438 virtual_alloc3();
439 SleepForever();
440 }
441 if (current_command.HasSwitch("virtual_alloc4")) {
442 virtual_alloc4();
443 SleepForever();
444 }
445 if (current_command.HasSwitch("virtual_alloc5")) {
446 virtual_alloc4();
447 SleepForever();
448 }
449 if (current_command.HasSwitch("heap_alloc1")) {
450 heap_alloc1();
451 SleepForever();
452 }
453 if (current_command.HasSwitch("heap_alloc2")) {
454 heap_alloc2();
455 SleepForever();
456 }
457 if (current_command.HasSwitch("heap_alloc3")) {
458 heap_alloc3();
459 SleepForever();
460 }
461 if (current_command.HasSwitch("leak_1gb")) {
462 leak_1gb();
463 SleepForever();
464 }
465 if (current_command.HasSwitch("swap1")) {
466 swap1();
467 SleepForever();
468 }
469 if (current_command.HasSwitch("swap2_child")) {
470 swap2_child();
471 SleepForever();
472 }
473 if (current_command.HasSwitch("swap2")) {
474 swap2();
475 SleepForever();
476 }
477 // Launch 2 child processes to mess with.
478 // base::LaunchOptions options;
479 base::Process a(base::Process::Current());
480 // base::CommandLine child_command(current_command);
481 // child_command.AppendSwitch("sleepy");
482 // base::Process b(base::LaunchProcess(child_command, options));
483 // base::Process c(base::LaunchProcess(child_command, options));
484
485 // // Test sharing a DLL.
486 // LoadDll();
487
488 // // Test shared memory that's not shared.
489 // CreateSharedMemoryButDontShare();
490
491 // // Test sharing with just one other process.
492 // ShareMeSomeMemory(2, {&b});
493 // ShareMeSomeMemory(4, {&c});
494
495 // // Test sharing with bunches of processes.
496 // ShareMeSomeMemory(7, {&b, &c});
497
498 // // Test sharing Copy on write pgae.
499 // ShareMeSomeCOWsAndTouchThem(12, {&b, &c});
500
501 // // Force us to swap out memory.
502 // ForceSwap();
503 // DumpStats({&a});
504
505 // for (int i = 0; i < 1000; ++i) {
506 // char*a = (char*)malloc(4096 * 16);
507 // *a = 'a';
508 // // for (int j = 0; j < 16; ++j)
509 // // a[j * 4096] = 'a';
510 // // base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
511 // }
512
513 // // Print out stats.
514 // DumpStats({&a});
515 //DumpStats({&a, &b, &c});
516
517 // Wait until input so it can be inspected.
518 char dummy;
519 scanf("%c", &dummy);
520
521 // Clean up 2 child processes.
522 // b.Terminate(0, true);
523 // c.Terminate(0, true);
524
525 return 0;
526 }
OLDNEW
« no previous file with comments | « base/BUILD.gn ('k') | base/memory/memory_uma_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698