You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2009/07/06 21:58:14 UTC

svn commit: r791592 - in /incubator/cassandra/trunk: conf/ src/java/org/apache/cassandra/config/ src/java/org/apache/cassandra/db/ src/java/org/apache/cassandra/io/ test/unit/org/apache/cassandra/io/

Author: jbellis
Date: Mon Jul  6 19:58:13 2009
New Revision: 791592

URL: http://svn.apache.org/viewvc?rev=791592&view=rev
Log:
per-table key cache size.
patch by jbellis; reviewed by Jun Rao for CASSANDRA-259

Modified:
    incubator/cassandra/trunk/conf/storage-conf.xml
    incubator/cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableWriter.java
    incubator/cassandra/trunk/test/unit/org/apache/cassandra/io/SSTableTest.java

Modified: incubator/cassandra/trunk/conf/storage-conf.xml
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/conf/storage-conf.xml?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/conf/storage-conf.xml (original)
+++ incubator/cassandra/trunk/conf/storage-conf.xml Mon Jul  6 19:58:13 2009
@@ -33,11 +33,17 @@
     -->
     <Tables>
         <Table Name="Table1">
-            <!-- Key cache size is the fraction of keys per sstable whose locations
-                 we keep in memory in "mostly LRU" order.  (JUST the key locations,
-                 NOT any column values.)  Consider increasing this is fine if you have
-                 fewer, wider rows. -->
-            <KeyCacheSize>0.01</KeyCacheSize>
+            <!-- The fraction of keys per sstable whose locations we
+                 keep in memory in "mostly LRU" order.  (JUST the key
+                 locations, NOT any column values.)
+
+                 The amount of memory used by the default setting of
+                 0.01 is comparable to the amount used by the internal
+                 per-sstable key index. Consider increasing this is
+                 fine if you have fewer, wider rows.  Set to 0 to
+                 disable entirely.
+            -->
+            <KeysCachedFraction>0.01</KeysCachedFraction>
             <!-- if FlushPeriodInMinutes is configured and positive, it will be
                  flushed to disk with that period whether it is dirty or not.
                  This is intended for lightly-used columnfamilies so that they

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java Mon Jul  6 19:58:13 2009
@@ -73,7 +73,7 @@
     private static String d_columnValue_      = "COLUMN_VALUE";
     private static String d_columnTimestamp_  = "COLUMN_TIMESTAMP";
 
-    private static Map<String, Double> tableKeyCacheSizes_;
+    private static Map<String, Double> tableKeysCachedFractions_;
     /*
      * A map from table names to the set of column families for the table and the
      * corresponding meta data for that column family.
@@ -273,7 +273,7 @@
                 CommitLog.setSegmentSize(Integer.parseInt(value) * 1024 * 1024);
 
             tableToCFMetaDataMap_ = new HashMap<String, Map<String, CFMetaData>>();
-            tableKeyCacheSizes_ = new HashMap<String, Double>();
+            tableKeysCachedFractions_ = new HashMap<String, Double>();
 
             /* Rack Aware option */
             value = xmlUtils.getNodeValue("/Storage/RackAware");
@@ -300,15 +300,15 @@
                 tables_.add(tName);
                 tableToCFMetaDataMap_.put(tName, new HashMap<String, CFMetaData>());
 
-                String xqlCacheSize = "/Storage/Tables/Table[@Name='" + tName + "']/KeyCacheSize";
+                String xqlCacheSize = "/Storage/Tables/Table[@Name='" + tName + "']/KeysCachedFraction";
                 value = xmlUtils.getNodeValue(xqlCacheSize);
                 if (value == null)
                 {
-                    tableKeyCacheSizes_.put(tName, 0.01);
+                    tableKeysCachedFractions_.put(tName, 0.01);
                 }
                 else
                 {
-                    tableKeyCacheSizes_.put(tName, Double.valueOf(value));
+                    tableKeysCachedFractions_.put(tName, Double.valueOf(value));
                 }
 
                 String xqlTable = "/Storage/Tables/Table[@Name='" + tName + "']/";
@@ -793,9 +793,9 @@
         return tableToCFMetaDataMap_;
     }
 
-    public static double getKeyCacheSize(String tableName)
+    public static double getKeysCachedFraction(String tableName)
     {
-        return tableKeyCacheSizes_.get(tableName);
+        return tableKeysCachedFractions_.get(tableName);
     }
 
     private static class ConfigurationException extends Exception

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/BinaryMemtable.java Mon Jul  6 19:58:13 2009
@@ -28,10 +28,9 @@
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.apache.cassandra.io.SSTableReader;
 import org.apache.cassandra.io.SSTableWriter;
-import org.apache.cassandra.io.SSTable;
 import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.config.DatabaseDescriptor;
 
 import org.apache.log4j.Logger;
 import org.cliffc.high_scale_lib.NonBlockingHashMap;
@@ -157,7 +156,7 @@
                 writer.append(key, bytes);
             }
         }
