• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2023 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Contains tables for relevant for TODO."""
15
16from python.generators.trace_processor_table.public import Column as C
17from python.generators.trace_processor_table.public import ColumnFlag
18from python.generators.trace_processor_table.public import CppInt32
19from python.generators.trace_processor_table.public import CppInt64
20from python.generators.trace_processor_table.public import CppOptional
21from python.generators.trace_processor_table.public import CppSelfTableId
22from python.generators.trace_processor_table.public import CppString
23from python.generators.trace_processor_table.public import Table
24from python.generators.trace_processor_table.public import TableDoc
25from python.generators.trace_processor_table.public import CppTableId
26from python.generators.trace_processor_table.public import CppUint32
27
28from src.trace_processor.tables.track_tables import TRACK_TABLE
29
30PROFILER_SMAPS_TABLE = Table(
31    python_module=__file__,
32    class_name='ProfilerSmapsTable',
33    sql_name='profiler_smaps',
34    columns=[
35        C('upid', CppUint32()),
36        C('ts', CppInt64()),
37        C('path', CppString()),
38        C('size_kb', CppInt64()),
39        C('private_dirty_kb', CppInt64()),
40        C('swap_kb', CppInt64()),
41        C('file_name', CppString()),
42        C('start_address', CppInt64()),
43        C('module_timestamp', CppInt64()),
44        C('module_debugid', CppString()),
45        C('module_debug_path', CppString()),
46        C('protection_flags', CppInt64()),
47        C('private_clean_resident_kb', CppInt64()),
48        C('shared_dirty_resident_kb', CppInt64()),
49        C('shared_clean_resident_kb', CppInt64()),
50        C('locked_kb', CppInt64()),
51        C('proportional_resident_kb', CppInt64()),
52    ],
53    tabledoc=TableDoc(
54        doc='''
55          The profiler smaps contains the memory stats for virtual memory ranges
56captured by the [heap profiler](/docs/data-sources/native-heap-profiler.md).
57        ''',
58        group='Callstack profilers',
59        columns={
60            'upid':
61                '''The UniquePID of the process.''',
62            'ts':
63                '''Timestamp of the snapshot. Multiple rows will have the same
64timestamp.''',
65            'path':
66                '''The mmaped file, as per /proc/pid/smaps.''',
67            'size_kb':
68                '''Total size of the mapping.''',
69            'private_dirty_kb':
70                '''KB of this mapping that are private dirty  RSS.''',
71            'swap_kb':
72                '''KB of this mapping that are in swap.''',
73            'file_name':
74                '''''',
75            'start_address':
76                '''''',
77            'module_timestamp':
78                '''''',
79            'module_debugid':
80                '''''',
81            'module_debug_path':
82                '''''',
83            'protection_flags':
84                '''''',
85            'private_clean_resident_kb':
86                '''''',
87            'shared_dirty_resident_kb':
88                '''''',
89            'shared_clean_resident_kb':
90                '''''',
91            'locked_kb':
92                '''''',
93            'proportional_resident_kb':
94                ''''''
95        }))
96
97PACKAGE_LIST_TABLE = Table(
98    python_module=__file__,
99    class_name='PackageListTable',
100    sql_name='package_list',
101    columns=[
102        C('package_name', CppString()),
103        C('uid', CppInt64()),
104        C('debuggable', CppInt32()),
105        C('profileable_from_shell', CppInt32()),
106        C('version_code', CppInt64()),
107    ],
108    tabledoc=TableDoc(
109        doc='''
110          Metadata about packages installed on the system.
111This is generated by the packages_list data-source.
112        ''',
113        group='Misc',
114        columns={
115            'package_name':
116                '''name of the package, e.g. com.google.android.gm.''',
117            'uid':
118                '''UID processes of this package run as.''',
119            'debuggable':
120                '''bool whether this app is debuggable.''',
121            'profileable_from_shell':
122                '''bool whether this app is profileable.''',
123            'version_code':
124                '''versionCode from the APK.'''
125        }))
126
127STACK_PROFILE_MAPPING_TABLE = Table(
128    python_module=__file__,
129    class_name='StackProfileMappingTable',
130    sql_name='stack_profile_mapping',
131    columns=[
132        C('build_id', CppString()),
133        C('exact_offset', CppInt64()),
134        C('start_offset', CppInt64()),
135        C('start', CppInt64()),
136        C('end', CppInt64()),
137        C('load_bias', CppInt64()),
138        C('name', CppString()),
139    ],
140    tabledoc=TableDoc(
141        doc='''
142          A mapping (binary / library) in a process.
143This is generated by the stack profilers: heapprofd and traced_perf.
144        ''',
145        group='Callstack profilers',
146        columns={
147            'build_id': '''hex-encoded Build ID of the binary / library.''',
148            'start': '''start of the mapping in the process' address space.''',
149            'end': '''end of the mapping in the process' address space.''',
150            'name': '''filename of the binary / library.''',
151            'exact_offset': '''''',
152            'start_offset': '''''',
153            'load_bias': ''''''
154        }))
155
156STACK_PROFILE_FRAME_TABLE = Table(
157    python_module=__file__,
158    class_name='StackProfileFrameTable',
159    sql_name='stack_profile_frame',
160    columns=[
161        C('name', CppString()),
162        C('mapping', CppTableId(STACK_PROFILE_MAPPING_TABLE)),
163        C('rel_pc', CppInt64()),
164        C('symbol_set_id', CppOptional(CppUint32())),
165        C('deobfuscated_name', CppOptional(CppString())),
166    ],
167    tabledoc=TableDoc(
168        doc='''
169          A frame on the callstack. This is a location in a program.
170This is generated by the stack profilers: heapprofd and traced_perf.
171        ''',
172        group='Callstack profilers',
173        columns={
174            'name':
175                '''name of the function this location is in.''',
176            'mapping':
177                '''the mapping (library / binary) this location is in.''',
178            'rel_pc':
179                '''the program counter relative to the start of the mapping.''',
180            'symbol_set_id':
181                '''if the profile was offline symbolized, the offline
182symbol information of this frame.''',
183            'deobfuscated_name':
184                ''''''
185        }))
186
187STACK_PROFILE_CALLSITE_TABLE = Table(
188    python_module=__file__,
189    class_name='StackProfileCallsiteTable',
190    sql_name='stack_profile_callsite',
191    columns=[
192        C('depth', CppUint32()),
193        C('parent_id', CppOptional(CppSelfTableId())),
194        C('frame_id', CppTableId(STACK_PROFILE_FRAME_TABLE)),
195    ],
196    tabledoc=TableDoc(
197        doc='''
198          A callsite. This is a list of frames that were on the stack.
199This is generated by the stack profilers: heapprofd and traced_perf.
200        ''',
201        group='Callstack profilers',
202        columns={
203            'depth':
204                '''distance from the bottom-most frame of the callstack.''',
205            'parent_id':
206                '''parent frame on the callstack. NULL for the bottom-most.''',
207            'frame_id':
208                '''frame at this position in the callstack.'''
209        }))
210
211STACK_SAMPLE_TABLE = Table(
212    python_module=__file__,
213    class_name='StackSampleTable',
214    sql_name='stack_sample',
215    columns=[
216        C('ts', CppInt64(), flags=ColumnFlag.SORTED),
217        C('callsite_id', CppTableId(STACK_PROFILE_CALLSITE_TABLE)),
218    ],
219    tabledoc=TableDoc(
220        doc='''
221          Root table for timestamped stack samples.
222        ''',
223        group='Callstack profilers',
224        columns={
225            'ts': '''timestamp of the sample.''',
226            'callsite_id': '''unwound callstack.'''
227        }))
228
229CPU_PROFILE_STACK_SAMPLE_TABLE = Table(
230    python_module=__file__,
231    class_name='CpuProfileStackSampleTable',
232    sql_name='cpu_profile_stack_sample',
233    columns=[
234        C('utid', CppUint32()),
235        C('process_priority', CppInt32()),
236    ],
237    parent=STACK_SAMPLE_TABLE,
238    tabledoc=TableDoc(
239        doc='''
240          Samples from the Chromium stack sampler.
241        ''',
242        group='Callstack profilers',
243        columns={
244            'utid': '''thread that was active when the sample was taken.''',
245            'process_priority': ''''''
246        }))
247
248PERF_SAMPLE_TABLE = Table(
249    python_module=__file__,
250    class_name='PerfSampleTable',
251    sql_name='perf_sample',
252    columns=[
253        C('ts', CppInt64(), flags=ColumnFlag.SORTED),
254        C('utid', CppUint32()),
255        C('cpu', CppUint32()),
256        C('cpu_mode', CppString()),
257        C('callsite_id', CppOptional(CppTableId(STACK_PROFILE_CALLSITE_TABLE))),
258        C('unwind_error', CppOptional(CppString())),
259        C('perf_session_id', CppUint32()),
260    ],
261    tabledoc=TableDoc(
262        doc='''
263          Samples from the traced_perf profiler.
264        ''',
265        group='Callstack profilers',
266        columns={
267            'ts':
268                '''timestamp of the sample.''',
269            'utid':
270                '''sampled thread..''',
271            'cpu':
272                '''the core the sampled thread was running on.''',
273            'cpu_mode':
274                '''execution state (userspace/kernelspace) of the sampled
275thread.''',
276            'callsite_id':
277                '''if set, unwound callstack of the sampled thread.''',
278            'unwind_error':
279                '''if set, indicates that the unwinding for this sample
280encountered an error. Such samples still reference the best-effort
281result via the callsite_id (with a synthetic error frame at the point
282where unwinding stopped).''',
283            'perf_session_id':
284                '''distinguishes samples from different profiling
285streams (i.e. multiple data sources).'''
286        }))
287
288SYMBOL_TABLE = Table(
289    python_module=__file__,
290    class_name='SymbolTable',
291    sql_name='stack_profile_symbol',
292    columns=[
293        C('symbol_set_id',
294          CppUint32(),
295          flags=ColumnFlag.SORTED | ColumnFlag.SET_ID),
296        C('name', CppString()),
297        C('source_file', CppString()),
298        C('line_number', CppUint32()),
299    ],
300    tabledoc=TableDoc(
301        doc='''
302            Symbolization data for a frame. Rows with the same symbol_set_id
303            describe one callframe, with the most-inlined symbol having
304            id == symbol_set_id.
305
306            For instance, if the function foo has an inlined call to the
307            function bar, which has an inlined call to baz, the
308            stack_profile_symbol table would look like this.
309
310            ```
311            |id|symbol_set_id|name         |source_file|line_number|
312            |--|-------------|-------------|-----------|-----------|
313            |1 |      1      |baz          |foo.cc     | 36        |
314            |2 |      1      |bar          |foo.cc     | 30        |
315            |3 |      1      |foo          |foo.cc     | 60        |
316            ```
317        ''',
318        group='Callstack profilers',
319        columns={
320            'name':
321                '''name of the function.''',
322            'source_file':
323                '''name of the source file containing the function.''',
324            'line_number':
325                '''
326                    line number of the frame in the source file. This is the
327                    exact line for the corresponding program counter, not the
328                    beginning of the function.
329                ''',
330            'symbol_set_id':
331                ''''''
332        }))
333
334HEAP_PROFILE_ALLOCATION_TABLE = Table(
335    python_module=__file__,
336    class_name='HeapProfileAllocationTable',
337    sql_name='heap_profile_allocation',
338    columns=[
339        C('ts', CppInt64()),
340        C('upid', CppUint32()),
341        C('heap_name', CppString()),
342        C('callsite_id', CppTableId(STACK_PROFILE_CALLSITE_TABLE)),
343        C('count', CppInt64()),
344        C('size', CppInt64()),
345    ],
346    tabledoc=TableDoc(
347        doc='''
348          Allocations that happened at a callsite.
349
350
351NOTE: this table is not sorted by timestamp intentionanlly - see b/193757386
352for details.
353TODO(b/193757386): readd the sorted flag once this bug is fixed.
354
355This is generated by heapprofd.
356        ''',
357        group='Callstack profilers',
358        columns={
359            'ts':
360                '''the timestamp the allocations happened at. heapprofd batches
361allocations and frees, and all data from a dump will have the same
362timestamp.''',
363            'upid':
364                '''the UniquePID of the allocating process.''',
365            'callsite_id':
366                '''the callsite the allocation happened at.''',
367            'count':
368                '''if positive: number of allocations that happened at this
369callsite. if negative: number of allocations that happened at this callsite
370that were freed.''',
371            'size':
372                '''if positive: size of allocations that happened at this
373callsite. if negative: size of allocations that happened at this callsite
374that were freed.''',
375            'heap_name':
376                ''''''
377        }))
378
379EXPERIMENTAL_FLAMEGRAPH_NODES_TABLE = Table(
380    python_module=__file__,
381    class_name='ExperimentalFlamegraphNodesTable',
382    sql_name='experimental_flamegraph_nodes',
383    columns=[
384        C('ts', CppInt64(), flags=ColumnFlag.SORTED | ColumnFlag.HIDDEN),
385        C('upid', CppUint32(), flags=ColumnFlag.HIDDEN),
386        C('profile_type', CppString(), flags=ColumnFlag.HIDDEN),
387        C('focus_str', CppString(), flags=ColumnFlag.HIDDEN),
388        C('depth', CppUint32()),
389        C('name', CppString()),
390        C('map_name', CppString()),
391        C('count', CppInt64()),
392        C('cumulative_count', CppInt64()),
393        C('size', CppInt64()),
394        C('cumulative_size', CppInt64()),
395        C('alloc_count', CppInt64()),
396        C('cumulative_alloc_count', CppInt64()),
397        C('alloc_size', CppInt64()),
398        C('cumulative_alloc_size', CppInt64()),
399        C('parent_id', CppOptional(CppSelfTableId())),
400        C('source_file', CppOptional(CppString())),
401        C('line_number', CppOptional(CppUint32())),
402        C('upid_group', CppOptional(CppString())),
403    ],
404    tabledoc=TableDoc(
405        doc='''
406            Table used to render flamegraphs. This gives cumulative sizes of
407            nodes in the flamegraph.
408
409            WARNING: This is experimental and the API is subject to change.
410        ''',
411        group='Callstack profilers',
412        columns={
413            'ts': '''''',
414            'upid': '''''',
415            'profile_type': '''''',
416            'focus_str': '''''',
417            'depth': '''''',
418            'name': '''''',
419            'map_name': '''''',
420            'count': '''''',
421            'cumulative_count': '''''',
422            'size': '''''',
423            'cumulative_size': '''''',
424            'alloc_count': '''''',
425            'cumulative_alloc_count': '''''',
426            'alloc_size': '''''',
427            'cumulative_alloc_size': '''''',
428            'parent_id': '''''',
429            'source_file': '''''',
430            'line_number': '''''',
431            'upid_group': ''''''
432        }))
433
434HEAP_GRAPH_CLASS_TABLE = Table(
435    python_module=__file__,
436    class_name='HeapGraphClassTable',
437    sql_name='heap_graph_class',
438    columns=[
439        C('name', CppString()),
440        C('deobfuscated_name', CppOptional(CppString())),
441        C('location', CppOptional(CppString())),
442        C('superclass_id', CppOptional(CppSelfTableId())),
443        C('classloader_id', CppOptional(CppUint32())),
444        C('kind', CppString()),
445    ],
446    tabledoc=TableDoc(
447        doc='''''',
448        group='ART Heap Graphs',
449        columns={
450            'name':
451                '''(potentially obfuscated) name of the class.''',
452            'deobfuscated_name':
453                '''if class name was obfuscated and deobfuscation map
454for it provided, the deobfuscated name.''',
455            'location':
456                '''the APK / Dex / JAR file the class is contained in.
457
458classloader_id should really be HeapGraphObject::id, but that would
459create a loop, which is currently not possible.
460TODO(lalitm): resolve this''',
461            'superclass_id':
462                '''''',
463            'classloader_id':
464                '''''',
465            'kind':
466                ''''''
467        }))
468
469HEAP_GRAPH_OBJECT_TABLE = Table(
470    python_module=__file__,
471    class_name='HeapGraphObjectTable',
472    sql_name='heap_graph_object',
473    columns=[
474        C('upid', CppUint32()),
475        C('graph_sample_ts', CppInt64()),
476        C('self_size', CppInt64()),
477        C('native_size', CppInt64()),
478        C('reference_set_id', CppOptional(CppUint32()), flags=ColumnFlag.DENSE),
479        C('reachable', CppInt32()),
480        C('type_id', CppTableId(HEAP_GRAPH_CLASS_TABLE)),
481        C('root_type', CppOptional(CppString())),
482        C('root_distance', CppInt32(), flags=ColumnFlag.HIDDEN),
483    ],
484    tabledoc=TableDoc(
485        doc='''
486          The objects on the Dalvik heap.
487
488All rows with the same (upid, graph_sample_ts) are one dump.
489        ''',
490        group='ART Heap Graphs',
491        columns={
492            'upid':
493                '''UniquePid of the target.''',
494            'graph_sample_ts':
495                '''timestamp this dump was taken at.''',
496            'self_size':
497                '''size this object uses on the Java Heap.''',
498            'native_size':
499                '''approximate amount of native memory used by this object,
500as reported by libcore.util.NativeAllocationRegistry.size.''',
501            'reference_set_id':
502                '''join key with heap_graph_reference containing all
503objects referred in this object's fields.''',
504            'reachable':
505                '''bool whether this object is reachable from a GC root. If
506false, this object is uncollected garbage.''',
507            'type_id':
508                '''class this object is an instance of.''',
509            'root_type':
510                '''if not NULL, this object is a GC root.''',
511            'root_distance':
512                ''''''
513        }))
514
515HEAP_GRAPH_REFERENCE_TABLE = Table(
516    python_module=__file__,
517    class_name='HeapGraphReferenceTable',
518    sql_name='heap_graph_reference',
519    columns=[
520        C('reference_set_id',
521          CppUint32(),
522          flags=ColumnFlag.SORTED | ColumnFlag.SET_ID),
523        C('owner_id', CppTableId(HEAP_GRAPH_OBJECT_TABLE)),
524        C('owned_id', CppOptional(CppTableId(HEAP_GRAPH_OBJECT_TABLE))),
525        C('field_name', CppString()),
526        C('field_type_name', CppString()),
527        C('deobfuscated_field_name', CppOptional(CppString())),
528    ],
529    tabledoc=TableDoc(
530        doc='''
531          Many-to-many mapping between heap_graph_object.
532
533This associates the object with given reference_set_id with the objects
534that are referred to by its fields.
535        ''',
536        group='ART Heap Graphs',
537        columns={
538            'reference_set_id':
539                '''join key to heap_graph_object.''',
540            'owner_id':
541                '''id of object that has this reference_set_id.''',
542            'owned_id':
543                '''id of object that is referred to.''',
544            'field_name':
545                '''the field that refers to the object. E.g. Foo.name.''',
546            'field_type_name':
547                '''the static type of the field. E.g. java.lang.String.''',
548            'deobfuscated_field_name':
549                '''if field_name was obfuscated and a
550deobfuscation mapping was provided for it, the deobfuscated name.'''
551        }))
552
553VULKAN_MEMORY_ALLOCATIONS_TABLE = Table(
554    python_module=__file__,
555    class_name='VulkanMemoryAllocationsTable',
556    sql_name='vulkan_memory_allocations',
557    columns=[
558        C('arg_set_id', CppOptional(CppUint32())),
559        C('source', CppString()),
560        C('operation', CppString()),
561        C('timestamp', CppInt64()),
562        C('upid', CppOptional(CppUint32())),
563        C('device', CppOptional(CppInt64())),
564        C('device_memory', CppOptional(CppInt64())),
565        C('memory_type', CppOptional(CppUint32())),
566        C('heap', CppOptional(CppUint32())),
567        C('function_name', CppOptional(CppString())),
568        C('object_handle', CppOptional(CppInt64())),
569        C('memory_address', CppOptional(CppInt64())),
570        C('memory_size', CppOptional(CppInt64())),
571        C('scope', CppString()),
572    ],
573    tabledoc=TableDoc(
574        doc='''''',
575        group='Misc',
576        columns={
577            'arg_set_id': '''''',
578            'source': '''''',
579            'operation': '''''',
580            'timestamp': '''''',
581            'upid': '''''',
582            'device': '''''',
583            'device_memory': '''''',
584            'memory_type': '''''',
585            'heap': '''''',
586            'function_name': '''''',
587            'object_handle': '''''',
588            'memory_address': '''''',
589            'memory_size': '''''',
590            'scope': ''''''
591        }))
592
593GPU_COUNTER_GROUP_TABLE = Table(
594    python_module=__file__,
595    class_name='GpuCounterGroupTable',
596    sql_name='gpu_counter_group',
597    columns=[
598        C('group_id', CppInt32()),
599        C('track_id', CppTableId(TRACK_TABLE)),
600    ],
601    tabledoc=TableDoc(
602        doc='''''',
603        group='Misc',
604        columns={
605            'group_id': '''''',
606            'track_id': ''''''
607        }))
608
609# Keep this list sorted.
610ALL_TABLES = [
611    CPU_PROFILE_STACK_SAMPLE_TABLE,
612    EXPERIMENTAL_FLAMEGRAPH_NODES_TABLE,
613    GPU_COUNTER_GROUP_TABLE,
614    HEAP_GRAPH_CLASS_TABLE,
615    HEAP_GRAPH_OBJECT_TABLE,
616    HEAP_GRAPH_REFERENCE_TABLE,
617    HEAP_PROFILE_ALLOCATION_TABLE,
618    PACKAGE_LIST_TABLE,
619    PERF_SAMPLE_TABLE,
620    PROFILER_SMAPS_TABLE,
621    STACK_PROFILE_CALLSITE_TABLE,
622    STACK_PROFILE_FRAME_TABLE,
623    STACK_PROFILE_MAPPING_TABLE,
624    STACK_SAMPLE_TABLE,
625    SYMBOL_TABLE,
626    VULKAN_MEMORY_ALLOCATIONS_TABLE,
627]
628