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

Side by Side Diff: tools/telemetry/telemetry/timeline/memory_dump_event_unittest.py

Issue 1553183002: [telemetry] Add support for composable process dumps in memory-infra (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes. Created 4 years, 11 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
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import unittest 5 import unittest
6 6
7 from telemetry.timeline import memory_dump_event 7 from telemetry.timeline import memory_dump_event
8 import mock 8 import mock
9 9
10 10
11 def TestProcessDumpEvent(dump_id='123456ABCDEF', pid=1234, start=0, mmaps=None, 11 def MakeRawMemoryDumpEvent(dump_id='123456ABCDEF', pid=1234, start=0,
12 allocators=None): 12 mmaps=None, allocators=None):
13
13 def vm_region(mapped_file, byte_stats): 14 def vm_region(mapped_file, byte_stats):
14 return { 15 return {
15 'mf': mapped_file, 16 'mf': mapped_file,
16 'bs': {k: hex(v) for k, v in byte_stats.iteritems()}} 17 'bs': {k: hex(v) for k, v in byte_stats.iteritems()}}
17 18
18 def attrs(sizes): 19 def attrs(sizes):
19 return {'attrs': {k: {'value': hex(v), 'units': 'bytes'} 20 return {'attrs': {k: {'value': hex(v), 'units': 'bytes'}
20 for k, v in sizes.iteritems()}} 21 for k, v in sizes.iteritems()}}
21 22
22 if allocators is None: 23 if allocators is None:
23 allocators = {} 24 allocators = {}
24 25
25 event = {'ph': 'v', 'id': dump_id, 'pid': pid, 'ts': start * 1000, 26 event = {'ph': 'v', 'id': dump_id, 'pid': pid, 'ts': start * 1000,
26 'args': {'dumps': {'allocators': { 27 'args': {'dumps': {'allocators': {
27 name: attrs(sizes) for name, sizes in allocators.iteritems()}}}} 28 name: attrs(sizes) for name, sizes in allocators.iteritems()}}}}
28 if mmaps: 29 if mmaps:
29 event['args']['dumps']['process_mmaps'] = { 30 event['args']['dumps']['process_mmaps'] = {
30 'vm_regions': [vm_region(mapped_file, byte_stats) 31 'vm_regions': [vm_region(mapped_file, byte_stats)
31 for mapped_file, byte_stats in mmaps.iteritems()]} 32 for mapped_file, byte_stats in mmaps.iteritems()]}
32 33
34 return event
35
36
37 def TestProcessDumpEvent(dump_id='123456ABCDEF', pid=1234, start=0, mmaps=None,
38 allocators=None):
39 event = MakeRawMemoryDumpEvent(dump_id, pid, start, mmaps=mmaps,
40 allocators=allocators)
33 process = mock.Mock() 41 process = mock.Mock()
34 process.pid = event['pid'] 42 process.pid = event['pid']
35 return memory_dump_event.ProcessMemoryDumpEvent(process, event) 43 return memory_dump_event.ProcessMemoryDumpEvent(process, [event])
36 44
37 45
38 class ProcessMemoryDumpEventUnitTest(unittest.TestCase): 46 class ProcessMemoryDumpEventUnitTest(unittest.TestCase):
47
39 def testProcessMemoryDump_allocators(self): 48 def testProcessMemoryDump_allocators(self):
40 memory_dump = TestProcessDumpEvent(allocators={ 49 process = mock.Mock()
41 'v8': {'size': 10, 'allocated_objects_size' : 5}, 50 process.pid = 1234
42 'v8/allocated_objects': {'size': 4}, 51 events = [
43 'skia': {'not_size': 10, 'allocated_objects_size' : 5}, 52 MakeRawMemoryDumpEvent(
44 'skia/cache1': {'size': 24}, 53 pid=process.pid, allocators={
45 'skia/cache2': {'not_size': 20}, 54 'v8': {'size': 10, 'allocated_objects_size': 5},
46 'skia/cache2/obj1': {'size': 8}, 55 'v8/allocated_objects': {'size': 4},
47 'skia/cache2/obj2': {'size': 9}, 56 'skia': {'not_size': 10,
48 'skia_different/obj': {'size': 30}, 57 'allocated_objects_size': 5},
49 'skia_different/obj/not_counted': {'size': 26}, 58 'skia/cache1': {'size': 24}
50 'global/0xdead': {'size': 26} 59 }
51 }) 60 ),
52 EXPECTED = { 61 MakeRawMemoryDumpEvent(
53 'skia': {'allocated_objects_size': 5, 'not_size': 30, 'size': 41}, 62 pid=process.pid, allocators={
54 'v8': {'allocated_objects_size': 5, 'size': 10}, 63 'skia/cache2': {'not_size': 20},
55 'skia_different': {'size': 30}} 64 'skia/cache2/obj1': {'size': 8},
65 'skia/cache2/obj2': {'size': 9},
66 'skia_different/obj': {'size': 30},
67 'skia_different/obj/not_counted': {'size': 26},
68 'global/0xdead': {'size': 26}
69 }
70 )
71 ]
72 memory_dump = memory_dump_event.ProcessMemoryDumpEvent(process, events)
56 73
57 self.assertEquals(memory_dump._allocators, EXPECTED) 74 EXPECTED_ALLOCATORS = {
75 'skia': {
76 'allocated_objects_size': 5,
77 'not_size': 30,
78 'size': 41
79 },
80 'v8': {
81 'allocated_objects_size': 5,
82 'size': 10
83 },
84 'skia_different': {'size': 30}
85 }
86
87 self.assertEquals(memory_dump._allocators, EXPECTED_ALLOCATORS)
58 88
59 def testProcessMemoryDump_mmaps(self): 89 def testProcessMemoryDump_mmaps(self):
60 ALL = [2 ** x for x in range(8)] 90 ALL = [2 ** x for x in range(8)]
61 (JAVA_SPACES, JAVA_CACHE, ASHMEM, NATIVE_1, NATIVE_2, 91 (JAVA_SPACES, JAVA_CACHE, ASHMEM, NATIVE_1, NATIVE_2, STACK, FILES_APK,
62 STACK, FILES_APK, DEVICE_GPU) = ALL 92 DEVICE_GPU) = ALL
63 93
64 memory_dump = TestProcessDumpEvent(mmaps={ 94 memory_dump = TestProcessDumpEvent(mmaps={
65 '/dev/ashmem/dalvik-space-foo': {'pss': JAVA_SPACES}, 95 '/dev/ashmem/dalvik-space-foo': {'pss': JAVA_SPACES},
66 '/dev/ashmem/dalvik-jit-code-cache': {'pss': JAVA_CACHE}, 96 '/dev/ashmem/dalvik-jit-code-cache': {'pss': JAVA_CACHE},
67 '/dev/ashmem/other-random-stuff': {'pss': ASHMEM}, 97 '/dev/ashmem/other-random-stuff': {'pss': ASHMEM},
68 '[heap] bar': {'pss': NATIVE_1}, 98 '[heap] bar': {'pss': NATIVE_1},
69 '': {'pss': NATIVE_2}, 99 '': {'pss': NATIVE_2},
70 '[stack thingy]': {'pss': STACK}, 100 '[stack thingy]': {'pss': STACK},
71 'my_little_app.apk': {'pss': FILES_APK}, 101 'my_little_app.apk': {'pss': FILES_APK},
72 '/dev/mali': {'pss': DEVICE_GPU}, 102 '/dev/mali': {'pss': DEVICE_GPU}
73 }) 103 })
74 104
75 EXPECTED = { 105 EXPECTED = {
76 '/': sum(ALL), 106 '/': sum(ALL),
77 '/Android/Java runtime': JAVA_SPACES + JAVA_CACHE, 107 '/Android/Java runtime': JAVA_SPACES + JAVA_CACHE,
78 '/Android/Ashmem': ASHMEM, 108 '/Android/Ashmem': ASHMEM,
79 '/Android': JAVA_SPACES + JAVA_CACHE + ASHMEM, 109 '/Android': JAVA_SPACES + JAVA_CACHE + ASHMEM,
80 '/Native heap': NATIVE_1 + NATIVE_2, 110 '/Native heap': NATIVE_1 + NATIVE_2,
81 '/Stack': STACK, 111 '/Stack': STACK,
82 '/Files/apk': FILES_APK, 112 '/Files/apk': FILES_APK,
83 '/Devices': DEVICE_GPU} 113 '/Devices': DEVICE_GPU}
84 114
85 self.assertTrue(memory_dump.has_mmaps) 115 self.assertTrue(memory_dump.has_mmaps)
86 for path, value in EXPECTED.iteritems(): 116 for path, value in EXPECTED.iteritems():
117 self.assertEquals(
118 value,
119 memory_dump.GetMemoryBucket(path).GetValue('proportional_resident'))
120
121 def testProcessMemoryDump_composability(self):
122 java_spaces = 100
123 process = mock.Mock()
124 process.pid = 1234
125 allocators = {'v8': {'size': 10}}
126 mmaps = {'/dev/ashmem/dalvik-space-foo': {'pss': java_spaces}}
127
128 events = [MakeRawMemoryDumpEvent(pid=process.pid, allocators=allocators),
129 MakeRawMemoryDumpEvent(pid=process.pid, mmaps=mmaps)]
130 memory_dump = memory_dump_event.ProcessMemoryDumpEvent(process, events)
131
132 self.assertEquals(memory_dump._allocators, allocators)
133
134 EXPECTED_MMAPS = {
135 '/': java_spaces,
136 '/Android/Java runtime': java_spaces,
137 '/Android': java_spaces,
138 }
139
140 self.assertTrue(memory_dump.has_mmaps)
141 for path, value in EXPECTED_MMAPS.iteritems():
87 self.assertEquals(value, 142 self.assertEquals(value,
88 memory_dump.GetMemoryBucket(path).GetValue( 143 memory_dump.GetMemoryBucket(path).GetValue('proportional_resident'))
89 'proportional_resident'))
90 144
91 145
92 class MemoryDumpEventUnitTest(unittest.TestCase): 146 class MemoryDumpEventUnitTest(unittest.TestCase):
93 def testRepr(self): 147 def testRepr(self):
94 process_dump1 = TestProcessDumpEvent( 148 process_dump1 = TestProcessDumpEvent(
95 mmaps={'/dev/ashmem/other-ashmem': {'pss': 5}}, 149 mmaps={'/dev/ashmem/other-ashmem': {'pss': 5}},
96 allocators={'v8': {'size': 10, 'allocated_objects_size' : 5}}) 150 allocators={'v8': {'size': 10, 'allocated_objects_size' : 5}})
97 process_dump2 = TestProcessDumpEvent( 151 process_dump2 = TestProcessDumpEvent(
98 mmaps={'/dev/ashmem/libc malloc': {'pss': 42, 'pd': 27}}, 152 mmaps={'/dev/ashmem/libc malloc': {'pss': 42, 'pd': 27}},
99 allocators={'v8': {'size': 20, 'allocated_objects_size' : 10}, 153 allocators={'v8': {'size': 20, 'allocated_objects_size' : 10},
100 'oilpan': {'size': 40}}) 154 'oilpan': {'size': 40}})
101 global_dump = memory_dump_event.GlobalMemoryDump( 155 global_dump = memory_dump_event.GlobalMemoryDump(
102 [process_dump1, process_dump2]) 156 [process_dump1, process_dump2])
103 157
104 self.assertEquals( 158 self.assertEquals(
105 repr(process_dump1), 159 repr(process_dump1),
106 'ProcessMemoryDumpEvent[pid=1234, allocated_objects_v8=5,' 160 'ProcessMemoryDumpEvent[pid=1234, allocated_objects_v8=5, '
107 ' allocator_v8=10, mmaps_ashmem=5, mmaps_java_heap=0,' 161 'allocator_v8=10, mmaps_ashmem=5, mmaps_overall_pss=5]')
108 ' mmaps_native_heap=0, mmaps_overall_pss=5, mmaps_private_dirty=0]')
109 self.assertEquals( 162 self.assertEquals(
110 repr(process_dump2), 163 repr(process_dump2),
111 'ProcessMemoryDumpEvent[pid=1234, allocated_objects_v8=10,' 164 'ProcessMemoryDumpEvent[pid=1234, allocated_objects_v8=10, '
112 ' allocator_oilpan=40, allocator_v8=20, mmaps_ashmem=0,' 165 'allocator_oilpan=40, allocator_v8=20, mmaps_native_heap=42, '
113 ' mmaps_java_heap=0, mmaps_native_heap=42, mmaps_overall_pss=42,' 166 'mmaps_overall_pss=42, mmaps_private_dirty=27]')
114 ' mmaps_private_dirty=27]')
115 self.assertEquals( 167 self.assertEquals(
116 repr(global_dump), 168 repr(global_dump),
117 'GlobalMemoryDump[id=123456ABCDEF, allocated_objects_v8=15,' 169 'GlobalMemoryDump[id=123456ABCDEF, allocated_objects_v8=15, '
118 ' allocator_oilpan=40, allocator_v8=30, mmaps_ashmem=5,' 170 'allocator_oilpan=40, allocator_v8=30, mmaps_ashmem=5, '
119 ' mmaps_java_heap=0, mmaps_native_heap=42, mmaps_overall_pss=47,' 171 'mmaps_native_heap=42, mmaps_overall_pss=47, mmaps_private_dirty=27]')
120 ' mmaps_private_dirty=27]')
121 172
122 def testDumpEventsTiming(self): 173 def testDumpEventsTiming(self):
174 process = mock.Mock()
175 process.pid = 1
176 composable_events = [
177 MakeRawMemoryDumpEvent(pid=process.pid, start=8),
178 MakeRawMemoryDumpEvent(pid=process.pid, start=16),
179 MakeRawMemoryDumpEvent(pid=process.pid, start=10)
180 ]
123 memory_dump = memory_dump_event.GlobalMemoryDump([ 181 memory_dump = memory_dump_event.GlobalMemoryDump([
182 memory_dump_event.ProcessMemoryDumpEvent(process, composable_events),
perezju 2016/01/13 16:30:34 keep the composed process_dump on a variable, and
ssid 2016/01/14 14:26:21 Done.
124 TestProcessDumpEvent(pid=3, start=8), 183 TestProcessDumpEvent(pid=3, start=8),
125 TestProcessDumpEvent(pid=1, start=4),
126 TestProcessDumpEvent(pid=2, start=13), 184 TestProcessDumpEvent(pid=2, start=13),
127 TestProcessDumpEvent(pid=4, start=7)]) 185 TestProcessDumpEvent(pid=4, start=7)])
128 186
129 self.assertFalse(memory_dump.has_mmaps) 187 self.assertFalse(memory_dump.has_mmaps)
130 self.assertEquals(4, 188 self.assertEquals(4, len(list(memory_dump.IterProcessMemoryDumps())))
131 len(list(memory_dump.IterProcessMemoryDumps()))) 189 self.assertAlmostEquals(7.0, memory_dump.start)
132 self.assertAlmostEquals(4.0, 190 self.assertAlmostEquals(16.0, memory_dump.end)
133 memory_dump.start) 191 self.assertAlmostEquals(9.0, memory_dump.duration)
134 self.assertAlmostEquals(13.0,
135 memory_dump.end)
136 self.assertAlmostEquals(9.0,
137 memory_dump.duration)
138 192
139 def testGetMemoryUsage(self): 193 def testGetMemoryUsage(self):
140 ALL = [2 ** x for x in range(7)] 194 ALL = [2 ** x for x in range(7)]
141 (JAVA_HEAP_1, JAVA_HEAP_2, ASHMEM_1, ASHMEM_2, NATIVE, 195 (JAVA_HEAP_1, JAVA_HEAP_2, ASHMEM_1, ASHMEM_2, NATIVE,
142 DIRTY_1, DIRTY_2) = ALL 196 DIRTY_1, DIRTY_2) = ALL
143 197
144 memory_dump = memory_dump_event.GlobalMemoryDump([ 198 memory_dump = memory_dump_event.GlobalMemoryDump([
145 TestProcessDumpEvent(pid=1, mmaps={ 199 TestProcessDumpEvent(pid=1, mmaps={
146 '/dev/ashmem/dalvik-alloc space': {'pss': JAVA_HEAP_1}}), 200 '/dev/ashmem/dalvik-alloc space': {'pss': JAVA_HEAP_1}}),
147 TestProcessDumpEvent(pid=2, mmaps={ 201 TestProcessDumpEvent(pid=2, mmaps={
(...skipping 15 matching lines...) Expand all
163 def testGetMemoryUsageWithAllocators(self): 217 def testGetMemoryUsageWithAllocators(self):
164 process_dump1 = TestProcessDumpEvent( 218 process_dump1 = TestProcessDumpEvent(
165 mmaps={'/dev/ashmem/other-ashmem': {'pss': 5}}, 219 mmaps={'/dev/ashmem/other-ashmem': {'pss': 5}},
166 allocators={'v8': {'size': 10, 'allocated_objects_size' : 5}}) 220 allocators={'v8': {'size': 10, 'allocated_objects_size' : 5}})
167 process_dump2 = TestProcessDumpEvent( 221 process_dump2 = TestProcessDumpEvent(
168 mmaps={'/dev/ashmem/other-ashmem': {'pss': 5}}, 222 mmaps={'/dev/ashmem/other-ashmem': {'pss': 5}},
169 allocators={'v8': {'size': 20, 'allocated_objects_size' : 10}}) 223 allocators={'v8': {'size': 20, 'allocated_objects_size' : 10}})
170 memory_dump = memory_dump_event.GlobalMemoryDump( 224 memory_dump = memory_dump_event.GlobalMemoryDump(
171 [process_dump1, process_dump2]) 225 [process_dump1, process_dump2])
172 self.assertEquals({'mmaps_overall_pss': 10, 226 self.assertEquals({'mmaps_overall_pss': 10,
173 'mmaps_private_dirty': 0,
174 'mmaps_java_heap': 0,
175 'mmaps_ashmem': 10, 227 'mmaps_ashmem': 10,
176 'mmaps_native_heap': 0,
177 'allocator_v8': 30, 228 'allocator_v8': 30,
178 'allocated_objects_v8': 15}, 229 'allocated_objects_v8': 15},
179 memory_dump.GetMemoryUsage()) 230 memory_dump.GetMemoryUsage())
180 231
181 def testGetMemoryUsageWithAndroidMemtrack(self): 232 def testGetMemoryUsageWithAndroidMemtrack(self):
182 GL1, EGL1, GL2, EGL2 = [2 ** x for x in range(4)] 233 GL1, EGL1, GL2, EGL2 = [2 ** x for x in range(4)]
183 process_dump1 = TestProcessDumpEvent( 234 process_dump1 = TestProcessDumpEvent(
184 allocators={'gpu/android_memtrack/gl': {'memtrack_pss' : GL1}, 235 allocators={'gpu/android_memtrack/gl': {'memtrack_pss' : GL1},
185 'gpu/android_memtrack/graphics': {'memtrack_pss': EGL1}}) 236 'gpu/android_memtrack/graphics': {'memtrack_pss': EGL1}})
186 process_dump2 = TestProcessDumpEvent( 237 process_dump2 = TestProcessDumpEvent(
(...skipping 12 matching lines...) Expand all
199 memory_dump = memory_dump_event.GlobalMemoryDump([ 250 memory_dump = memory_dump_event.GlobalMemoryDump([
200 TestProcessDumpEvent( 251 TestProcessDumpEvent(
201 mmaps={'/dev/ashmem/libc malloc': {'pss': HEAP + TRACING_2, 252 mmaps={'/dev/ashmem/libc malloc': {'pss': HEAP + TRACING_2,
202 'pd': DIRTY + TRACING_2}}, 253 'pd': DIRTY + TRACING_2}},
203 allocators={ 254 allocators={
204 'tracing': {'size': TRACING_1, 'resident_size': TRACING_2}, 255 'tracing': {'size': TRACING_1, 'resident_size': TRACING_2},
205 'malloc': {'size': MALLOC + TRACING_1}})]) 256 'malloc': {'size': MALLOC + TRACING_1}})])
206 257
207 self.assertEquals({'mmaps_overall_pss': HEAP, 258 self.assertEquals({'mmaps_overall_pss': HEAP,
208 'mmaps_private_dirty': DIRTY, 259 'mmaps_private_dirty': DIRTY,
209 'mmaps_java_heap': 0,
210 'mmaps_ashmem': 0,
211 'mmaps_native_heap': HEAP, 260 'mmaps_native_heap': HEAP,
212 'allocator_tracing': TRACING_1, 261 'allocator_tracing': TRACING_1,
213 'allocator_malloc': MALLOC}, 262 'allocator_malloc': MALLOC},
214 memory_dump.GetMemoryUsage()) 263 memory_dump.GetMemoryUsage())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698