Updated Branches:
  refs/heads/trunk 67f5d6f1c -> 7a6fbc1b2

replace measureDeep in key cache with custom calculation
patch by Vijay; reviewed by Jonathan Ellis for CASSANDRA-4860


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/da93a1cf
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/da93a1cf
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/da93a1cf

Branch: refs/heads/trunk
Commit: da93a1cfe483a1522b2c149d287279a74e43a8a9
Parents: 40e7aba
Author: Vijay Parthasarathy <vijay2...@gmail.com>
Authored: Tue Apr 16 18:24:11 2013 -0700
Committer: Vijay Parthasarathy <vijay2...@gmail.com>
Committed: Tue Apr 16 18:24:11 2013 -0700

----------------------------------------------------------------------
 src/java/org/apache/cassandra/cache/CacheKey.java  |    2 +-
 .../cassandra/cache/ConcurrentLinkedHashCache.java |   11 +-
 .../apache/cassandra/cache/IMeasurableMemory.java  |    6 +
 .../org/apache/cassandra/cache/IRowCacheEntry.java |    2 +-
 .../org/apache/cassandra/cache/KeyCacheKey.java    |    7 +
 .../org/apache/cassandra/cache/RowCacheKey.java    |    7 +
 .../apache/cassandra/cache/RowCacheSentinel.java   |    8 +
 src/java/org/apache/cassandra/db/ColumnFamily.java |    5 +
 src/java/org/apache/cassandra/db/DeletionInfo.java |    9 +
 src/java/org/apache/cassandra/db/DeletionTime.java |    7 +
 .../org/apache/cassandra/db/RowIndexEntry.java     |   19 ++-
 .../apache/cassandra/io/sstable/IndexHelper.java   |    6 +
 .../org/apache/cassandra/utils/ObjectSizes.java    |  204 +++++++++++++++
 .../apache/cassandra/cache/CacheProviderTest.java  |   33 ++-
 .../org/apache/cassandra/cache/ObjectSizeTest.java |   83 ++++++
 15 files changed, 390 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/cache/CacheKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cache/CacheKey.java 
b/src/java/org/apache/cassandra/cache/CacheKey.java
index 5743dfc..aa9f5f6 100644
--- a/src/java/org/apache/cassandra/cache/CacheKey.java
+++ b/src/java/org/apache/cassandra/cache/CacheKey.java
@@ -19,7 +19,7 @@ package org.apache.cassandra.cache;
 
 import org.apache.cassandra.utils.Pair;
 
