1-- 2-- Copyright 2019 The Android Open Source Project 3-- 4-- Licensed under the Apache License, Version 2.0 (the "License"); 5-- you may not use this file except in compliance with the License. 6-- You may obtain a copy of the License at 7-- 8-- https://www.apache.org/licenses/LICENSE-2.0 9-- 10-- Unless required by applicable law or agreed to in writing, software 11-- distributed under the License is distributed on an "AS IS" BASIS, 12-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13-- See the License for the specific language governing permissions and 14-- limitations under the License. 15-- 16 17SELECT RUN_METRIC('android/process_metadata.sql'); 18SELECT RUN_METRIC('android/process_mem.sql'); 19 20CREATE VIEW java_heap_stats_output AS 21WITH 22-- Base view 23base_stat_counts AS ( 24 SELECT 25 upid, 26 graph_sample_ts, 27 SUM(self_size) AS total_size, 28 COUNT(1) AS total_obj_count, 29 SUM(CASE reachable WHEN TRUE THEN self_size ELSE 0 END) AS reachable_size, 30 SUM(CASE reachable WHEN TRUE THEN 1 ELSE 0 END) AS reachable_obj_count 31 FROM heap_graph_object 32 GROUP BY 1, 2 33), 34heap_roots AS ( 35 SELECT 36 upid, 37 graph_sample_ts, 38 root_type, 39 IFNULL(t.deobfuscated_name, t.name) type_name, 40 COUNT(1) obj_count 41 FROM heap_graph_object o 42 JOIN heap_graph_class t ON o.type_id = t.id 43 -- Classes are going to be particularly spammy and uninteresting 44 -- from a memory analysis perspective (compared e.g. to local jni roots) 45 WHERE root_type IS NOT NULL AND root_type != 'ROOT_STICKY_CLASS' 46 GROUP BY 1, 2, 3, 4 47 ORDER BY obj_count DESC 48), 49heap_roots_proto AS ( 50 SELECT 51 upid, 52 graph_sample_ts, 53 RepeatedField(JavaHeapStats_HeapRoots( 54 'root_type', root_type, 55 'type_name', type_name, 56 'obj_count', obj_count 57 )) roots 58 FROM heap_roots 59 GROUP BY 1, 2 60), 61base_stats AS ( 62 SELECT * FROM base_stat_counts JOIN heap_roots_proto USING (upid, graph_sample_ts) 63), 64-- Find closest value 65closest_anon_swap AS ( 66 SELECT 67 upid, 68 graph_sample_ts, 69 ( 70 SELECT anon_swap_val 71 FROM ( 72 SELECT 73 ts, dur, 74 CAST(anon_and_swap_val AS INTEGER) anon_swap_val, 75 ABS(ts - base_stats.graph_sample_ts) diff 76 FROM anon_and_swap_span 77 WHERE upid = base_stats.upid) 78 WHERE 79 (graph_sample_ts >= ts AND graph_sample_ts < ts + dur) 80 -- If the first memory sample for the UPID comes *after* the heap profile 81 -- accept it if close (500ms) 82 OR (graph_sample_ts < ts AND diff <= 500 * 1e6) 83 ORDER BY diff LIMIT 1 84 ) val 85 FROM base_stats 86), 87-- Group by upid 88heap_graph_sample_protos AS ( 89 SELECT 90 base_stats.upid, 91 RepeatedField(JavaHeapStats_Sample( 92 'ts', graph_sample_ts, 93 'heap_size', total_size, 94 'obj_count', total_obj_count, 95 'reachable_heap_size', reachable_size, 96 'reachable_obj_count', reachable_obj_count, 97 'roots', roots, 98 'anon_rss_and_swap_size', closest_anon_swap.val 99 )) sample_protos 100 FROM base_stats 101 LEFT JOIN closest_anon_swap USING (upid, graph_sample_ts) 102 GROUP BY 1 103) 104SELECT JavaHeapStats( 105 'instance_stats', RepeatedField(JavaHeapStats_InstanceStats( 106 'upid', upid, 107 'process', process_metadata.metadata, 108 'samples', sample_protos 109 ))) 110FROM heap_graph_sample_protos JOIN process_metadata USING (upid); 111