merge from 0.6

git-svn-id: https://svn.apache.org/repos/asf/cassandra/trunk@956979 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jonathan Ellis 2010-06-22 19:06:25 +00:00
parent 8eeaa1469c
commit 97b45898c0
6 changed files with 205 additions and 2 deletions

View File

@ -52,6 +52,7 @@ dev
* force anti-entropy service to stream files on the stream stage to avoid
sending streams out of order (CASSANDRA-1169)
* remove inactive stream managers after AES streams files (CASSANDRA-1169)
* add JMX metrics for row-level bloom filter false positives (CASSANDRA-1212)
* added a redhat init script to contrib (CASSANDRA-1201)

View File

@ -32,9 +32,11 @@ import java.util.regex.Pattern;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import org.apache.commons.collections.IteratorUtils;
import com.google.common.collect.Iterables;
import org.apache.cassandra.concurrent.JMXEnabledThreadPoolExecutor;
import org.apache.cassandra.concurrent.NamedThreadFactory;
import org.apache.cassandra.concurrent.StageManager;
@ -1168,6 +1170,53 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
};
return commitLogUpdater_.submit(runnable);
}
}
public long getBloomFilterFalsePositives()
{
long count = 0L;
for (SSTableReader sstable: getSSTables())
{
count += sstable.getBloomFilterFalsePositiveCount();
}
return count;
}
public long getRecentBloomFilterFalsePositives()
{
long count = 0L;
for (SSTableReader sstable: getSSTables())
{
count += sstable.getRecentBloomFilterFalsePositiveCount();
}
return count;
}
public double getBloomFilterFalseRatio()
{
Long falseCount = 0L;
Long trueCount = 0L;
for (SSTableReader sstable: getSSTables())
{
falseCount += sstable.getBloomFilterFalsePositiveCount();
trueCount += sstable.getBloomFilterTruePositiveCount();
}
if (falseCount.equals(0L) && trueCount.equals(0L))
return 0d;
return falseCount.doubleValue() / (trueCount.doubleValue() + falseCount.doubleValue());
}
public double getRecentBloomFilterFalseRatio()
{
Long falseCount = 0L;
Long trueCount = 0L;
for (SSTableReader sstable: getSSTables())
{
falseCount += sstable.getRecentBloomFilterFalsePositiveCount();
trueCount += sstable.getRecentBloomFilterTruePositiveCount();
}
if (falseCount.equals(0L) && trueCount.equals(0L))
return 0d;
return falseCount.doubleValue() / (trueCount.doubleValue() + falseCount.doubleValue());
}
}

View File

@ -157,4 +157,12 @@ public interface ColumnFamilyStoreMBean
* @return
*/
public long getMeanRowCompactedSize();
public long getBloomFilterFalsePositives();
public long getRecentBloomFilterFalsePositives();
public double getBloomFilterFalseRatio();
public double getRecentBloomFilterFalseRatio();
}

View File

@ -0,0 +1,57 @@
package org.apache.cassandra.io;
import java.util.concurrent.atomic.AtomicLong;
public class BloomFilterTracker
{
private AtomicLong falsePositiveCount = new AtomicLong(0);
private AtomicLong truePositiveCount = new AtomicLong(0);
private long lastFalsePositiveCount = 0L;
private long lastTruePositiveCount = 0L;
public void addFalsePositive()
{
falsePositiveCount.incrementAndGet();
}
public void addTruePositive()
{
truePositiveCount.incrementAndGet();
}
public long getFalsePositiveCount()
{
return falsePositiveCount.get();
}
public long getRecentFalsePositiveCount()
{
long fpc = getFalsePositiveCount();
try
{
return (fpc - lastFalsePositiveCount);
}
finally
{
lastFalsePositiveCount = fpc;
}
}
public long getTruePositiveCount()
{
return truePositiveCount.get();
}
public long getRecentTruePositiveCount()
{
long tpc = getTruePositiveCount();
try
{
return (tpc - lastTruePositiveCount);
}
finally
{
lastTruePositiveCount = tpc;
}
}
}

View File

