diff graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/ShapeProfiler.java @ 18408:2c3666f44855

Truffle: initial commit of object API implementation
author Andreas Woess <andreas.woess@jku.at>
date Tue, 18 Nov 2014 23:19:43 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/ShapeProfiler.java	Tue Nov 18 23:19:43 2014 +0100
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.debug;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+
+public class ShapeProfiler {
+    private static final String LINE_SEPARATOR = "***********************************************";
+    private static final String BULLET = "* ";
+    private static final String TOKEN_SEPARATOR = "\t";
+    private final ConcurrentLinkedQueue<DynamicObject> queue;
+
+    public ShapeProfiler() {
+        queue = new ConcurrentLinkedQueue<>();
+    }
+
+    public void track(DynamicObject obj) {
+        queue.add(obj);
+    }
+
+    public void dump(PrintWriter out) {
+        ShapeStats globalStats = new ShapeStats("Cumulative results for all shapes");
+        for (DynamicObject obj : queue) {
+            Shape shape = obj.getShape();
+            globalStats.profile(shape);
+        }
+
+        globalStats.dump(out);
+    }
+
+    public void dump(PrintWriter out, int topResults) {
+        if (topResults > 0) {
+            IdentityHashMap<Shape, ShapeStats> shapeMap = new IdentityHashMap<>();
+
+            for (DynamicObject obj : queue) {
+                Shape shape = obj.getShape();
+                ShapeStats stats = shapeMap.get(shape);
+                if (stats == null) {
+                    shapeMap.put(shape, stats = new ShapeStats(createLabel(shape)));
+                }
+                stats.profile(shape);
+            }
+
+            List<ShapeStats> allStats = new ArrayList<>(shapeMap.values());
+            Collections.sort(allStats, new Comparator<ShapeStats>() {
+                public int compare(ShapeStats a, ShapeStats b) {
+                    return Long.compare(b.jsObjects, a.jsObjects);
+                }
+            });
+
+            ShapeStats avgStats = new ShapeStats("Cumulative results for top " + topResults + " shapes");
+            for (int i = 0; i < topResults; i++) {
+                ShapeStats stats = allStats.get(i);
+                stats.setLabel("Shape " + (i + 1) + ": " + stats.getLabel());
+                stats.dump(out);
+                avgStats.add(stats);
+            }
+            avgStats.dump(out);
+        }
+        // Dump also cumulative results.
+        dump(out);
+    }
+
+    private static String createLabel(Shape shape) {
+        String label = shape.toString();
+        return label.substring(label.indexOf('{') + 1, label.lastIndexOf('}'));
+    }
+
+    private static class ShapeStats {
+        private String label;
+        private long jsObjects;
+        private long oac;
+        private long oas;
+        private long ofs;
+        private long pac;
+        private long pas;
+        private long pfs;
+
+        public ShapeStats(String label) {
+            this.label = label;
+        }
+
+        public String getLabel() {
+            return label;
+        }
+
+        public void setLabel(String label) {
+            this.label = label;
+        }
+
+        public void profile(Shape shape) {
+            jsObjects++;
+            oac += shape.getObjectArrayCapacity();
+            oas += shape.getObjectArraySize();
+            ofs += shape.getObjectFieldSize();
+            pac += shape.getPrimitiveArrayCapacity();
+            pas += shape.getPrimitiveArraySize();
+            pfs += shape.getPrimitiveFieldSize();
+        }
+
+        public void add(ShapeStats stats) {
+            jsObjects += stats.jsObjects;
+            oac += stats.oac;
+            oas += stats.oas;
+            ofs += stats.ofs;
+            oac += stats.oac;
+            oas += stats.oas;
+            ofs += stats.ofs;
+        }
+
+        public void dump(PrintWriter out) {
+            DecimalFormat format = new DecimalFormat("###.####");
+            out.println(LINE_SEPARATOR);
+            out.println(BULLET + label);
+            out.println(LINE_SEPARATOR);
+            out.println(BULLET + "Allocated objects:\t" + jsObjects);
+            out.println(BULLET + "Total object array capacity:\t" + oac);
+            out.println(BULLET + "Total object array size:\t" + oas);
+            out.println(BULLET + "Total object field size:\t" + ofs);
+            out.println(BULLET + "Average object array capacity:\t" + avgOAC(format));
+            out.println(BULLET + "Average object array size:\t" + avgOAS(format));
+            out.println(BULLET + "Average object field size:\t" + avgOFS(format));
+            out.println(LINE_SEPARATOR);
+            out.println(BULLET + "Total primitive array capacity:\t" + pac);
+            out.println(BULLET + "Total primitive array size:\t" + pas);
+            out.println(BULLET + "Total primitive field size:\t" + pfs);
+            out.println(BULLET + "Average primitive array capacity:\t" + avgPAC(format));
+            out.println(BULLET + "Average primitive array size:\t" + avgPAS(format));
+            out.println(BULLET + "Average primitive field size:\t" + avgPFS(format));
+            out.println(LINE_SEPARATOR);
+            out.println(BULLET + toString());
+            out.println(LINE_SEPARATOR + "\n");
+            out.flush();
+        }
+
+        @Override
+        public String toString() {
+            DecimalFormat format = new DecimalFormat("###.####");
+            // @formatter:off
+            return "{" + label + "}" + TOKEN_SEPARATOR
+                   + jsObjects + TOKEN_SEPARATOR
+                   + avgOAC(format) + TOKEN_SEPARATOR
+                   + avgOAS(format) + TOKEN_SEPARATOR
+                   + avgOFS(format) + TOKEN_SEPARATOR
+                   + avgPAC(format) + TOKEN_SEPARATOR
+                   + avgPAS(format) + TOKEN_SEPARATOR
+                   + avgPFS(format);
+            // @formatter:on
+        }
+
+        private String avgOAC(DecimalFormat format) {
+            return format.format((double) oac / jsObjects);
+        }
+
+        private String avgOAS(DecimalFormat format) {
+            return format.format((double) oas / jsObjects);
+        }
+
+        private String avgOFS(DecimalFormat format) {
+            return format.format((double) ofs / jsObjects);
+        }
+
+        private String avgPAC(DecimalFormat format) {
+            return format.format((double) pac / jsObjects);
+        }
+
+        private String avgPAS(DecimalFormat format) {
+            return format.format((double) pas / jsObjects);
+        }
+
+        private String avgPFS(DecimalFormat format) {
+            return format.format((double) pfs / jsObjects);
+        }
+    }
+
+    public static ShapeProfiler getInstance() {
+        return shapeProf;
+    }
+
+    private static final ShapeProfiler shapeProf;
+    static {
+        if (ObjectStorageOptions.Profile) {
+            shapeProf = new ShapeProfiler();
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                @Override
+                public void run() {
+                    getInstance().dump(new PrintWriter(System.out), ObjectStorageOptions.ProfileTopResults);
+                }
+            });
+        } else {
+            shapeProf = null;
+        }
+    }
+}