-public interface CacheKey
+public interface CacheKey extends IMeasurableMemory
 {
     /**
      * @return The keyspace and ColumnFamily names to which this key belongs

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java 
b/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java
index 0f992d3..30cb958 100644
--- a/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java
+++ b/src/java/org/apache/cassandra/cache/ConcurrentLinkedHashCache.java
@@ -19,18 +19,15 @@ package org.apache.cassandra.cache;
 
 import java.util.Set;
 
-import org.github.jamm.MemoryMeter;
-
 import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
 import com.googlecode.concurrentlinkedhashmap.EntryWeigher;
 
 /** Wrapper so CLHM can implement ICache interface.
  *  (this is what you get for making library classes final.) */
-public class ConcurrentLinkedHashCache<K, V> implements ICache<K, V>
+public class ConcurrentLinkedHashCache<K extends IMeasurableMemory, V extends 
IMeasurableMemory> implements ICache<K, V>
 {
     public static final int DEFAULT_CONCURENCY_LEVEL = 64;
     private final ConcurrentLinkedHashMap<K, V> map;
-    private static final MemoryMeter meter = new 
MemoryMeter().omitSharedBufferOverhead();
 
     private ConcurrentLinkedHashCache(ConcurrentLinkedHashMap<K, V> map)
     {
@@ -40,7 +37,7 @@ public class ConcurrentLinkedHashCache<K, V> implements 
ICache<K, V>
     /**
      * Initialize a cache with initial capacity with weightedCapacity
      */
-    public static <K, V> ConcurrentLinkedHashCache<K, V> create(long 
weightedCapacity, EntryWeigher<K, V> entryWeiger)
+    public static <K extends IMeasurableMemory, V extends IMeasurableMemory> 
ConcurrentLinkedHashCache<K, V> create(long weightedCapacity, EntryWeigher<K, 
V> entryWeiger)
     {
         ConcurrentLinkedHashMap<K, V> map = new 
ConcurrentLinkedHashMap.Builder<K, V>()
                                             .weigher(entryWeiger)
@@ -51,13 +48,13 @@ public class ConcurrentLinkedHashCache<K, V> implements 
ICache<K, V>
         return new ConcurrentLinkedHashCache<K, V>(map);
     }
 
-    public static <K, V> ConcurrentLinkedHashCache<K, V> create(long 
weightedCapacity)
+    public static <K extends IMeasurableMemory, V extends IMeasurableMemory> 
ConcurrentLinkedHashCache<K, V> create(long weightedCapacity)
     {
         return create(weightedCapacity, new EntryWeigher<K, V>()
         {
             public int weightOf(K key, V value)
             {
-                long size = meter.measureDeep(key) + meter.measureDeep(value);
+                long size = key.memorySize() + value.memorySize();
                 assert size < Integer.MAX_VALUE : "Serialized size cannot be 
more than 2GB/Integer.MAX_VALUE";
                 return (int) size;
             }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/cache/IMeasurableMemory.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cache/IMeasurableMemory.java 
b/src/java/org/apache/cassandra/cache/IMeasurableMemory.java
new file mode 100644
index 0000000..6b5f00e
--- /dev/null
+++ b/src/java/org/apache/cassandra/cache/IMeasurableMemory.java
@@ -0,0 +1,6 @@
+package org.apache.cassandra.cache;
+
+public interface IMeasurableMemory
+{
+    public long memorySize();
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/cache/IRowCacheEntry.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cache/IRowCacheEntry.java 
b/src/java/org/apache/cassandra/cache/IRowCacheEntry.java
index 2c9dffd..0a4ac02 100644
--- a/src/java/org/apache/cassandra/cache/IRowCacheEntry.java
+++ b/src/java/org/apache/cassandra/cache/IRowCacheEntry.java
@@ -17,6 +17,6 @@
  */
 package org.apache.cassandra.cache;
 
-public interface IRowCacheEntry
+public interface IRowCacheEntry extends IMeasurableMemory
 {
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/cache/KeyCacheKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cache/KeyCacheKey.java 
b/src/java/org/apache/cassandra/cache/KeyCacheKey.java
index 016cccb..9741c7f 100644
--- a/src/java/org/apache/cassandra/cache/KeyCacheKey.java
+++ b/src/java/org/apache/cassandra/cache/KeyCacheKey.java
@@ -22,6 +22,7 @@ import java.util.Arrays;
 
 import org.apache.cassandra.io.sstable.Descriptor;
 import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.ObjectSizes;
 import org.apache.cassandra.utils.Pair;
 
 public class KeyCacheKey implements CacheKey
@@ -49,6 +50,12 @@ public class KeyCacheKey implements CacheKey
         return String.format("KeyCacheKey(%s, %s)", desc, 
ByteBufferUtil.bytesToHex(ByteBuffer.wrap(key)));
     }
 
+    public long memorySize()
+    {
+        long fields = ObjectSizes.getReferenceSize() + 
ObjectSizes.getSizeWithRef(key);
+        return ObjectSizes.getFieldSize(fields);
+    }
+
     @Override
     public boolean equals(Object o)
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/cache/RowCacheKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cache/RowCacheKey.java 
b/src/java/org/apache/cassandra/cache/RowCacheKey.java
index f6c743f..d7dab35 100644
--- a/src/java/org/apache/cassandra/cache/RowCacheKey.java
+++ b/src/java/org/apache/cassandra/cache/RowCacheKey.java
@@ -25,6 +25,7 @@ import org.apache.cassandra.config.Schema;
 import org.apache.cassandra.db.DecoratedKey;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.ObjectSizes;
 import org.apache.cassandra.utils.Pair;
 
 public class RowCacheKey implements CacheKey, Comparable<RowCacheKey>
@@ -49,6 +50,12 @@ public class RowCacheKey implements CacheKey, 
Comparable<RowCacheKey>
         return Schema.instance.getCF(cfId);
     }
 
+    public long memorySize()
+    {
+        long fields = ObjectSizes.getReferenceSize() + 
ObjectSizes.getSizeWithRef(key);
+        return ObjectSizes.getFieldSize(fields);
+    }
+
     @Override
     public boolean equals(Object o)
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/cache/RowCacheSentinel.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cache/RowCacheSentinel.java 
b/src/java/org/apache/cassandra/cache/RowCacheSentinel.java
index 83c49d4..d7da6ce 100644
--- a/src/java/org/apache/cassandra/cache/RowCacheSentinel.java
+++ b/src/java/org/apache/cassandra/cache/RowCacheSentinel.java
@@ -19,6 +19,8 @@ package org.apache.cassandra.cache;
 
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.cassandra.utils.ObjectSizes;
+
 import com.google.common.base.Objects;
 
 /**
@@ -54,4 +56,10 @@ public class RowCacheSentinel implements IRowCacheEntry
     {
         return Objects.hashCode(sentinelId);
     }
+
+    public long memorySize()
+    {
+        // Only long reference.
+        return ObjectSizes.getFieldSize(8);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/db/ColumnFamily.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ColumnFamily.java 
b/src/java/org/apache/cassandra/db/ColumnFamily.java
index 6f19fc4..6164900 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamily.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamily.java
@@ -277,6 +277,11 @@ public class ColumnFamily extends AbstractColumnContainer 
implements IRowCacheEn
         return size;
     }
 
+    public long memorySize()
+    {
+        return ObjectSizes.measureDeep(this);
+    }
+
     public long maxTimestamp()
     {
         long maxTimestamp = deletionInfo().maxTimestamp();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/db/DeletionInfo.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/DeletionInfo.java 
b/src/java/org/apache/cassandra/db/DeletionInfo.java
index be64224..405645f 100644
--- a/src/java/org/apache/cassandra/db/DeletionInfo.java
+++ b/src/java/org/apache/cassandra/db/DeletionInfo.java
@@ -35,6 +35,7 @@ import org.apache.cassandra.io.sstable.Descriptor;
 import org.apache.cassandra.net.MessagingService;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.IntervalTree;
+import org.apache.cassandra.utils.ObjectSizes;
 
 public class DeletionInfo
 {
@@ -257,6 +258,14 @@ public class DeletionInfo
         return topLevel.equals(that.topLevel) && ranges.equals(that.ranges);
     }
 
+    public long memorySize()
+    {
+        long fields = topLevel.memorySize() + (2 * 
ObjectSizes.getReferenceSize());
+        if (ranges != null && !ranges.isEmpty())
+            fields += ObjectSizes.measureDeep(ranges);
+        return ObjectSizes.getFieldSize(fields);
+    }
+
     @Override
     public final int hashCode()
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/db/DeletionTime.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/DeletionTime.java 
b/src/java/org/apache/cassandra/db/DeletionTime.java
index 2b9efcd..5f39071 100644
--- a/src/java/org/apache/cassandra/db/DeletionTime.java
+++ b/src/java/org/apache/cassandra/db/DeletionTime.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import com.google.common.base.Objects;
 
 import org.apache.cassandra.io.ISerializer;
+import org.apache.cassandra.utils.ObjectSizes;
 
 public class DeletionTime implements Comparable<DeletionTime>
 {
@@ -85,6 +86,12 @@ public class DeletionTime implements Comparable<DeletionTime>
         return column.isMarkedForDelete() && column.getMarkedForDeleteAt() <= 
markedForDeleteAt;
     }
 
+    public long memorySize()
+    {
+        long fields = TypeSizes.NATIVE.sizeof(markedForDeleteAt) + 
TypeSizes.NATIVE.sizeof(localDeletionTime);
+        return ObjectSizes.getFieldSize(fields);
+    }
+
     private static class Serializer implements ISerializer<DeletionTime>
     {
         public void serialize(DeletionTime delTime, DataOutput out) throws 
IOException

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/db/RowIndexEntry.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/RowIndexEntry.java 
b/src/java/org/apache/cassandra/db/RowIndexEntry.java
index e9f08b2..a831498 100644
--- a/src/java/org/apache/cassandra/db/RowIndexEntry.java
+++ b/src/java/org/apache/cassandra/db/RowIndexEntry.java
@@ -24,13 +24,15 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.cassandra.cache.IMeasurableMemory;
 import org.apache.cassandra.io.sstable.Descriptor;
 import org.apache.cassandra.io.sstable.IndexHelper;
 import org.apache.cassandra.io.util.FileUtils;
 import org.apache.cassandra.utils.IFilter;
 import org.apache.cassandra.utils.FilterFactory;
+import org.apache.cassandra.utils.ObjectSizes;
 
-public class RowIndexEntry
+public class RowIndexEntry implements IMeasurableMemory
 {
     public static final Serializer serializer = new Serializer();
 
@@ -74,6 +76,12 @@ public class RowIndexEntry
         throw new UnsupportedOperationException();
     }
 
+    public long memorySize()
+    {
+        long fields = TypeSizes.NATIVE.sizeof(position) + 
ObjectSizes.getReferenceSize(); 
+        return ObjectSizes.getFieldSize(fields);
+    }
+
     public static class Serializer
     {
         public void serialize(RowIndexEntry rie, DataOutput dos) throws 
IOException
@@ -200,5 +208,14 @@ public class RowIndexEntry
             assert size <= Integer.MAX_VALUE;
             return (int)size;
         }
+
+        public long memorySize()
+        {
+            long internal = 0;
+            for (IndexHelper.IndexInfo idx : columnsIndex)
+                internal += idx.memorySize();
+            long listSize = 
ObjectSizes.getFieldSize(ObjectSizes.getArraySize(columnsIndex.size(), 
internal) + 4);
+            return ObjectSizes.getFieldSize(deletionInfo.memorySize() + 
listSize);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/io/sstable/IndexHelper.java 
b/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
index b81f7b8..444ec0b 100644
--- a/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
+++ b/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
@@ -246,5 +246,11 @@ public class IndexHelper
         {
             return new IndexInfo(ByteBufferUtil.readWithShortLength(dis), 
ByteBufferUtil.readWithShortLength(dis), dis.readLong(), dis.readLong());
         }
+
+        public long memorySize()
+        {
+            long fields = ObjectSizes.getSize(firstName) + 
ObjectSizes.getSize(lastName) + 8 + 8; 
+            return ObjectSizes.getFieldSize(fields);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/src/java/org/apache/cassandra/utils/ObjectSizes.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/ObjectSizes.java 
b/src/java/org/apache/cassandra/utils/ObjectSizes.java
new file mode 100644
index 0000000..6c28389
--- /dev/null
+++ b/src/java/org/apache/cassandra/utils/ObjectSizes.java
@@ -0,0 +1,204 @@
+package org.apache.cassandra.utils;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.nio.ByteBuffer;
+
+import org.github.jamm.MemoryMeter;
+
+/**
+ * Modified version of the code from.
+ * https://github.com/twitter/commons/blob/master
+ * /src/java/com/twitter/common/objectsize/ObjectSizeCalculator.java
+ *
+ * Difference is that we don't use reflection.
+ */
+public class ObjectSizes
+{
+    public static final MemoryLayoutSpecification SPEC = 
getEffectiveMemoryLayoutSpecification();
+    private static final MemoryMeter meter = new 
MemoryMeter().omitSharedBufferOverhead();
+
+    /**
+     * Describes constant memory overheads for various constructs in a JVM
+     * implementation.
+     */
+    public interface MemoryLayoutSpecification
+    {
+        int getArrayHeaderSize();
+
+        int getObjectHeaderSize();
+
+        int getObjectPadding();
+
+        int getReferenceSize();
+
+        int getSuperclassFieldPadding();
+    }
+
+    public static long getFieldSize(long fieldsSize)
+    {
+        return roundTo(SPEC.getObjectHeaderSize() + fieldsSize, 
SPEC.getObjectPadding());
+    }
+
+    public static long getSuperClassFieldSize(long fieldsSize)
+    {
+        return roundTo(fieldsSize, SPEC.getSuperclassFieldPadding());
+    }
+
+    public static long getArraySize(int length, long elementSize)
+    {
+        return roundTo(SPEC.getArrayHeaderSize() + length * elementSize, 
SPEC.getObjectPadding());
+    }
+
+    public static long getSizeWithRef(byte[] bytes)
+    {
+        return SPEC.getReferenceSize() + getArraySize(bytes.length, 1);
+    }
+
+    public static long getSize(ByteBuffer buffer)
+    {
+        long size = 0;
+        /* BB Class */
+        // final byte[] hb;
+        // final int offset;
+        // boolean isReadOnly;
+        size += ObjectSizes.getFieldSize(1L + 4 + 
ObjectSizes.getReferenceSize() + ObjectSizes.getArraySize(buffer.capacity(), 
1));
+        /* Super Class */
+        // private int mark;
+        // private int position;
+        // private int limit;
+        // private int capacity;
+        size += ObjectSizes.getSuperClassFieldSize(4L + 4 + 4 + 4 + 8);
+        return size;
+    }
+
+    public static long getSizeWithRef(ByteBuffer buffer)
+    {
+        return SPEC.getReferenceSize() + getSize(buffer);
+    }
+
+    public static long roundTo(long x, int multiple)
+    {
+        return ((x + multiple - 1) / multiple) * multiple;
+    }
+
+    public static int getReferenceSize()
+    {
+        return SPEC.getReferenceSize();
+    }
+
+    private static MemoryLayoutSpecification 
getEffectiveMemoryLayoutSpecification()
+    {
+        final String dataModel = System.getProperty("sun.arch.data.model");
+        if ("32".equals(dataModel))
+        {
+            // Running with 32-bit data model
+            return new MemoryLayoutSpecification()
+            {
+                public int getArrayHeaderSize()
+                {
+                    return 12;
+                }
+
+                public int getObjectHeaderSize()
+                {
+                    return 8;
+                }
+
+                public int getObjectPadding()
+                {
+                    return 8;
+                }
+
+                public int getReferenceSize()
+                {
+                    return 4;
+                }
+
+                public int getSuperclassFieldPadding()
+                {
+                    return 4;
+                }
+            };
+        }
+
+        final String strVmVersion = System.getProperty("java.vm.version");
+        final int vmVersion = Integer.parseInt(strVmVersion.substring(0, 
strVmVersion.indexOf('.')));
+        if (vmVersion >= 17)
+        {
+            long maxMemory = 0;
+            for (MemoryPoolMXBean mp : 
ManagementFactory.getMemoryPoolMXBeans())
+            {
+                maxMemory += mp.getUsage().getMax();
+            }
+            if (maxMemory < 30L * 1024 * 1024 * 1024)
+            {
+                // HotSpot 17.0 and above use compressed OOPs below 30GB of RAM
+                // total for all memory pools (yes, including code cache).
+                return new MemoryLayoutSpecification()
+                {
+                    public int getArrayHeaderSize()
+                    {
+                        return 16;
+                    }
+
+                    public int getObjectHeaderSize()
+                    {
+                        return 12;
+                    }
+
+                    public int getObjectPadding()
+                    {
+                        return 8;
+                    }
+
+                    public int getReferenceSize()
+                    {
+                        return 4;
+                    }
+
+                    public int getSuperclassFieldPadding()
+                    {
+                        return 4;
+                    }
+                };
+            }
+        }
+
+        /* Worst case we over count. */
+
+        // In other cases, it's a 64-bit uncompressed OOPs object model
+        return new MemoryLayoutSpecification()
+        {
+            public int getArrayHeaderSize()
+            {
+                return 24;
+            }
+
+            public int getObjectHeaderSize()
+            {
+                return 16;
+            }
+
+            public int getObjectPadding()
+            {
+                return 8;
+            }
+
+            public int getReferenceSize()
+            {
+                return 8;
+            }
+
+            public int getSuperclassFieldPadding()
+            {
+                return 8;
+            }
+        };
+    }
+
+    public static long measureDeep(Object pojo)
+    {
+        return meter.measureDeep(pojo);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/test/unit/org/apache/cassandra/cache/CacheProviderTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cache/CacheProviderTest.java 
b/test/unit/org/apache/cassandra/cache/CacheProviderTest.java
index fe0aa7f..bf0e34c 100644
--- a/test/unit/org/apache/cassandra/cache/CacheProviderTest.java
+++ b/test/unit/org/apache/cassandra/cache/CacheProviderTest.java
@@ -38,16 +38,16 @@ import static org.junit.Assert.*;
 
 public class CacheProviderTest extends SchemaLoader
 {
-    String key1 = "key1";
-    String key2 = "key2";
-    String key3 = "key3";
-    String key4 = "key4";
-    String key5 = "key5";
+    MeasureableString key1 = new MeasureableString("key1");
+    MeasureableString key2 = new MeasureableString("key2");
+    MeasureableString key3 = new MeasureableString("key3");
+    MeasureableString key4 = new MeasureableString("key4");
+    MeasureableString key5 = new MeasureableString("key5");
     private static final long CAPACITY = 4;
     private String tableName = "Keyspace1";
     private String cfName = "Standard1";
 
-    private void simpleCase(ColumnFamily cf, ICache<String, IRowCacheEntry> 
cache)
+    private void simpleCase(ColumnFamily cf, ICache<MeasureableString, 
IRowCacheEntry> cache)
     {
         cache.put(key1, cf);
         assert cache.get(key1) != null;
@@ -69,7 +69,7 @@ public class CacheProviderTest extends SchemaLoader
     }
 
     // TODO this isn't terribly useful
-    private void concurrentCase(final ColumnFamily cf, final ICache<String, 
IRowCacheEntry> cache) throws InterruptedException
+    private void concurrentCase(final ColumnFamily cf, final 
ICache<MeasureableString, IRowCacheEntry> cache) throws InterruptedException
     {
         Runnable runable = new Runnable()
         {
@@ -108,7 +108,7 @@ public class CacheProviderTest extends SchemaLoader
     @Test
     public void testHeapCache() throws InterruptedException
     {
-        ICache<String, IRowCacheEntry> cache = 
ConcurrentLinkedHashCache.create(CAPACITY, Weighers.<String, 
IRowCacheEntry>entrySingleton());
+        ICache<MeasureableString, IRowCacheEntry> cache = 
ConcurrentLinkedHashCache.create(CAPACITY, Weighers.<MeasureableString, 
IRowCacheEntry>entrySingleton());
         ColumnFamily cf = createCF();
         simpleCase(cf, cache);
         concurrentCase(cf, cache);
@@ -117,7 +117,7 @@ public class CacheProviderTest extends SchemaLoader
     @Test
     public void testSerializingCache() throws InterruptedException
     {
-        ICache<String, IRowCacheEntry> cache = 
SerializingCache.create(CAPACITY, Weighers.<RefCountedMemory>singleton(), new 
SerializingCacheProvider.RowCacheSerializer());
+        ICache<MeasureableString, IRowCacheEntry> cache = 
SerializingCache.create(CAPACITY, Weighers.<RefCountedMemory>singleton(), new 
SerializingCacheProvider.RowCacheSerializer());
         ColumnFamily cf = createCF();
         simpleCase(cf, cache);
         concurrentCase(cf, cache);
@@ -140,4 +140,19 @@ public class CacheProviderTest extends SchemaLoader
         assertNotSame(key1, key3);
         assertNotSame(key1.hashCode(), key3.hashCode());
     }
+
+    private class MeasureableString implements IMeasurableMemory
+    {
+        public final String string;
+
+        public MeasureableString(String input)
+        {
+            this.string = input;
+        }
+
+        public long memorySize()
+        {
+            return string.length();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/da93a1cf/test/unit/org/apache/cassandra/cache/ObjectSizeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cache/ObjectSizeTest.java 
b/test/unit/org/apache/cassandra/cache/ObjectSizeTest.java
new file mode 100644
index 0000000..398b395
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cache/ObjectSizeTest.java
@@ -0,0 +1,83 @@
+package org.apache.cassandra.cache;
+
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+import junit.framework.Assert;
+
+import org.apache.cassandra.db.DeletionInfo;
+import org.apache.cassandra.db.RowIndexEntry;
+import org.apache.cassandra.utils.ObjectSizes;
+import org.github.jamm.MemoryMeter;
+import org.junit.Test;
+
+public class ObjectSizeTest
+{
+    public static final MemoryMeter meter = new 
MemoryMeter().omitSharedBufferOverhead();
+
+    @Test
+    public void testArraySizes()
+    {
+        long size = ObjectSizes.getArraySize(0, 1);
+        long size2 = meter.measureDeep(new byte[0]);
+        Assert.assertEquals(size, size2);
+    }
+
+    @Test
+    public void testBiggerArraySizes()
+    {
+        long size = ObjectSizes.getArraySize(0, 1);
+        long size2 = meter.measureDeep(new byte[0]);
+        Assert.assertEquals(size, size2);
+
+        size = ObjectSizes.getArraySize(8, 1);
+        size2 = meter.measureDeep(new byte[8]);
+        Assert.assertEquals(size, size2);
+    }
+
+    @Test
+    public void testKeyCacheKey()
+    {
+        KeyCacheKey key = new KeyCacheKey(null, ByteBuffer.wrap(new byte[0]));
+        long size = key.memorySize();
+        long size2 = meter.measureDeep(key);
+        Assert.assertEquals(size, size2);
+    }
+
+    @Test
+    public void testKeyCacheValue()
+    {
+        RowIndexEntry entry = new RowIndexEntry(123);
+        long size = entry.memorySize();
+        long size2 = meter.measureDeep(entry);
+        Assert.assertEquals(size, size2);
+    }
+
+    @Test
+    public void testKeyCacheValueWithDelInfo()
+    {
+        RowIndexEntry entry = RowIndexEntry.create(123, new DeletionInfo(123, 
123), null);
+        long size = entry.memorySize();
+        long size2 = meter.measureDeep(entry);
+        Assert.assertEquals(size, size2);
+    }
+
+    @Test
+    public void testRowCacheKey()
+    {
+        UUID id = UUID.randomUUID();
+        RowCacheKey key = new RowCacheKey(id, ByteBuffer.wrap(new byte[11]));
+        long size = key.memorySize();
+        long size2 = meter.measureDeep(key) - meter.measureDeep(id);
+        Assert.assertEquals(size, size2);
+    }
+
+    @Test
+    public void testRowCacheSentinel()
+    {
+        RowCacheSentinel sentinel = new RowCacheSentinel(123);
+        long size = sentinel.memorySize();
+        long size2 = meter.measureDeep(sentinel);
+        Assert.assertEquals(size, size2);
+    }
+}

Reply via email to