Introduce dmabuf_allocs to stdlib
With inode-based buffer tracking and allocation re-attribution by
following binders to gralloc.
Bug: 339536476
Change-Id: Ib59348bd248869be74b22f9c4b7e9bc7a699cef8
diff --git a/Android.bp b/Android.bp
index 09c661a..3da4304 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13118,6 +13118,7 @@
"src/trace_processor/perfetto_sql/stdlib/android/input.sql",
"src/trace_processor/perfetto_sql/stdlib/android/io.sql",
"src/trace_processor/perfetto_sql/stdlib/android/job_scheduler.sql",
+ "src/trace_processor/perfetto_sql/stdlib/android/memory/dmabuf.sql",
"src/trace_processor/perfetto_sql/stdlib/android/memory/heap_graph/dominator_tree.sql",
"src/trace_processor/perfetto_sql/stdlib/android/memory/process.sql",
"src/trace_processor/perfetto_sql/stdlib/android/monitor_contention.sql",
diff --git a/BUILD b/BUILD
index d336746..de47252 100644
--- a/BUILD
+++ b/BUILD
@@ -2536,6 +2536,7 @@
perfetto_filegroup(
name = "src_trace_processor_perfetto_sql_stdlib_android_memory_memory",
srcs = [
+ "src/trace_processor/perfetto_sql/stdlib/android/memory/dmabuf.sql",
"src/trace_processor/perfetto_sql/stdlib/android/memory/process.sql",
],
)
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/memory/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/android/memory/BUILD.gn
index e6555fc..af2894d 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/memory/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/android/memory/BUILD.gn
@@ -16,5 +16,8 @@
perfetto_sql_source_set("memory") {
deps = [ "heap_graph" ]
- sources = [ "process.sql" ]
+ sources = [
+ "dmabuf.sql",
+ "process.sql",
+ ]
}
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/memory/dmabuf.sql b/src/trace_processor/perfetto_sql/stdlib/android/memory/dmabuf.sql
new file mode 100644
index 0000000..1576e9c
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/android/memory/dmabuf.sql
@@ -0,0 +1,100 @@
+--
+-- Copyright 2024 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the 'License');
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an 'AS IS' BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+INCLUDE PERFETTO MODULE android.binder;
+INCLUDE PERFETTO MODULE slices.with_context;
+
+-- Raw ftrace events
+CREATE PERFETTO TABLE _raw_dmabuf_events AS
+SELECT
+ (SELECT int_value FROM args WHERE arg_set_id = c.arg_set_id AND key = 'inode') AS inode,
+ tt.utid,
+ c.ts,
+ CAST(c.value AS INT) AS buf_size
+FROM thread_counter_track tt
+ JOIN counter c ON c.track_id = tt.id
+WHERE tt.name = 'mem.dma_heap_change';
+
+-- gralloc binder reply slices
+CREATE PERFETTO TABLE _gralloc_binders AS
+SELECT
+ id AS gralloc_binder_reply_id,
+ utid,
+ ts,
+ dur
+FROM thread_slice
+WHERE process_name GLOB '/vendor/bin/hw/android.hardware.graphics.allocator*'
+AND name = 'binder reply';
+
+-- Match gralloc thread allocations to inbound binders
+CREATE PERFETTO TABLE _attributed_dmabufs AS
+SELECT
+ r.inode,
+ r.ts,
+ r.buf_size,
+ IFNULL(b.client_utid, r.utid) AS attr_utid
+FROM _raw_dmabuf_events r
+LEFT JOIN _gralloc_binders gb ON r.utid = gb.utid AND r.ts BETWEEN gb.ts AND gb.ts + gb.dur
+LEFT JOIN android_binder_txns b ON gb.gralloc_binder_reply_id = b.binder_reply_id
+ORDER BY r.inode, r.ts;
+
+CREATE PERFETTO FUNCTION _alloc_source(is_alloc BOOL, inode INT, ts INT)
+RETURNS INT AS
+SELECT attr_utid
+FROM _attributed_dmabufs
+WHERE
+ inode = $inode
+ AND (
+ ($is_alloc AND ts = $ts) OR
+ (NOT $is_alloc AND ts < $ts)
+ )
+ORDER BY ts DESC
+LIMIT 1;
+
+-- Track dmabuf allocations, re-attributing gralloc allocations to their source
+-- (if binder transactions to gralloc are recorded).
+CREATE PERFETTO TABLE android_dmabuf_allocs (
+ -- timestamp of the allocation
+ ts INT,
+ -- allocation size (will be negative for release)
+ buf_size INT,
+ -- dmabuf inode
+ inode INT,
+ -- utid of thread responsible for the allocation
+ -- if a dmabuf is allocated by gralloc we follow the binder transaction
+ -- to the requesting thread (requires binder tracing)
+ utid INT,
+ -- tid of thread responsible for the allocation
+ tid INT,
+ -- thread name
+ thread_name STRING,
+ -- upid of process responsible for the allocation (matches utid)
+ upid INT,
+ -- pid of process responsible for the allocation
+ pid INT,
+ -- process name
+ process_name STRING
+) AS
+WITH _thread_allocs AS (
+ SELECT inode, ts, buf_size, _alloc_source(buf_size > 0, inode, ts) AS utid
+ FROM _attributed_dmabufs
+)
+SELECT ts, buf_size, inode,
+ utid, tid, thread.name AS thread_name,
+ upid, pid, process.name AS process_name
+FROM _thread_allocs allocs
+JOIN thread USING (utid)
+LEFT JOIN process USING (upid)
+ORDER BY ts;
diff --git a/test/trace_processor/diff_tests/stdlib/android/memory.py b/test/trace_processor/diff_tests/stdlib/android/memory.py
index 1da5baf..b62c680 100644
--- a/test/trace_processor/diff_tests/stdlib/android/memory.py
+++ b/test/trace_processor/diff_tests/stdlib/android/memory.py
@@ -46,3 +46,99 @@
1737069091010,682459310,975,"cached",289,"com.android.packageinstaller",2480,332,1737064421516,29484835,1217,"binder:642_1","processEnd","IActivityManager#1598246212",49364992,52539392,827392,102731776,0,49364992,102731776
1737069240534,489635,985,"cached",268,"com.android.managedprovisioning",1868,332,1737064421516,29484835,1217,"binder:642_1","processEnd","IActivityManager#1598246212",50683904,53985280,815104,105484288,0,50683904,105484288
"""))
+
+ def test_memory_dmabuf(self):
+ return DiffTestBlueprint(
+ trace=TextProto(r"""
+ packet {
+ ftrace_events {
+ cpu: 0
+ event {
+ timestamp: 1
+ pid: 3000
+ dma_heap_stat {
+ inode: 13583
+ len: 3000
+ total_allocated: 3000
+ }
+ }
+ event {
+ timestamp: 2
+ pid: 3000
+ dma_heap_stat {
+ inode: 13583
+ len: -3000
+ total_allocated: 0
+ }
+ }
+ event {
+ timestamp: 4144791776152
+ pid: 9403
+ binder_transaction {
+ debug_id: 3052940
+ target_node: 256
+ to_proc: 572
+ to_thread: 0
+ reply: 0
+ code: 1
+ flags: 16
+ }
+ }
+ event {
+ timestamp: 4144791793486
+ pid: 591
+ binder_transaction_received {
+ debug_id: 3052940
+ }
+ }
+ event {
+ timestamp: 4144792258492
+ pid: 591
+ dma_heap_stat {
+ inode: 13583
+ len: 10399744
+ total_allocated: 254873600
+ }
+ }
+ event {
+ timestamp: 4144792517566
+ pid: 591
+ binder_transaction {
+ debug_id: 3052950
+ target_node: 0
+ to_proc: 2051
+ to_thread: 9403
+ reply: 1
+ code: 0
+ flags: 0
+ }
+ }
+ event {
+ timestamp: 4144792572498
+ pid: 9403
+ binder_transaction_received {
+ debug_id: 3052950
+ }
+ }
+ event {
+ timestamp: 4145263509021
+ pid: 613
+ dma_heap_stat {
+ inode: 13583
+ len: -10399744
+ total_allocated: 390160384
+ }
+ }
+ }
+ }"""),
+ query="""
+ INCLUDE PERFETTO MODULE android.memory.dmabuf;
+ SELECT * FROM android_dmabuf_allocs;
+ """,
+ out=Csv("""
+ "ts","buf_size","inode","utid","tid","thread_name","upid","pid","process_name"
+ 1,3000,13583,1,3000,"[NULL]","[NULL]","[NULL]","[NULL]"
+ 2,-3000,13583,1,3000,"[NULL]","[NULL]","[NULL]","[NULL]"
+ 4144792258492,10399744,13583,3,591,"[NULL]","[NULL]","[NULL]","[NULL]"
+ 4145263509021,-10399744,13583,3,591,"[NULL]","[NULL]","[NULL]","[NULL]"
+ """))
\ No newline at end of file