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