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