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