changeset 13981:a1b71ebfdf5f

reduce IGV memory usage, intern strings, eliminate some LinkedHashMaps, cache InputEdges
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Wed, 19 Feb 2014 14:50:49 -0800
parents 68ae6fae9d2e
children b167b1838029 aaba5b41c953
files src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java
diffstat 4 files changed, 59 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Wed Feb 19 14:41:51 2014 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java	Wed Feb 19 14:50:49 2014 -0800
@@ -24,6 +24,8 @@
 package com.sun.hotspot.igv.data;
 
 import java.util.Comparator;
+import java.util.WeakHashMap;
+import java.lang.ref.WeakReference;
 
 /**
  *
@@ -32,7 +34,7 @@
 public class InputEdge {
 
     public enum State {
-
+        IMMUTABLE,
         SAME,
         NEW,
         DELETED
@@ -61,12 +63,12 @@
             }
     };
 
-    private char toIndex;
-    private char fromIndex;
-    private int from;
-    private int to;
+    private final char toIndex;
+    private final char fromIndex;
+    private final int from;
+    private final int to;
+    private final String label;
     private State state;
-    private String label;
 
     public InputEdge(char toIndex, int from, int to) {
         this((char) 0, toIndex, from, to, null);
@@ -85,11 +87,38 @@
         this.label = label;
     }
 
+    static WeakHashMap<InputEdge, WeakReference<InputEdge>> immutableCache = new WeakHashMap<>();
+
+    public static synchronized InputEdge createImmutable(char fromIndex, char toIndex, int from, int to, String label) {
+        InputEdge edge = new InputEdge(fromIndex, toIndex, from, to, label, State.IMMUTABLE);
+        WeakReference<InputEdge> result = immutableCache.get(edge);
+        if (result != null) {
+            InputEdge edge2 = result.get();
+            if (edge2 != null) {
+                return edge2;
+            }
+        }
+        immutableCache.put(edge, new WeakReference<>(edge));
+        return edge;
+    }
+
+    public InputEdge(char fromIndex, char toIndex, int from, int to, String label, State state) {
+        this.toIndex = toIndex;
+        this.fromIndex = fromIndex;
+        this.from = from;
+        this.to = to;
+        this.state = state;
+        this.label = label;
+    }
+
     public State getState() {
         return state;
     }
 
     public void setState(State x) {
+        if (state == State.IMMUTABLE) {
+            throw new InternalError("Can't change immutable instances");
+        }
         this.state = x;
     }
 
@@ -123,7 +152,12 @@
             return false;
         }
         InputEdge conn2 = (InputEdge) o;
-        return conn2.fromIndex == fromIndex && conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
+        boolean result = conn2.fromIndex == fromIndex && conn2.toIndex == toIndex && conn2.from == from && conn2.to == to;
+        if (result && (state == State.IMMUTABLE || conn2.state == State.IMMUTABLE)) {
+            // Immutable instances must be exactly the same
+            return conn2.label == label && conn2.state == state;
+        }
+        return result;
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Wed Feb 19 14:41:51 2014 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Wed Feb 19 14:50:49 2014 -0800
@@ -32,19 +32,19 @@
 public class InputGraph extends Properties.Entity implements FolderElement {
 
     private Map<Integer, InputNode> nodes;
-    private Set<InputEdge> edges;
+    private List<InputEdge> edges;
     private Folder parent;
     private Group parentGroup;
     private Map<String, InputBlock> blocks;
-    private Set<InputBlockEdge> blockEdges;
+    private List<InputBlockEdge> blockEdges;
     private Map<Integer, InputBlock> nodeToBlock;
 
     public InputGraph(String name) {
         setName(name);
         nodes = new LinkedHashMap<>();
-        edges = new LinkedHashSet<>();
+        edges = new ArrayList<>();
         blocks = new LinkedHashMap<>();
-        blockEdges = new LinkedHashSet<>();
+        blockEdges = new ArrayList<>();
         nodeToBlock = new LinkedHashMap<>();
     }
     
@@ -234,7 +234,7 @@
     }
 
     public Collection<InputEdge> getEdges() {
-        return Collections.unmodifiableSet(edges);
+        return Collections.unmodifiableList(edges);
     }
 
     public void removeEdge(InputEdge c) {
@@ -283,7 +283,7 @@
     }
 
     public Collection<InputBlockEdge> getBlockEdges() {
-        return Collections.unmodifiableSet(blockEdges);
+        return Collections.unmodifiableList(blockEdges);
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Wed Feb 19 14:41:51 2014 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Properties.java	Wed Feb 19 14:50:49 2014 -0800
@@ -320,6 +320,9 @@
     }
 
     public void setProperty(String name, String value) {
+        setPropertyInternal(name.intern(), value.intern());
+    }
+    private void setPropertyInternal(String name, String value) {
 
         for (int i = 0; i < map.length; i += 2) {
             if (map[i] != null && map[i].equals(name)) {
@@ -353,7 +356,8 @@
 
     public void add(Properties properties) {
         for (Property p : properties) {
-            setProperty(p.getName(), p.getValue());
+            // Already interned
+            setPropertyInternal(p.getName(), p.getValue());
         }
     }
 
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Wed Feb 19 14:41:51 2014 -0800
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Wed Feb 19 14:50:49 2014 -0800
@@ -327,7 +327,7 @@
         char[] chars = new char[len];
         buffer.asCharBuffer().get(chars);
         buffer.position(buffer.position() + len * 2);
-        return new String(chars);
+        return new String(chars).intern();
     }
 
     private byte[] readBytes() throws IOException {
@@ -355,7 +355,7 @@
             }
         }
         sb.append(']');
-        return sb.toString();
+        return sb.toString().intern();
     }
     
     private String readDoublesToString() throws IOException {
@@ -372,7 +372,7 @@
             }
         }
         sb.append(']');
-        return sb.toString();
+        return sb.toString().intern();
     }
     
     private String readPoolObjectsToString() throws IOException {
@@ -388,7 +388,7 @@
             }
         }
         sb.append(']');
-        return sb.toString();
+        return sb.toString().intern();
     }
     
     private <T> T readPoolObject(Class<T> klass) throws IOException {
@@ -780,7 +780,7 @@
         for (Edge e : edges) {
             char fromIndex = e.input ? 1 : e.num;
             char toIndex = e.input ? e.num : 0;
-            graph.addEdge(new InputEdge(fromIndex, toIndex, e.from, e.to, e.label));
+            graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label));
         }
     }
     
@@ -837,7 +837,7 @@
             m.appendReplacement(sb, result);
         }
         m.appendTail(sb);
-        return sb.toString();
+        return sb.toString().intern();
     }
     
     private static class Edge {
@@ -852,7 +852,7 @@
         public Edge(int from, int to, char num, String label, boolean input) {
             this.from = from;
             this.to = to;
-            this.label = label;
+            this.label = label != null ? label.intern() : label;
             this.num = num;
             this.input = input;
         }