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
17package com.android.ahat;
18
19import com.android.tools.perflib.heap.Instance;
20import com.android.tools.perflib.heap.Heap;
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.Comparator;
24import java.util.List;
25import 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 */
35class 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