-        cfStore.storeLocation(writer.closeAndOpenReader());
+        cfStore.storeLocation(writer.closeAndOpenReader(DatabaseDescriptor.getKeysCachedFraction(table_)));
         columnFamilies_.clear();       
     }
 }

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java Mon Jul  6 19:58:13 2009
@@ -180,7 +180,7 @@
             String filename = file.getAbsolutePath();
             try
             {
-                SSTableReader sstable = SSTableReader.open(filename, StorageService.getPartitioner());
+                SSTableReader sstable = SSTableReader.open(filename);
                 ssTables_.put(filename, sstable);
             }
             catch (IOException ex)
@@ -985,7 +985,7 @@
                 if (logger_.isDebugEnabled())
                   logger_.debug("New file : " + newfile + " of size " + new File(newfile).length());
                 assert newfile != null;
-                ssTables_.put(newfile, SSTableReader.open(newfile, StorageService.getPartitioner()));
+                ssTables_.put(newfile, SSTableReader.open(newfile));
             }
             SSTableReader.get(file).delete();
         }
@@ -1174,7 +1174,7 @@
 
         if (rangeWriter != null)
         {
-            rangeWriter.closeAndOpenReader();
+            rangeWriter.closeAndOpenReader(DatabaseDescriptor.getKeysCachedFraction(table_));
             if (fileList != null)
             {
                 fileList.add(rangeWriter.getFilename());
@@ -1347,7 +1347,7 @@
         if (writer != null)
         {
             // TODO if all the keys were the same nothing will be done here
-            ssTable = writer.closeAndOpenReader();
+            ssTable = writer.closeAndOpenReader(DatabaseDescriptor.getKeysCachedFraction(table_));
             newfile = writer.getFilename();
         }
         lock_.writeLock().lock();

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnIterator.java Mon Jul  6 19:58:13 2009
@@ -25,7 +25,6 @@
 import org.apache.cassandra.io.DataOutputBuffer;
 import org.apache.cassandra.io.SSTableReader;
 import org.apache.cassandra.io.SequenceFile.ColumnGroupReader;
-import org.apache.cassandra.service.StorageService;
 import com.google.common.collect.AbstractIterator;
 
 public interface ColumnIterator extends Iterator<IColumn>
@@ -58,7 +57,7 @@
     throws IOException
     {
         this.isAscending = isAscending;
-        SSTableReader ssTable = SSTableReader.open(filename, StorageService.getPartitioner());
+        SSTableReader ssTable = SSTableReader.open(filename);
         reader = ssTable.getColumnGroupReader(key, cfName, startColumn, isAscending);
         this.startColumn = startColumn;
         curColumnIndex = isAscending ? 0 : -1;

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Memtable.java Mon Jul  6 19:58:13 2009
@@ -277,7 +277,7 @@
                 writer.append(partitioner.decorateKey(key), buffer);
             }
         }
-        SSTableReader ssTable = writer.closeAndOpenReader();
+        SSTableReader ssTable = writer.closeAndOpenReader(DatabaseDescriptor.getKeysCachedFraction(table_));
         cfStore.onMemtableFlush(cLogCtx);
         cfStore.storeLocation(ssTable);
         buffer.close();

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java Mon Jul  6 19:58:13 2009
@@ -185,7 +185,7 @@
                  * list of the associated Column Family. Also merge the CBF into the
                  * sampler.
                 */                
-                SSTableReader sstable = SSTableReader.open(streamContext.getTargetFile(), StorageService.getPartitioner());
+                SSTableReader sstable = SSTableReader.open(streamContext.getTargetFile());
                 logger_.debug("Merging the counting bloom filter in the sampler ...");                
                 String[] peices = FBUtilities.strip(fileName, "-");
                 Table.open(peices[0]).getColumnFamilyStore(peices[1]).addToList(sstable);                

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java Mon Jul  6 19:58:13 2009
@@ -28,6 +28,8 @@
 import org.apache.cassandra.io.SequenceFile.ColumnGroupReader;
 import org.apache.cassandra.utils.BloomFilter;
 import org.apache.cassandra.utils.FileUtils;
+import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.config.DatabaseDescriptor;
 import org.cliffc.high_scale_lib.NonBlockingHashMap;
 import com.reardencommerce.kernel.collections.shared.evictable.ConcurrentLinkedHashMap;
 
@@ -78,7 +80,12 @@
         return indexedKeys;
     }
 
-    public static synchronized SSTableReader open(String dataFileName, IPartitioner partitioner) throws IOException
+    public static synchronized SSTableReader open(String dataFileName) throws IOException
+    {
+        return open(dataFileName, StorageService.getPartitioner(), DatabaseDescriptor.getKeysCachedFraction(parseTableName(dataFileName)));
+    }
+
+    public static synchronized SSTableReader open(String dataFileName, IPartitioner partitioner, double cacheFraction) throws IOException
     {
         SSTableReader sstable = openedFiles.get(dataFileName);
         if (sstable == null)
@@ -89,6 +96,10 @@
             long start = System.currentTimeMillis();
             sstable.loadIndexFile();
             sstable.loadBloomFilter();
+            if (cacheFraction > 0)
+            {
+                sstable.keyCache = createKeyCache((int)((sstable.getIndexPositions().size() + 1) * INDEX_INTERVAL * cacheFraction));
+            }
             logger.debug("INDEX LOAD TIME for "  + dataFileName + ": " + (System.currentTimeMillis() - start) + " ms.");
 
             openedFiles.put(dataFileName, sstable);
@@ -103,14 +114,20 @@
         return sstable;
     }
 
