ss: make node cache static
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 13 Apr 2016 22:01:04 +0000 (18:01 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Tue, 3 May 2016 19:49:42 +0000 (15:49 -0400)
The state system is being used in many places now. A kernel trace
can have over 10 state systems running simultaneously. Therefore,
the caches have been taking more and more space. A summary reading
of heap dumps showed that for a kernel trace now, 512 mb is needed
for these caches. This will not scale.

This patch makes ONE cache for all of trace compass. There is a tiny
heuristic, each location is offsetted by the object's hashcode. This
is to avoid too much cache thrashing du to temporal co-locality.

The seek times in trace compass (going from one place to another)
are accelerated by a factor of 3 and are noticeable on an i7 with
16gb of ram and an ssd.

Moreover, this patch improves scalability, by making trace compass
not run out of memory after opening 5 kernel traces simultaneously.

Change-Id: I9c6509b0e32c04025fc66c0fdda3d31e971584b4
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/70600
Reviewed-by: Hudson CI
Reviewed-by: Alexandre Montplaisir <alexmonthy@efficios.com>
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/backend/historytree/HT_IO.java

index 857a3058f3013db392e37307d6b6c49664dee26c..66cd434ec58d7baa488e93b15bc8b4a7a5beae8c 100644 (file)
@@ -20,6 +20,7 @@ import java.nio.channels.ClosedChannelException;
 import java.nio.channels.FileChannel;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.tracecompass.internal.statesystem.core.Activator;
 
 /**
@@ -35,6 +36,26 @@ import org.eclipse.tracecompass.internal.statesystem.core.Activator;
  *
  */
 class HT_IO {
+
+    @NonNullByDefault
+    private static final class CacheElement {
+        private final HTNode value;
+        private final HT_IO key;
+
+        public CacheElement(HT_IO ss, HTNode node) {
+            key = ss;
+            value = node;
+        }
+
+        public HT_IO getKey() {
+            return key;
+        }
+
+        public HTNode getValue() {
+            return value;
+        }
+    }
+
     /* Configuration of the History Tree */
     private final HTConfig fConfig;
 
@@ -50,7 +71,7 @@ class HT_IO {
      */
     private static final int CACHE_SIZE = 256;
     private static final int CACHE_MASK = CACHE_SIZE - 1;
-    private final HTNode fNodeCache[] = new HTNode[CACHE_SIZE];
+    private static final CacheElement NODE_CACHE[] = new CacheElement[CACHE_SIZE];
 
     /**
      * Standard constructor
@@ -106,25 +127,28 @@ class HT_IO {
      */
     public synchronized @NonNull HTNode readNode(int seqNumber) throws ClosedChannelException {
         /* Do a cache lookup */
-        int offset = seqNumber & CACHE_MASK;
-        HTNode readNode = fNodeCache[offset];
-        if (readNode != null && readNode.getSequenceNumber() == seqNumber) {
-            return readNode;
+        int offset = (seqNumber + hashCode()) & CACHE_MASK;
+        CacheElement cachedNode = NODE_CACHE[offset];
+
+        if (cachedNode != null && cachedNode.getKey() == this && cachedNode.getValue().getSequenceNumber() == seqNumber) {
+            return cachedNode.getValue();
         }
 
         /* Lookup on disk */
         try {
             seekFCToNodePos(fFileChannelIn, seqNumber);
-            readNode = HTNode.readNode(fConfig, fFileChannelIn);
+            HTNode readNode = HTNode.readNode(fConfig, fFileChannelIn);
 
             /* Put the node in the cache. */
-            fNodeCache[offset] = readNode;
+            NODE_CACHE[offset] = new CacheElement(this, readNode);
             return readNode;
 
         } catch (ClosedChannelException e) {
             throw e;
         } catch (IOException e) {
-            /* Other types of IOExceptions shouldn't happen at this point though */
+            /*
+             * Other types of IOExceptions shouldn't happen at this point though
+             */
             Activator.getDefault().logError(e.getMessage(), e);
             throw new IllegalStateException();
         }
@@ -134,8 +158,8 @@ class HT_IO {
         try {
             /* Insert the node into the cache. */
             int seqNumber = node.getSequenceNumber();
-            int offset = seqNumber & CACHE_MASK;
-            fNodeCache[offset] = node;
+            int offset = (seqNumber + hashCode()) & CACHE_MASK;
+            NODE_CACHE[offset] = new CacheElement(this, node);
 
             /* Position ourselves at the start of the node and write it */
             seekFCToNodePos(fFileChannelOut, seqNumber);
This page took 0.027134 seconds and 5 git commands to generate.