diff --git a/README.md b/README.md index d293694..c88724f 100755 --- a/README.md +++ b/README.md @@ -55,28 +55,30 @@ Found a total of 2.53MiB of instances allocated on the heap. Top 20 allocated classes: -Total size | Instances | Largest | Class name ----------------------------------------------------------------------------------- - 1.99MiB | 436 | 634.78KiB | int[] - 197.11KiB | 1991 | 16.02KiB | char[] - 85.25KiB | 443 | 8.02KiB | byte[] - 47.38KiB | 1516 | 32.00bytes | java.lang.String - 45.42KiB | 560 | 8.02KiB | java.lang.Object[] - 15.26KiB | 126 | 124.00bytes | java.lang.reflect.Field - 14.77KiB | 378 | 40.00bytes | java.util.LinkedList$Node - 9.94KiB | 212 | 48.00bytes | java.util.HashMap$Node - 8.91KiB | 190 | 48.00bytes | java.util.LinkedList - 8.42KiB | 98 | 88.00bytes | java.lang.ref.SoftReference - 6.05KiB | 258 | 24.00bytes | java.lang.Integer - 5.91KiB | 18 | 2.02KiB | java.util.HashMap$Node[] - 5.86KiB | 150 | 40.00bytes | java.lang.StringBuilder - 5.44KiB | 116 | 48.00bytes | java.util.Hashtable$Entry - 5.05KiB | 38 | 136.00bytes | sun.util.locale.LocaleObjectCache$CacheEntry - 5.00KiB | 40 | 128.00bytes | java.lang.ref.Finalizer - 3.50KiB | 32 | 112.00bytes | java.net.URL - 3.42KiB | 73 | 48.00bytes | java.io.File - 3.17KiB | 12 | 776.00bytes | java.util.Hashtable$Entry[] - 3.13KiB | 56 | 144.00bytes | java.lang.String[] ++------------+-----------+-------------+----------------------------------------------+ +| Total size | Instances | Largest | Class name | ++------------+-----------+-------------+----------------------------------------------+ +| 1.99MiB | 436 | 634.78KiB | int[] | +| 197.11KiB | 1991 | 16.02KiB | char[] | +| 85.25KiB | 443 | 8.02KiB | byte[] | +| 47.38KiB | 1516 | 32.00bytes | java.lang.String | +| 45.42KiB | 560 | 8.02KiB | java.lang.Object[] | +| 15.26KiB | 126 | 124.00bytes | java.lang.reflect.Field | +| 14.77KiB | 378 | 40.00bytes | java.util.LinkedList$Node | +| 9.94KiB | 212 | 48.00bytes | java.util.HashMap$Node | +| 8.91KiB | 190 | 48.00bytes | java.util.LinkedList | +| 8.42KiB | 98 | 88.00bytes | java.lang.ref.SoftReference | +| 6.05KiB | 258 | 24.00bytes | java.lang.Integer | +| 5.91KiB | 18 | 2.02KiB | java.util.HashMap$Node[] | +| 5.86KiB | 150 | 40.00bytes | java.lang.StringBuilder | +| 5.44KiB | 116 | 48.00bytes | java.util.Hashtable$Entry | +| 5.05KiB | 38 | 136.00bytes | sun.util.locale.LocaleObjectCache$CacheEntry | +| 5.00KiB | 40 | 128.00bytes | java.lang.ref.Finalizer | +| 3.50KiB | 32 | 112.00bytes | java.net.URL | +| 3.42KiB | 73 | 48.00bytes | java.io.File | +| 3.17KiB | 12 | 776.00bytes | java.util.Hashtable$Entry[] | +| 3.13KiB | 56 | 144.00bytes | java.lang.String[] | ++------------+-----------+-------------+----------------------------------------------+ ``` ## Installation diff --git a/src/result_recorder.rs b/src/result_recorder.rs index a1601c4..a44ff67 100644 --- a/src/result_recorder.rs +++ b/src/result_recorder.rs @@ -597,45 +597,96 @@ impl ResultRecorder { |r| r.3.to_string(), class_name_header, ); + let class_name_len = class_name_header.chars().count() + class_name_padding.chars().count(); + // headers with padding + let total_size_header = format!(" {}{} ", total_size_header_padding, total_size_header); + let instance_count_header = format!( + " {}{} ", + instance_count_header_padding, instance_count_header + ); + let largest_instance_header = + format!(" {}{} ", largest_instance_padding, largest_instance_header,); + let class_name_header = format!(" {}{} ", class_name_header, class_name_padding); + + // render line before header + Self::render_table_vertical_line( + analysis, + &total_size_header, + &instance_count_header, + &largest_instance_header, + &class_name_header, + ); + + // render header let header = format!( - "{}{} | {}{} | {}{} | {}{}\n", - total_size_header_padding, - total_size_header, - instance_count_header_padding, - instance_count_header, - largest_instance_padding, - largest_instance_header, - class_name_header, - class_name_padding + "|{}|{}|{}|{}|", + total_size_header, instance_count_header, largest_instance_header, class_name_header ); - let header_len = header.chars().count(); analysis.push_str(&header); - analysis.push_str(&("-".repeat(header_len))); analysis.push('\n'); - rows_formatted.into_iter().for_each( - |(allocation_size, count, largest_allocation_size, class_name)| { - let padding_size_str = - ResultRecorder::column_padding(&allocation_size, total_size_len); - let padding_count_str = - ResultRecorder::column_padding(&count.to_string(), instance_len); - let padding_largest_size_str = - ResultRecorder::column_padding(&largest_allocation_size, largest_len); - - let row = format!( - "{}{} | {}{} | {}{} | {}\n", - padding_size_str, - allocation_size, - padding_count_str, - count, - padding_largest_size_str, - largest_allocation_size, - class_name - ); - analysis.push_str(&row); - }, + // render line after header + Self::render_table_vertical_line( + analysis, + &total_size_header, + &instance_count_header, + &largest_instance_header, + &class_name_header, ); + + // render rows + for (allocation_size, count, largest_allocation_size, class_name) in rows_formatted { + let padding_size_str = ResultRecorder::column_padding(&allocation_size, total_size_len); + let padding_count_str = + ResultRecorder::column_padding(&count.to_string(), instance_len); + let padding_largest_size_str = + ResultRecorder::column_padding(&largest_allocation_size, largest_len); + let padding_largest_class_name_str = + ResultRecorder::column_padding(class_name, class_name_len); + + let row = format!( + "| {}{} | {}{} | {}{} | {}{} |", + padding_size_str, + allocation_size, + padding_count_str, + count, + padding_largest_size_str, + largest_allocation_size, + class_name, + padding_largest_class_name_str + ); + analysis.push_str(&row); + analysis.push('\n'); + } + + // render line after rows + Self::render_table_vertical_line( + analysis, + &total_size_header, + &instance_count_header, + &largest_instance_header, + &class_name_header, + ); + } + + pub fn render_table_vertical_line( + analysis: &mut String, + total_size_header: &str, + instance_count_header: &str, + largest_instance_header: &str, + class_name_header: &str, + ) { + analysis.push('+'); + analysis.push_str(&("-".repeat(total_size_header.chars().count()))); + analysis.push('+'); + analysis.push_str(&("-".repeat(instance_count_header.chars().count()))); + analysis.push('+'); + analysis.push_str(&("-".repeat(largest_instance_header.chars().count()))); + analysis.push('+'); + analysis.push_str(&("-".repeat(class_name_header.chars().count()))); + analysis.push('+'); + analysis.push('\n'); } fn padding_for_header( diff --git a/test-heap-dumps/hprof-64-result.txt b/test-heap-dumps/hprof-64-result.txt index 1cc52ec..b1fc4b9 100644 --- a/test-heap-dumps/hprof-64-result.txt +++ b/test-heap-dumps/hprof-64-result.txt @@ -67,50 +67,54 @@ Found a total of 2.53MiB of instances allocated on the heap. Top 20 allocated classes: -Total size | Instances | Largest | Class name ------------------------------------------------------------------------------------- - 1.99MiB | 436 | 634.78KiB | int[] - 197.11KiB | 1991 | 16.02KiB | char[] - 85.25KiB | 443 | 8.02KiB | byte[] - 47.38KiB | 1516 | 32.00bytes | java.lang.String - 45.42KiB | 560 | 8.02KiB | java.lang.Object[] - 15.26KiB | 126 | 124.00bytes | java.lang.reflect.Field - 14.77KiB | 378 | 40.00bytes | java.util.LinkedList$Node - 9.94KiB | 212 | 48.00bytes | java.util.HashMap$Node - 8.91KiB | 190 | 48.00bytes | java.util.LinkedList - 8.42KiB | 98 | 88.00bytes | java.lang.ref.SoftReference - 6.05KiB | 258 | 24.00bytes | java.lang.Integer - 5.91KiB | 18 | 2.02KiB | java.util.HashMap$Node[] - 5.86KiB | 150 | 40.00bytes | java.lang.StringBuilder - 5.44KiB | 116 | 48.00bytes | java.util.Hashtable$Entry - 5.05KiB | 38 | 136.00bytes | sun.util.locale.LocaleObjectCache$CacheEntry - 5.00KiB | 40 | 128.00bytes | java.lang.ref.Finalizer - 3.50KiB | 32 | 112.00bytes | java.net.URL - 3.42KiB | 73 | 48.00bytes | java.io.File - 3.17KiB | 12 | 776.00bytes | java.util.Hashtable$Entry[] - 3.13KiB | 56 | 144.00bytes | java.lang.String[] ++------------+-----------+-------------+----------------------------------------------+ +| Total size | Instances | Largest | Class name | ++------------+-----------+-------------+----------------------------------------------+ +| 1.99MiB | 436 | 634.78KiB | int[] | +| 197.11KiB | 1991 | 16.02KiB | char[] | +| 85.25KiB | 443 | 8.02KiB | byte[] | +| 47.38KiB | 1516 | 32.00bytes | java.lang.String | +| 45.42KiB | 560 | 8.02KiB | java.lang.Object[] | +| 15.26KiB | 126 | 124.00bytes | java.lang.reflect.Field | +| 14.77KiB | 378 | 40.00bytes | java.util.LinkedList$Node | +| 9.94KiB | 212 | 48.00bytes | java.util.HashMap$Node | +| 8.91KiB | 190 | 48.00bytes | java.util.LinkedList | +| 8.42KiB | 98 | 88.00bytes | java.lang.ref.SoftReference | +| 6.05KiB | 258 | 24.00bytes | java.lang.Integer | +| 5.91KiB | 18 | 2.02KiB | java.util.HashMap$Node[] | +| 5.86KiB | 150 | 40.00bytes | java.lang.StringBuilder | +| 5.44KiB | 116 | 48.00bytes | java.util.Hashtable$Entry | +| 5.05KiB | 38 | 136.00bytes | sun.util.locale.LocaleObjectCache$CacheEntry | +| 5.00KiB | 40 | 128.00bytes | java.lang.ref.Finalizer | +| 3.50KiB | 32 | 112.00bytes | java.net.URL | +| 3.42KiB | 73 | 48.00bytes | java.io.File | +| 3.17KiB | 12 | 776.00bytes | java.util.Hashtable$Entry[] | +| 3.13KiB | 56 | 144.00bytes | java.lang.String[] | ++------------+-----------+-------------+----------------------------------------------+ Top 20 largest instances: - Total size | Instances | Largest | Class name --------------------------------------------------------------------------------------- - 1.99MiB | 436 | 634.78KiB | int[] - 197.11KiB | 1991 | 16.02KiB | char[] - 85.25KiB | 443 | 8.02KiB | byte[] - 45.42KiB | 560 | 8.02KiB | java.lang.Object[] - 5.91KiB | 18 | 2.02KiB | java.util.HashMap$Node[] - 2.05KiB | 2 | 2.02KiB | java.lang.invoke.MethodHandle[] - 2.02KiB | 1 | 2.02KiB | java.lang.Integer[] - 3.17KiB | 12 | 776.00bytes | java.util.Hashtable$Entry[] -462.00bytes | 1 | 462.00bytes | sun.misc.Launcher$AppClassLoader -454.00bytes | 1 | 454.00bytes | sun.misc.Launcher$ExtClassLoader -680.00bytes | 2 | 340.00bytes | simple.Producer -680.00bytes | 2 | 340.00bytes | simple.Consumer - 2.30KiB | 7 | 336.00bytes | java.util.jar.JarFile$JarFileEntry -334.00bytes | 1 | 334.00bytes | java.lang.ref.Finalizer$FinalizerThread -332.00bytes | 1 | 332.00bytes | java.lang.ref.Reference$ReferenceHandler - 1.01KiB | 9 | 312.00bytes | java.lang.reflect.Field[] - 1.48KiB | 7 | 272.00bytes | java.util.concurrent.ConcurrentHashMap$Node[] -236.00bytes | 1 | 236.00bytes | sun.net.www.protocol.file.FileURLConnection -440.00bytes | 2 | 220.00bytes | java.io.ExpiringCache$1 -432.00bytes | 2 | 216.00bytes | java.lang.NoSuchMethodError ++-------------+-----------+-------------+-----------------------------------------------+ +| Total size | Instances | Largest | Class name | ++-------------+-----------+-------------+-----------------------------------------------+ +| 1.99MiB | 436 | 634.78KiB | int[] | +| 197.11KiB | 1991 | 16.02KiB | char[] | +| 85.25KiB | 443 | 8.02KiB | byte[] | +| 45.42KiB | 560 | 8.02KiB | java.lang.Object[] | +| 5.91KiB | 18 | 2.02KiB | java.util.HashMap$Node[] | +| 2.05KiB | 2 | 2.02KiB | java.lang.invoke.MethodHandle[] | +| 2.02KiB | 1 | 2.02KiB | java.lang.Integer[] | +| 3.17KiB | 12 | 776.00bytes | java.util.Hashtable$Entry[] | +| 462.00bytes | 1 | 462.00bytes | sun.misc.Launcher$AppClassLoader | +| 454.00bytes | 1 | 454.00bytes | sun.misc.Launcher$ExtClassLoader | +| 680.00bytes | 2 | 340.00bytes | simple.Producer | +| 680.00bytes | 2 | 340.00bytes | simple.Consumer | +| 2.30KiB | 7 | 336.00bytes | java.util.jar.JarFile$JarFileEntry | +| 334.00bytes | 1 | 334.00bytes | java.lang.ref.Finalizer$FinalizerThread | +| 332.00bytes | 1 | 332.00bytes | java.lang.ref.Reference$ReferenceHandler | +| 1.01KiB | 9 | 312.00bytes | java.lang.reflect.Field[] | +| 1.48KiB | 7 | 272.00bytes | java.util.concurrent.ConcurrentHashMap$Node[] | +| 236.00bytes | 1 | 236.00bytes | sun.net.www.protocol.file.FileURLConnection | +| 440.00bytes | 2 | 220.00bytes | java.io.ExpiringCache$1 | +| 432.00bytes | 2 | 216.00bytes | java.lang.NoSuchMethodError | ++-------------+-----------+-------------+-----------------------------------------------+ \ No newline at end of file