+    public static ConcurrentLinkedHashMap<String, Long> createKeyCache(int size)
+    {
+        return ConcurrentLinkedHashMap.create(ConcurrentLinkedHashMap.EvictionPolicy.SECOND_CHANCE, size);
+    }
+
 
-    private ConcurrentLinkedHashMap<String, Long> keyCache = ConcurrentLinkedHashMap.create(ConcurrentLinkedHashMap.EvictionPolicy.SECOND_CHANCE, 1000);
+    private ConcurrentLinkedHashMap<String, Long> keyCache;
 
-    SSTableReader(String filename, IPartitioner partitioner, List<KeyPosition> indexPositions, BloomFilter bloomFilter)
+    SSTableReader(String filename, IPartitioner partitioner, List<KeyPosition> indexPositions, BloomFilter bloomFilter, ConcurrentLinkedHashMap<String, Long> keyCache)
     {
         super(filename, partitioner);
         this.indexPositions = indexPositions;
         this.bf = bloomFilter;
+        this.keyCache = keyCache;
         synchronized (SSTableReader.this)
         {
             openedFiles.put(filename, this);
@@ -183,10 +200,13 @@
     {
         if (!bf.isPresent(decoratedKey))
             return -1;
-        Long cachedPosition = keyCache.get(decoratedKey);
-        if (cachedPosition != null)
+        if (keyCache != null)
         {
-            return cachedPosition;
+            Long cachedPosition = keyCache.get(decoratedKey);
+            if (cachedPosition != null)
+            {
+                return cachedPosition;
+            }
         }
         long start = getIndexScanPosition(decoratedKey, partitioner);
         if (start < 0)
@@ -215,7 +235,8 @@
                 int v = partitioner.getDecoratedKeyComparator().compare(indexDecoratedKey, decoratedKey);
                 if (v == 0)
                 {
-                    keyCache.put(decoratedKey, position);
+                    if (keyCache != null)
+                        keyCache.put(decoratedKey, position);
                     return position;
                 }
                 if (v > 0)
@@ -350,7 +371,7 @@
         openedFiles.clear();
         for (SSTableReader sstable : sstables)
         {
-            SSTableReader.open(sstable.dataFile, sstable.partitioner);
+            SSTableReader.open(sstable.dataFile, sstable.partitioner, 0.01);
         }
     }
 

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableWriter.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableWriter.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableWriter.java (original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableWriter.java Mon Jul  6 19:58:13 2009
@@ -11,6 +11,7 @@
 
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.cassandra.utils.BloomFilter;
+import com.reardencommerce.kernel.collections.shared.evictable.ConcurrentLinkedHashMap;
 
 public class SSTableWriter extends SSTable
 {
@@ -91,7 +92,7 @@
     /**
      * Renames temporary SSTable files to valid data, index, and bloom filter files
      */
-    public SSTableReader closeAndOpenReader() throws IOException
+    public SSTableReader closeAndOpenReader(double cacheFraction) throws IOException
     {
         // bloom filter
         FileOutputStream fos = new FileOutputStream(filterFilename());
@@ -112,7 +113,10 @@
         rename(filterFilename());
         dataFile = rename(dataFile); // important to do this last since index & filter file names are derived from it
 
-        return new SSTableReader(dataFile, partitioner, indexPositions, bf);
+        ConcurrentLinkedHashMap<String,Long> keyCache = cacheFraction > 0
+                                                        ? SSTableReader.createKeyCache((int) (cacheFraction * keysWritten))
+                                                        : null;
+        return new SSTableReader(dataFile, partitioner, indexPositions, bf, keyCache);
     }
 
 }

Modified: incubator/cassandra/trunk/test/unit/org/apache/cassandra/io/SSTableTest.java
URL: http://svn.apache.org/viewvc/incubator/cassandra/trunk/test/unit/org/apache/cassandra/io/SSTableTest.java?rev=791592&r1=791591&r2=791592&view=diff
==============================================================================
--- incubator/cassandra/trunk/test/unit/org/apache/cassandra/io/SSTableTest.java (original)
+++ incubator/cassandra/trunk/test/unit/org/apache/cassandra/io/SSTableTest.java Mon Jul  6 19:58:13 2009
@@ -42,7 +42,7 @@
 
         String key = Integer.toString(1);
         writer.append(key, bytes);
-        SSTableReader ssTable = writer.closeAndOpenReader();
+        SSTableReader ssTable = writer.closeAndOpenReader(0.01);
 
         // verify
         verifySingle(ssTable, bytes, key);
@@ -81,7 +81,7 @@
         {
             writer.append(key, map.get(key));
         }
-        SSTableReader ssTable = writer.closeAndOpenReader();
+        SSTableReader ssTable = writer.closeAndOpenReader(0.01);
 
         // verify
         verifyMany(ssTable, map);