1 /* 2 * Copyright (C) 2015 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 * http://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 17 package com.android.ahat.heapdump; 18 19 import java.util.ArrayList; 20 import java.util.Arrays; 21 import java.util.Comparator; 22 import java.util.Iterator; 23 import java.util.List; 24 25 /** 26 * Provides Comparators and helper functions for sorting Instances, Sites, and 27 * other things. 28 * 29 * Note: The Comparators defined here impose orderings that are inconsistent 30 * with equals. They should not be used for element lookup or search. They 31 * should only be used for showing elements to the user in different orders. 32 */ 33 public class Sort { 34 /** 35 * Compare instances by their total retained size. 36 * Different instances with the same total retained size are considered 37 * equal for the purposes of comparison. 38 * This sorts instances from larger retained size to smaller retained size. 39 */ 40 public static final Comparator<AhatInstance> INSTANCE_BY_TOTAL_RETAINED_SIZE 41 = new Comparator<AhatInstance>() { 42 @Override 43 public int compare(AhatInstance a, AhatInstance b) { 44 return Long.compare(b.getTotalRetainedSize(), a.getTotalRetainedSize()); 45 } 46 }; 47 48 /** 49 * Compare instances by their retained size for a given heap index. 50 * Different instances with the same total retained size are considered 51 * equal for the purposes of comparison. 52 * This sorts instances from larger retained size to smaller retained size. 53 */ 54 public static class InstanceByHeapRetainedSize implements Comparator<AhatInstance> { 55 private AhatHeap mHeap; 56 InstanceByHeapRetainedSize(AhatHeap heap)57 public InstanceByHeapRetainedSize(AhatHeap heap) { 58 mHeap = heap; 59 } 60 61 @Override compare(AhatInstance a, AhatInstance b)62 public int compare(AhatInstance a, AhatInstance b) { 63 return Long.compare(b.getRetainedSize(mHeap), a.getRetainedSize(mHeap)); 64 } 65 } 66 67 /** 68 * Compare objects based on a list of comparators, giving priority to the 69 * earlier comparators in the list. 70 */ 71 public static class WithPriority<T> implements Comparator<T> { 72 private List<Comparator<T>> mComparators; 73 WithPriority(Comparator<T>.... comparators)74 public WithPriority(Comparator<T>... comparators) { 75 mComparators = Arrays.asList(comparators); 76 } 77 WithPriority(List<Comparator<T>> comparators)78 public WithPriority(List<Comparator<T>> comparators) { 79 mComparators = comparators; 80 } 81 82 @Override compare(T a, T b)83 public int compare(T a, T b) { 84 int res = 0; 85 Iterator<Comparator<T>> iter = mComparators.iterator(); 86 while (res == 0 && iter.hasNext()) { 87 res = iter.next().compare(a, b); 88 } 89 return res; 90 } 91 } 92 defaultInstanceCompare(AhatSnapshot snapshot)93 public static Comparator<AhatInstance> defaultInstanceCompare(AhatSnapshot snapshot) { 94 List<Comparator<AhatInstance>> comparators = new ArrayList<Comparator<AhatInstance>>(); 95 96 // Priority goes to the app heap, if we can find one. 97 AhatHeap appHeap = snapshot.getHeap("app"); 98 if (appHeap != null) { 99 comparators.add(new InstanceByHeapRetainedSize(appHeap)); 100 } 101 102 // Next is by total retained size. 103 comparators.add(INSTANCE_BY_TOTAL_RETAINED_SIZE); 104 return new WithPriority<AhatInstance>(comparators); 105 } 106 107 /** 108 * Compare Sites by the size of objects allocated on a given heap. 109 * Different object infos with the same size on the given heap are 110 * considered equal for the purposes of comparison. 111 * This sorts sites from larger size to smaller size. 112 */ 113 public static class SiteByHeapSize implements Comparator<Site> { 114 AhatHeap mHeap; 115 SiteByHeapSize(AhatHeap heap)116 public SiteByHeapSize(AhatHeap heap) { 117 mHeap = heap; 118 } 119 120 @Override compare(Site a, Site b)121 public int compare(Site a, Site b) { 122 return Long.compare(b.getSize(mHeap), a.getSize(mHeap)); 123 } 124 } 125 126 /** 127 * Compare Sites by the total size of objects allocated. 128 * This sorts sites from larger size to smaller size. 129 */ 130 public static final Comparator<Site> SITE_BY_TOTAL_SIZE = new Comparator<Site>() { 131 @Override 132 public int compare(Site a, Site b) { 133 return Long.compare(b.getTotalSize(), a.getTotalSize()); 134 } 135 }; 136 defaultSiteCompare(AhatSnapshot snapshot)137 public static Comparator<Site> defaultSiteCompare(AhatSnapshot snapshot) { 138 List<Comparator<Site>> comparators = new ArrayList<Comparator<Site>>(); 139 140 // Priority goes to the app heap, if we can find one. 141 AhatHeap appHeap = snapshot.getHeap("app"); 142 if (appHeap != null) { 143 comparators.add(new SiteByHeapSize(appHeap)); 144 } 145 146 // Next is by total size. 147 comparators.add(SITE_BY_TOTAL_SIZE); 148 return new WithPriority<Site>(comparators); 149 } 150 151 /** 152 * Compare Site.ObjectsInfo by their size. 153 * Different object infos with the same total retained size are considered 154 * equal for the purposes of comparison. 155 * This sorts object infos from larger retained size to smaller size. 156 */ 157 public static final Comparator<Site.ObjectsInfo> OBJECTS_INFO_BY_SIZE 158 = new Comparator<Site.ObjectsInfo>() { 159 @Override 160 public int compare(Site.ObjectsInfo a, Site.ObjectsInfo b) { 161 return Long.compare(b.numBytes, a.numBytes); 162 } 163 }; 164 165 /** 166 * Compare Site.ObjectsInfo by heap name. 167 * Different object infos with the same heap name are considered equal for 168 * the purposes of comparison. 169 */ 170 public static final Comparator<Site.ObjectsInfo> OBJECTS_INFO_BY_HEAP_NAME 171 = new Comparator<Site.ObjectsInfo>() { 172 @Override 173 public int compare(Site.ObjectsInfo a, Site.ObjectsInfo b) { 174 return a.heap.getName().compareTo(b.heap.getName()); 175 } 176 }; 177 178 /** 179 * Compare Site.ObjectsInfo by class name. 180 * Different object infos with the same class name are considered equal for 181 * the purposes of comparison. 182 */ 183 public static final Comparator<Site.ObjectsInfo> OBJECTS_INFO_BY_CLASS_NAME 184 = new Comparator<Site.ObjectsInfo>() { 185 @Override 186 public int compare(Site.ObjectsInfo a, Site.ObjectsInfo b) { 187 String aName = a.getClassName(); 188 String bName = b.getClassName(); 189 return aName.compareTo(bName); 190 } 191 }; 192 } 193 194