comparison truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/ShapeProfiler.java @ 21951:9c8c0937da41

Moving all sources into truffle subdirectory
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 17 Jun 2015 10:58:08 +0200
parents graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/ShapeProfiler.java@2c3666f44855
children 5bc7f7b867ab
comparison
equal deleted inserted replaced
21950:2a5011c7e641 21951:9c8c0937da41
1 /*
2 * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.truffle.object.debug;
24
25 import java.io.*;
26 import java.text.*;
27 import java.util.*;
28 import java.util.concurrent.*;
29
30 import com.oracle.truffle.api.object.*;
31 import com.oracle.truffle.object.*;
32
33 public class ShapeProfiler {
34 private static final String LINE_SEPARATOR = "***********************************************";
35 private static final String BULLET = "* ";
36 private static final String TOKEN_SEPARATOR = "\t";
37 private final ConcurrentLinkedQueue<DynamicObject> queue;
38
39 public ShapeProfiler() {
40 queue = new ConcurrentLinkedQueue<>();
41 }
42
43 public void track(DynamicObject obj) {
44 queue.add(obj);
45 }
46
47 public void dump(PrintWriter out) {
48 ShapeStats globalStats = new ShapeStats("Cumulative results for all shapes");
49 for (DynamicObject obj : queue) {
50 Shape shape = obj.getShape();
51 globalStats.profile(shape);
52 }
53
54 globalStats.dump(out);
55 }
56
57 public void dump(PrintWriter out, int topResults) {
58 if (topResults > 0) {
59 IdentityHashMap<Shape, ShapeStats> shapeMap = new IdentityHashMap<>();
60
61 for (DynamicObject obj : queue) {
62 Shape shape = obj.getShape();
63 ShapeStats stats = shapeMap.get(shape);
64 if (stats == null) {
65 shapeMap.put(shape, stats = new ShapeStats(createLabel(shape)));
66 }
67 stats.profile(shape);
68 }
69
70 List<ShapeStats> allStats = new ArrayList<>(shapeMap.values());
71 Collections.sort(allStats, new Comparator<ShapeStats>() {
72 public int compare(ShapeStats a, ShapeStats b) {
73 return Long.compare(b.jsObjects, a.jsObjects);
74 }
75 });
76
77 ShapeStats avgStats = new ShapeStats("Cumulative results for top " + topResults + " shapes");
78 for (int i = 0; i < topResults; i++) {
79 ShapeStats stats = allStats.get(i);
80 stats.setLabel("Shape " + (i + 1) + ": " + stats.getLabel());
81 stats.dump(out);
82 avgStats.add(stats);
83 }
84 avgStats.dump(out);
85 }
86 // Dump also cumulative results.
87 dump(out);
88 }
89
90 private static String createLabel(Shape shape) {
91 String label = shape.toString();
92 return label.substring(label.indexOf('{') + 1, label.lastIndexOf('}'));
93 }
94
95 private static class ShapeStats {
96 private String label;
97 private long jsObjects;
98 private long oac;
99 private long oas;
100 private long ofs;
101 private long pac;
102 private long pas;
103 private long pfs;
104
105 public ShapeStats(String label) {
106 this.label = label;
107 }
108
109 public String getLabel() {
110 return label;
111 }
112
113 public void setLabel(String label) {
114 this.label = label;
115 }
116
117 public void profile(Shape shape) {
118 jsObjects++;
119 oac += shape.getObjectArrayCapacity();
120 oas += shape.getObjectArraySize();
121 ofs += shape.getObjectFieldSize();
122 pac += shape.getPrimitiveArrayCapacity();
123 pas += shape.getPrimitiveArraySize();
124 pfs += shape.getPrimitiveFieldSize();
125 }
126
127 public void add(ShapeStats stats) {
128 jsObjects += stats.jsObjects;
129 oac += stats.oac;
130 oas += stats.oas;
131 ofs += stats.ofs;
132 oac += stats.oac;
133 oas += stats.oas;
134 ofs += stats.ofs;
135 }
136
137 public void dump(PrintWriter out) {
138 DecimalFormat format = new DecimalFormat("###.####");
139 out.println(LINE_SEPARATOR);
140 out.println(BULLET + label);
141 out.println(LINE_SEPARATOR);
142 out.println(BULLET + "Allocated objects:\t" + jsObjects);
143 out.println(BULLET + "Total object array capacity:\t" + oac);
144 out.println(BULLET + "Total object array size:\t" + oas);
145 out.println(BULLET + "Total object field size:\t" + ofs);
146 out.println(BULLET + "Average object array capacity:\t" + avgOAC(format));
147 out.println(BULLET + "Average object array size:\t" + avgOAS(format));
148 out.println(BULLET + "Average object field size:\t" + avgOFS(format));
149 out.println(LINE_SEPARATOR);
150 out.println(BULLET + "Total primitive array capacity:\t" + pac);
151 out.println(BULLET + "Total primitive array size:\t" + pas);
152 out.println(BULLET + "Total primitive field size:\t" + pfs);
153 out.println(BULLET + "Average primitive array capacity:\t" + avgPAC(format));
154 out.println(BULLET + "Average primitive array size:\t" + avgPAS(format));
155 out.println(BULLET + "Average primitive field size:\t" + avgPFS(format));
156 out.println(LINE_SEPARATOR);
157 out.println(BULLET + toString());
158 out.println(LINE_SEPARATOR + "\n");
159 out.flush();
160 }
161
162 @Override
163 public String toString() {
164 DecimalFormat format = new DecimalFormat("###.####");
165 // @formatter:off
166 return "{" + label + "}" + TOKEN_SEPARATOR
167 + jsObjects + TOKEN_SEPARATOR
168 + avgOAC(format) + TOKEN_SEPARATOR
169 + avgOAS(format) + TOKEN_SEPARATOR
170 + avgOFS(format) + TOKEN_SEPARATOR
171 + avgPAC(format) + TOKEN_SEPARATOR
172 + avgPAS(format) + TOKEN_SEPARATOR
173 + avgPFS(format);
174 // @formatter:on
175 }
176
177 private String avgOAC(DecimalFormat format) {
178 return format.format((double) oac / jsObjects);
179 }
180
181 private String avgOAS(DecimalFormat format) {
182 return format.format((double) oas / jsObjects);
183 }
184
185 private String avgOFS(DecimalFormat format) {
186 return format.format((double) ofs / jsObjects);
187 }
188
189 private String avgPAC(DecimalFormat format) {
190 return format.format((double) pac / jsObjects);
191 }
192
193 private String avgPAS(DecimalFormat format) {
194 return format.format((double) pas / jsObjects);
195 }
196
197 private String avgPFS(DecimalFormat format) {
198 return format.format((double) pfs / jsObjects);
199 }
200 }
201
202 public static ShapeProfiler getInstance() {
203 return shapeProf;
204 }
205
206 private static final ShapeProfiler shapeProf;
207 static {
208 if (ObjectStorageOptions.Profile) {
209 shapeProf = new ShapeProfiler();
210 Runtime.getRuntime().addShutdownHook(new Thread() {
211 @Override
212 public void run() {
213 getInstance().dump(new PrintWriter(System.out), ObjectStorageOptions.ProfileTopResults);
214 }
215 });
216 } else {
217 shapeProf = null;
218 }
219 }
220 }