@ -44,6 +44,7 @@ import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.dht.AbstractBounds;
import org.apache.cassandra.dht.Range;
import org.apache.cassandra.io.BloomFilterTracker;
import org.apache.cassandra.io.ICompactSerializer2;
import org.apache.cassandra.io.util.FileDataInput;
import org.apache.cassandra.utils.BloomFilter;
@ -118,6 +119,8 @@ public class SSTableReader extends SSTable implements Comparable<SSTableReader>
private InstrumentedCache<Pair<Descriptor,DecoratedKey>, Long> keyCache;
private BloomFilterTracker bloomFilterTracker = new BloomFilterTracker();
private volatile SSTableDeletingReference phantomReference;
public static int indexInterval()
@ -397,8 +400,12 @@ public class SSTableReader extends SSTable implements Comparable<SSTableReader>
// next, see if the sampled index says it's impossible for the key to be present
IndexSummary.KeyPosition sampledPosition = getIndexScanPosition(decoratedKey);
if (sampledPosition == null)
{
if (op == Operator.EQ)
bloomFilterTracker.addFalsePositive();
// we matched the -1th position: if the operator might match forward, return the 0th position
return op.apply(1) >= 0 ? 0 : -1;
}
// scan the on-disk index, starting at the nearest sampled position
Iterator<FileDataInput> segments = ifile.iterator(sampledPosition.indexPosition, INDEX_FILE_BUFFER_BYTES);
@ -418,12 +425,20 @@ public class SSTableReader extends SSTable implements Comparable<SSTableReader>
if (v == 0)
{
if (comparison == 0 && keyCache != null && keyCache.getCapacity() > 0)
{
if (op == Operator.EQ)
bloomFilterTracker.addTruePositive();
// store exact match for the key
keyCache.put(unifiedKey, Long.valueOf(dataPosition));
}
return dataPosition;
}
if (v < 0)
{
if (op == Operator.EQ)
bloomFilterTracker.addFalsePositive();
return -1;
}
}
}
catch (IOException e)
@ -442,6 +457,9 @@ public class SSTableReader extends SSTable implements Comparable<SSTableReader>
}
}
}
if (op == Operator.EQ)
bloomFilterTracker.addFalsePositive();
return -1;
}
@ -571,4 +589,24 @@ public class SSTableReader extends SSTable implements Comparable<SSTableReader>
public int apply(int comparison) { return comparison > 0 ? 0 : 1; }
}
}
public long getBloomFilterFalsePositiveCount()
{
return bloomFilterTracker.getFalsePositiveCount();
}
public long getRecentBloomFilterFalsePositiveCount()
{
return bloomFilterTracker.getRecentFalsePositiveCount();
}
public long getBloomFilterTruePositiveCount()
{
return bloomFilterTracker.getTruePositiveCount();
}
public long getRecentBloomFilterTruePositiveCount()
{
return bloomFilterTracker.getRecentTruePositiveCount();
}
}

View File

@ -0,0 +1,50 @@
package org.apache.cassandra.io;
import org.junit.Test;
import org.apache.cassandra.CleanupHelper;
import static org.junit.Assert.assertEquals;
public class BloomFilterTrackerTest extends CleanupHelper
{
@Test
public void testAddingFalsePositives()
{
BloomFilterTracker bft = new BloomFilterTracker();
assertEquals(0L, bft.getFalsePositiveCount());
assertEquals(0L, bft.getRecentFalsePositiveCount());
bft.addFalsePositive();
bft.addFalsePositive();
assertEquals(2L, bft.getFalsePositiveCount());
assertEquals(2L, bft.getRecentFalsePositiveCount());
assertEquals(0L, bft.getRecentFalsePositiveCount());
assertEquals(2L, bft.getFalsePositiveCount()); // sanity check
}
@Test
public void testAddingTruePositives()
{
BloomFilterTracker bft = new BloomFilterTracker();
assertEquals(0L, bft.getTruePositiveCount());
assertEquals(0L, bft.getRecentTruePositiveCount());
bft.addTruePositive();
bft.addTruePositive();
assertEquals(2L, bft.getTruePositiveCount());
assertEquals(2L, bft.getRecentTruePositiveCount());
assertEquals(0L, bft.getRecentTruePositiveCount());
assertEquals(2L, bft.getTruePositiveCount()); // sanity check
}
@Test
public void testAddingToOneLeavesTheOtherAlone()
{
BloomFilterTracker bft = new BloomFilterTracker();
bft.addFalsePositive();
assertEquals(0L, bft.getTruePositiveCount());
assertEquals(0L, bft.getRecentTruePositiveCount());
bft.addTruePositive();
assertEquals(1L, bft.getFalsePositiveCount());
assertEquals(1L, bft.getRecentFalsePositiveCount());
}
}