1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Collection;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.HashMap;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.TreeMap;
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Statistics about the contents of a file.
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class Statistics {
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} data about each type of item */
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final HashMap<String, Data> dataMap;
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Statistics() {
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        dataMap = new HashMap<String, Data>(50);
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Adds the given item to the statistics.
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param item {@code non-null;} the item to add
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void add(Item item) {
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        String typeName = item.typeName();
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        Data data = dataMap.get(typeName);
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (data == null) {
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            dataMap.put(typeName, new Data(item, typeName));
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            data.add(item);
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Adds the given list of items to the statistics.
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param list {@code non-null;} the list of items to add
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void addAll(Section list) {
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        Collection<? extends Item> items = list.items();
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (Item item : items) {
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            add(item);
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Writes the statistics as an annotation.
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} where to write to
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final void writeAnnotation(AnnotatedOutput out) {
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (dataMap.size() == 0) {
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return;
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.annotate(0, "\nstatistics:\n");
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        TreeMap<String, Data> sortedData = new TreeMap<String, Data>();
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (Data data : dataMap.values()) {
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sortedData.put(data.name, data);
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (Data data : sortedData.values()) {
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            data.writeAnnotation(out);
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toHuman() {
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringBuilder sb = new StringBuilder();
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append("Statistics:\n");
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        TreeMap<String, Data> sortedData = new TreeMap<String, Data>();
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (Data data : dataMap.values()) {
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sortedData.put(data.name, data);
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (Data data : sortedData.values()) {
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(data.toHuman());
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sb.toString();
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Statistical data about a particular class.
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static class Data {
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code non-null;} name to use as a label */
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private final String name;
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} number of instances */
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private int count;
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} total size of instances in bytes */
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private int totalSize;
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} largest size of any individual item */
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private int largestSize;
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} smallest size of any individual item */
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private int smallestSize;
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Constructs an instance for the given item.
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param item {@code non-null;} item in question
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param name {@code non-null;} type name to use
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public Data(Item item, String name) {
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int size = item.writeSize();
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.name = name;
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.count = 1;
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.totalSize = size;
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.largestSize = size;
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.smallestSize = size;
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Incorporates a new item. This assumes the type name matches.
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param item {@code non-null;} item to incorporate
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void add(Item item) {
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int size = item.writeSize();
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            count++;
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            totalSize += size;
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (size > largestSize) {
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                largestSize = size;
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (size < smallestSize) {
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                smallestSize = size;
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Writes this instance as an annotation.
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param out {@code non-null;} where to write to
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void writeAnnotation(AnnotatedOutput out) {
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate(toHuman());
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Generates a human-readable string for this data item.
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return string for human consumption.
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public String toHuman() {
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            StringBuilder sb = new StringBuilder();
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append("  " + name + ": " +
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                         count + " item" + (count == 1 ? "" : "s") + "; " +
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                         totalSize + " bytes total\n");
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (smallestSize == largestSize) {
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append("    " + smallestSize + " bytes/item\n");
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            } else {
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                int average = totalSize / count;
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append("    " + smallestSize + ".." + largestSize +
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                             " bytes/item; average " + average + "\n");
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return sb.toString();
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
196