#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct HistRow {
pub pretty_class: String,
pub instances: u64,
pub shallow: u64,
pub retained: u64,
#[serde(default)]
pub max_instance_shallow: u64,
#[serde(default)]
pub incoming_ref_count: u64,
pub loader_id: u64,
pub loader_label: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub root_path: Option<Vec<RootPathStep>>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct UnreachableClassRow {
pub pretty_class: String,
pub objects: u64,
pub shallow: u64,
pub retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct UnreachableGarbageRoot {
pub pretty_class: String,
pub retained: u64,
pub objects: u64,
#[serde(default)]
pub children: Vec<UnreachableGarbageRoot>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct GcRootTypeRow {
pub root_type: String,
pub count: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct GcRootClassRow {
pub class_name: String,
pub count: u64,
pub retained: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct GcRootRetainedRow {
pub root_type: String,
pub count: u64,
pub retained: u64,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub top_classes: Vec<GcRootClassRow>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct KindStat {
pub kind: String,
pub objects: u64,
pub shallow_heap: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct HeapComposition {
pub by_kind: Vec<KindStat>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub prim_array_by_type: Vec<KindStat>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct DepthBucket {
pub depth: u32,
pub objects: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct SizeBucket {
pub upper_bytes: u64,
pub count: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct TopSizeDistribution {
pub buckets: Vec<SizeBucket>,
pub count: u64,
pub min: u64,
pub max: u64,
pub median: u64,
pub total: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct RetentionSummary {
pub total_retained: u64,
pub top1_bp: u32,
pub top10_bp: u32,
pub top100_bp: u32,
#[serde(default)]
pub top1_retained: u64,
#[serde(default)]
pub top10_retained: u64,
#[serde(default)]
pub top100_retained: u64,
pub num_objects_ge_1pct: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct PropEntry {
pub key: String,
pub value: String,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct LoaderRollup {
pub loader_label: Option<String>,
pub loader_id: u64,
pub class_count: u64,
pub instances: u64,
pub shallow: u64,
pub retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct TopComponents {
pub components: Vec<Component>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct Component {
pub loader_label: String,
pub retained: u64,
pub pct: f64,
pub top_classes: Vec<ComponentClass>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct ComponentClass {
pub pretty_class: String,
pub retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct DuplicateClassLoaderRow {
pub loader_label: String,
pub loader_id: u64,
pub instances: u64,
pub shallow: u64,
pub retained: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct DuplicateClass {
pub pretty_class: String,
pub loader_count: u64,
pub loaders: Vec<String>,
pub total_instances: u64,
pub total_retained: u64,
#[serde(default)]
pub per_loader: Vec<DuplicateClassLoaderRow>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct BoxedNumberRow {
pub pretty_class: String,
pub instances: u64,
pub total_shallow: u64,
pub pct_of_heap_bp: u32,
pub avg_shallow: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct HeaderOverheadRow {
pub pretty_class: String,
pub instances: u64,
pub header_bytes: u8,
pub total_header_bytes: u64,
pub header_pct_of_shallow_bp: u32,
pub avg_shallow: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct BoxedNumberHolder {
pub class_name: String,
pub boxed_refs: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct SystemOverview {
pub source_name: String,
pub file_path: String,
pub format: String,
pub file_size: u64,
pub identifier_size_bits: u32,
pub compressed_oops: Option<bool>,
pub dump_creation: Option<i64>,
pub total_objects: u64,
pub total_shallow: u64,
pub gc_roots: u64,
pub gc_roots_by_type: Vec<GcRootTypeRow>,
pub heap_composition: HeapComposition,
pub dominator_depth_histogram: Vec<DepthBucket>,
pub retention_concentration: RetentionSummary,
pub classes_loaded: u64,
pub classloaders_loaded: u64,
pub unreachable_count: u64,
pub unreachable_shallow: u64,
#[serde(default)]
pub unreachable_retained: u64,
#[serde(default)]
pub unreachable_composition: HeapComposition,
#[serde(default)]
pub unreachable_garbage_roots: Vec<UnreachableGarbageRoot>,
#[serde(default)]
pub heap_fragmentation_ratio: f64,
#[serde(default)]
pub top_class_concentration_bp: u32,
#[serde(default)]
pub gc_roots_retained_by_type: Vec<GcRootRetainedRow>,
#[serde(default)]
pub unreachable_histogram: Vec<UnreachableClassRow>,
pub histogram: Vec<HistRow>,
pub histogram_truncated_to: Option<u64>,
pub system_properties: Vec<PropEntry>,
pub jvm_version: Option<String>,
pub loader_rollup: Vec<LoaderRollup>,
pub duplicate_classes: Vec<DuplicateClass>,
#[serde(default)]
pub record_census: crate::pass2::RecordCensus,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub duplicate_strings: Option<crate::pass2::DupStrings>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub duplicate_prim_arrays: Option<crate::pass2::DupPrimArrays>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub boxed_numbers: Vec<BoxedNumberRow>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub header_overhead: Vec<HeaderOverheadRow>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub boxed_number_holders: Vec<BoxedNumberHolder>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct PathStep {
pub depth: usize,
pub obj_index_1based: usize,
pub display_class: String,
pub retained: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct RootPathStep {
pub obj_index_1based: usize,
pub display_class: String,
pub retained: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub root_type_label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub field_edge: Option<String>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct DominatedRow {
pub obj_index_1based: usize,
pub display_class: String,
pub shallow: u64,
pub retained: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct DomTreeNode {
pub obj_index_1based: usize,
pub display_class: String,
pub shallow: u64,
pub retained: u64,
pub children: Vec<DomTreeNode>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ObjGraphEdge {
#[serde(default)]
pub field_name: String,
pub child_idx: u32,
pub child_class: String,
pub child_retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct InboundEdge {
pub src_idx: u32,
pub field_name: String,
pub src_class: String,
pub src_shallow: u64,
pub src_retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CaptureParams {
pub edge_cap: usize,
pub size_tier: String,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct SubtreeClassRow {
pub class: String,
pub instance_count: u32,
pub total_shallow: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ObjGraphFlatNode {
pub display_class: String,
pub shallow: u64,
pub retained: u64,
#[serde(default)]
pub edges_unknown: bool,
#[serde(default)]
pub edges_truncated: bool,
pub idom: Option<u32>,
#[serde(default)]
pub dom_subtree_count: u32,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub subtree_classes: Vec<SubtreeClassRow>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct TypeEdge {
pub src_class: String,
pub dst_class: String,
pub edge_count: u64,
pub retained_weight: u64,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub top_field_names: Vec<String>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ObjGraphFlat {
pub nodes: std::collections::HashMap<u32, ObjGraphFlatNode>,
pub edges: std::collections::HashMap<u32, Vec<ObjGraphEdge>>,
pub dom_children: std::collections::HashMap<u32, Vec<u32>>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub root_dom_trees: Vec<(u32, DomTreeNode)>,
pub roots: Vec<u32>,
pub sig_floor_bytes: u64,
#[serde(default, skip_serializing_if = "std::collections::HashMap::is_empty")]
pub inbound_edges: std::collections::HashMap<u32, Vec<InboundEdge>>,
#[serde(default, skip_serializing_if = "std::collections::HashSet::is_empty")]
pub inbound_truncated: std::collections::HashSet<u32>,
#[serde(default)]
pub capture_params: CaptureParams,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct MergedPathNode {
pub display_class: String,
pub object_count: u64,
pub retained: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub root_type_label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub field_edge: Option<String>,
pub children: Vec<MergedPathNode>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct Suspect {
pub is_single: bool,
pub pretty_class: String,
pub instance_count: u64,
pub retained: u64,
pub shallow: u64,
pub path: Vec<PathStep>,
pub accumulation_obj_1based: Option<usize>,
pub accumulation_class: Option<String>,
pub accumulation_retained: Option<u64>,
pub dominated: Vec<DominatedRow>,
pub dominated_total_count: u64,
pub dominated_shown: u64,
pub dominated_by_class: Vec<HistRow>,
pub keywords: Vec<String>,
pub root_type_label: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub root_path: Option<Vec<RootPathStep>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dominator_tree: Option<DomTreeNode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub merged_paths: Option<MergedPathNode>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct LeakSuspects {
pub total_shallow: u64,
pub suspects: Vec<Suspect>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ObjRow {
pub obj_index_1based: usize,
pub display_class: String,
pub shallow: u64,
pub retained: u64,
pub pct_bp: u64,
#[serde(skip)]
#[schemars(skip)]
pub pct: f64,
#[serde(default)]
pub owner: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub held_via: Option<String>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct ClassRow {
pub pretty_class: String,
pub instances: u64,
pub retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct PackageNode {
pub name: String,
pub top_dominator_count: u64,
pub shallow_heap: u64,
pub retained_heap: u64,
pub children: Vec<PackageNode>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct TopConsumers {
pub biggest_objects: Vec<ObjRow>,
pub biggest_classes: Vec<ClassRow>,
pub threshold_bp: u32,
pub biggest_packages: PackageNode,
#[serde(default)]
pub size_distribution: TopSizeDistribution,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ThreadInfo {
pub thread_serial: u32,
pub name: Option<String>,
pub class_name: Option<String>,
pub frames: Vec<String>,
pub local_root_count: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub local_objects: Option<Vec<ThreadLocalObj>>,
#[serde(default)]
pub shallow: u64,
#[serde(default)]
pub retained: u64,
#[serde(default)]
pub max_local_retained: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub context_class_loader: Option<String>,
#[serde(default)]
pub is_daemon: bool,
#[serde(default)]
pub priority: i32,
#[serde(default)]
pub thread_state: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub significant_frames: Vec<SignificantFrame>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct SignificantFrame {
pub frame: String,
pub locals: Vec<SignificantLocal>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct SignificantLocal {
pub display_class: String,
pub retained: u64,
pub pct: f64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct ThreadLocalObj {
pub obj_index_1based: usize,
pub display_class: String,
pub shallow: u64,
pub retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ThreadOverview {
pub threads: Vec<ThreadInfo>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct SizeHistogramBucket {
pub upper_len: u64,
pub objects: u64,
pub shallow: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ArraysBySize {
pub obj_array_buckets: Vec<SizeHistogramBucket>,
pub prim_array_buckets: Vec<SizeHistogramBucket>,
pub zero_length_count: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct BigDropRow {
pub obj_index_1based: u64,
pub display_class: String,
pub retained: u64,
pub child_count: u64,
pub largest_child_retained: u64,
pub largest_child_class: String,
pub drop_bytes: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct BigDrops {
pub threshold: u64,
pub rows: Vec<BigDropRow>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ImmediateDominatorRow {
pub dominator_class: String,
pub dominator_count: u64,
pub dominated_count: u64,
pub dominator_shallow: u64,
pub dominated_shallow: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ImmDomPair {
pub dominator_class: String,
pub dominated_class: String,
pub pair_count: u64,
pub dominated_retained: u64,
pub dominated_shallow: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ImmediateDominators {
pub rows: Vec<ImmediateDominatorRow>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub pairs: Vec<ImmDomPair>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct DominatorAnalysis {
pub big_drops: BigDrops,
pub immediate_dominators: ImmediateDominators,
#[serde(default)]
pub longest_chain_depth: u32,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct FillRatioBucket {
pub lower_ratio_bp: u32,
pub upper_ratio_bp: u32,
pub objects: u64,
pub shallow: u64,
pub wasted: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionFillRatio {
pub tracked: u64,
pub total: u64,
pub buckets: Vec<FillRatioBucket>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionsBySize {
pub tracked: u64,
pub empty_count: u64,
pub buckets: Vec<SizeHistogramBucket>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ArrayFillRatio {
pub tracked: u64,
pub buckets: Vec<FillRatioBucket>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct MapCollisionRatio {
pub tracked: u64,
pub total: u64,
pub buckets: Vec<FillRatioBucket>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ConstantArrayRow {
pub array_class: String,
pub length: u64,
pub value: i64,
pub objects: u64,
pub shallow: u64,
#[serde(default)]
pub owner: Option<String>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ConstantPrimitiveArrays {
pub rows: Vec<ConstantArrayRow>,
pub truncated: bool,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct TopArrayRow {
pub array_class: String,
pub length: u64,
pub shallow: u64,
pub obj_index_1based: u64,
#[serde(default)]
pub non_null: Option<u64>,
#[serde(default)]
pub owner: Option<String>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct TopArrayClassRow {
pub array_class: String,
pub objects: u64,
pub shallow: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct TopArrays {
pub top_individual: Vec<TopArrayRow>,
pub top_by_class: Vec<TopArrayClassRow>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionsAnalysis {
#[serde(default)]
pub collection_fill_ratio: CollectionFillRatio,
#[serde(default)]
pub collections_by_size: CollectionsBySize,
#[serde(default)]
pub array_fill_ratio: ArrayFillRatio,
#[serde(default)]
pub map_collision_ratio: MapCollisionRatio,
#[serde(default)]
pub constant_primitive_arrays: ConstantPrimitiveArrays,
#[serde(default)]
pub top_prim_arrays: TopArrays,
#[serde(default)]
pub top_obj_arrays: TopArrays,
#[serde(default)]
pub kind_summary: CollectionKindSummary,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct WasteSource {
pub label: String,
pub bytes: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub anchor: Option<String>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct WasteSummary {
pub total_bytes: u64,
pub sources: Vec<WasteSource>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionKindStat {
pub kind: String, pub count: u64, pub total_elements: u64, pub total_shallow: u64, pub max_elements: u64, }
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionKindSummary {
pub kinds: Vec<CollectionKindStat>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct FieldAttributionRow {
pub holder_class: String,
pub field: String,
pub container_kind: String,
pub total_elements: u64,
pub total_retained: u64,
pub container_count: u64,
#[serde(default)]
pub holder_instances: u64,
#[serde(default)]
pub total_wasted_slots: u64,
#[serde(default)]
pub total_wasted_bytes: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct FieldAttributionBiggestRow {
pub holder_class: String,
pub field: String,
pub container_class: String,
pub elements: u64,
pub retained: u64,
#[serde(default)]
pub capacity: u64,
#[serde(default)]
pub container_kind: String,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionAttribution {
pub most_overall: Vec<FieldAttributionRow>,
pub biggest_single: Vec<FieldAttributionBiggestRow>,
#[serde(default)]
pub tiny_overhead: Vec<TinyCollectionRow>,
pub truncated: bool,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct TinyCollectionRow {
pub holder_class: String,
pub field: String,
pub container_kind: String,
pub empty_count: u64,
pub singleton_count: u64,
pub overhead_bytes: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct FieldBySizeRow {
pub holder_class: String,
pub field: String,
pub pointee_type: String,
pub total_retained: u64,
pub pointees: u64,
pub holder_instances: u64,
#[serde(default)]
pub elements: u64,
#[serde(default)]
pub category: String,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct FieldsBySize {
pub rows: Vec<FieldBySizeRow>,
pub truncated: bool,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ValueTypeShare {
pub type_name: String,
pub count: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct BiggestCollectionRow {
pub kind: String,
pub container_class: String,
pub elements: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub retained: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub owner: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub dominant_value_type: Option<String>,
#[serde(default)]
pub value_type_breakdown: Vec<ValueTypeShare>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub obj_index_1based: Option<u32>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionKindTable {
pub kind: String,
pub rows: Vec<BiggestCollectionRow>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct BiggestCollections {
pub combined: Vec<BiggestCollectionRow>,
pub by_kind: Vec<CollectionKindTable>,
pub truncated: bool,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionContentsRow {
pub collection_class: String,
pub instances: u64,
pub total_values: u64,
pub top_value_types: Vec<ValueTypeShare>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct CollectionContents {
pub rows: Vec<CollectionContentsRow>,
pub truncated: bool,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct RefStatClassRow {
pub pretty_class: String,
pub objects: u64,
pub shallow: u64,
#[serde(default)]
pub retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ReferenceStats {
pub kind: String,
pub reference_instances: u64,
#[serde(default)]
pub null_referent_count: u64,
pub referent_histogram: Vec<RefStatClassRow>,
pub only_weakly_retained: Vec<RefStatClassRow>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ReferencesAnalysis {
#[serde(default)]
pub soft: Option<ReferenceStats>,
#[serde(default)]
pub weak: Option<ReferenceStats>,
#[serde(default)]
pub phantom: Option<ReferenceStats>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct LeakIndicators {
pub anonymous_class_count: u64,
pub thread_local_null_key_count: u64,
pub direct_byte_buffer_capacity_sum: u64,
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(rename_all = "lowercase")]
pub enum TriageSeverity {
Info,
Warning,
Critical,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct TriageSignal {
pub id: String,
pub severity: TriageSeverity,
pub title: String,
pub detail: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub anchor: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub anchor_label: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bytes: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub nav_class: Option<String>,
}
pub const SCHEMA_VERSION: u32 = 11;
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct FrameworkAnalysis {
pub framework: String,
pub instance_count: u32,
pub total_retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ThreadLocalLeakRow {
pub value_class: String,
pub entry_count: u32,
pub stale_count: u32,
pub retained: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct AllocSite {
pub stack_serial: u32,
pub frames: Vec<String>,
pub object_count: u64,
pub shallow_total: u64,
pub retained_total: u64,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct AllocSites {
pub traces_present: bool,
pub sites: Vec<AllocSite>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct FieldRefStat {
pub field_name: String,
pub null_count: u64,
pub non_null_count: u64,
pub total_retained: u64,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct ClassFieldStats {
pub class_name: String,
pub instance_count: u64,
pub ref_fields: Vec<FieldRefStat>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct FieldStats {
pub classes: Vec<ClassFieldStats>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct Report {
pub schema_version: u32,
pub generated: String,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub truncated_input: bool,
pub overview: SystemOverview,
pub leaks: LeakSuspects,
pub top: TopConsumers,
pub threads: ThreadOverview,
#[serde(default)]
pub top_components: TopComponents,
#[serde(skip_serializing_if = "Option::is_none")]
pub alloc_sites: Option<AllocSites>,
#[serde(default)]
pub arrays_by_size: ArraysBySize,
#[serde(default)]
pub dominator_analysis: DominatorAnalysis,
#[serde(default)]
pub collections: CollectionsAnalysis,
#[serde(default)]
pub references: ReferencesAnalysis,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub collection_attribution: Option<CollectionAttribution>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fields_by_size: Option<FieldsBySize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub biggest_collections: Option<BiggestCollections>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub collection_contents: Option<CollectionContents>,
#[serde(default)]
pub leak_indicators: LeakIndicators,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub waste_summary: Option<WasteSummary>,
#[serde(default)]
pub triage: Vec<TriageSignal>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub top_retainers: Vec<RetainerRow>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub queries: Vec<crate::query::model::QueryResult>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub obj_graph_flat: Option<ObjGraphFlat>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub type_ref_graph: Vec<TypeEdge>,
#[serde(default)]
pub analysis_flags: AnalysisFlags,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub thread_local_analysis: Vec<ThreadLocalLeakRow>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub framework_analysis: Vec<FrameworkAnalysis>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub field_stats: Option<FieldStats>,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct AnalysisFlags {
#[serde(default)]
pub find_duplicates: bool,
#[serde(default)]
pub collections: bool,
#[serde(default)]
pub obj_graph: bool,
#[serde(default)]
pub ref_paths: bool,
}
#[derive(
Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
pub struct RetainerRow {
pub name: String,
pub kind: String,
pub retained: u64,
}
#[cfg(test)]
mod model_completeness {
use super::*;
#[test]
fn obj_graph_flat_has_inbound_fields() {
let flat = ObjGraphFlat::default();
let _ = flat.inbound_edges;
let _ = flat.inbound_truncated;
let _ = &flat.capture_params;
}
}