mirror of https://github.com/apache/cassandra
Avoid memory allocation when searching index summary
patch by benedict; reviewed by ariel for CASSANDRA-8793
This commit is contained in:
parent
6d266253a5
commit
bf9c503130
|
|
@ -1,4 +1,5 @@
|
||||||
3.0
|
3.0
|
||||||
|
* Avoid memory allocation when searching index summary (CASSANDRA-8793)
|
||||||
* Optimise (Time)?UUIDType Comparisons (CASSANDRA-8730)
|
* Optimise (Time)?UUIDType Comparisons (CASSANDRA-8730)
|
||||||
* Make CRC32Ex into a separate maven dependency (CASSANDRA-8836)
|
* Make CRC32Ex into a separate maven dependency (CASSANDRA-8836)
|
||||||
* Use preloaded jemalloc w/ Unsafe (CASSANDRA-8714)
|
* Use preloaded jemalloc w/ Unsafe (CASSANDRA-8714)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import org.apache.cassandra.io.util.Memory;
|
||||||
import org.apache.cassandra.io.util.MemoryOutputStream;
|
import org.apache.cassandra.io.util.MemoryOutputStream;
|
||||||
import org.apache.cassandra.utils.FBUtilities;
|
import org.apache.cassandra.utils.FBUtilities;
|
||||||
import org.apache.cassandra.utils.concurrent.WrappedSharedCloseable;
|
import org.apache.cassandra.utils.concurrent.WrappedSharedCloseable;
|
||||||
|
import org.apache.cassandra.utils.memory.MemoryUtil;
|
||||||
|
|
||||||
import static org.apache.cassandra.io.sstable.Downsampling.BASE_SAMPLING_LEVEL;
|
import static org.apache.cassandra.io.sstable.Downsampling.BASE_SAMPLING_LEVEL;
|
||||||
|
|
||||||
|
|
@ -105,11 +106,13 @@ public class IndexSummary extends WrappedSharedCloseable
|
||||||
// Harmony's Collections implementation
|
// Harmony's Collections implementation
|
||||||
public int binarySearch(RowPosition key)
|
public int binarySearch(RowPosition key)
|
||||||
{
|
{
|
||||||
|
ByteBuffer hollow = MemoryUtil.getHollowDirectByteBuffer();
|
||||||
int low = 0, mid = offsetCount, high = mid - 1, result = -1;
|
int low = 0, mid = offsetCount, high = mid - 1, result = -1;
|
||||||
while (low <= high)
|
while (low <= high)
|
||||||
{
|
{
|
||||||
mid = (low + high) >> 1;
|
mid = (low + high) >> 1;
|
||||||
result = -DecoratedKey.compareTo(partitioner, ByteBuffer.wrap(getKey(mid)), key);
|
fillTemporaryKey(mid, hollow);
|
||||||
|
result = -DecoratedKey.compareTo(partitioner, hollow, key);
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
{
|
{
|
||||||
low = mid + 1;
|
low = mid + 1;
|
||||||
|
|
@ -147,6 +150,13 @@ public class IndexSummary extends WrappedSharedCloseable
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fillTemporaryKey(int index, ByteBuffer buffer)
|
||||||
|
{
|
||||||
|
long start = getPositionInSummary(index);
|
||||||
|
int keySize = (int) (calculateEnd(index) - start - 8L);
|
||||||
|
entries.setByteBuffer(buffer, start, keySize);
|
||||||
|
}
|
||||||
|
|
||||||
public long getPosition(int index)
|
public long getPosition(int index)
|
||||||
{
|
{
|
||||||
return entries.getLong(calculateEnd(index) - 8);
|
return entries.getLong(calculateEnd(index) - 8);
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,8 @@ public class IndexSummaryBuilder implements AutoCloseable
|
||||||
|
|
||||||
// for initializing data structures, adjust our estimates based on the sampling level
|
// for initializing data structures, adjust our estimates based on the sampling level
|
||||||
maxExpectedEntries = Math.max(1, (maxExpectedEntries * samplingLevel) / BASE_SAMPLING_LEVEL);
|
maxExpectedEntries = Math.max(1, (maxExpectedEntries * samplingLevel) / BASE_SAMPLING_LEVEL);
|
||||||
offsets = new SafeMemoryWriter(4 * maxExpectedEntries).withByteOrder(ByteOrder.nativeOrder());
|
offsets = new SafeMemoryWriter(4 * maxExpectedEntries).order(ByteOrder.nativeOrder());
|
||||||
entries = new SafeMemoryWriter(40 * maxExpectedEntries).withByteOrder(ByteOrder.nativeOrder());
|
entries = new SafeMemoryWriter(40 * maxExpectedEntries).order(ByteOrder.nativeOrder());
|
||||||
setNextSamplePosition(-minIndexInterval);
|
setNextSamplePosition(-minIndexInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ public class Memory implements AutoCloseable
|
||||||
|
|
||||||
public void setShort(long offset, short l)
|
public void setShort(long offset, short l)
|
||||||
{
|
{
|
||||||
checkBounds(offset, offset + 4);
|
checkBounds(offset, offset + 2);
|
||||||
if (unaligned)
|
if (unaligned)
|
||||||
{
|
{
|
||||||
unsafe.putShort(peer + offset, l);
|
unsafe.putShort(peer + offset, l);
|
||||||
|
|
@ -245,9 +245,7 @@ public class Memory implements AutoCloseable
|
||||||
else if (count == 0)
|
else if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
long end = memoryOffset + count;
|
checkBounds(memoryOffset, memoryOffset + count);
|
||||||
checkBounds(memoryOffset, end);
|
|
||||||
|
|
||||||
unsafe.copyMemory(buffer, BYTE_ARRAY_BASE_OFFSET + bufferOffset, null, peer + memoryOffset, count);
|
unsafe.copyMemory(buffer, BYTE_ARRAY_BASE_OFFSET + bufferOffset, null, peer + memoryOffset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,6 +341,8 @@ public class Memory implements AutoCloseable
|
||||||
|
|
||||||
public void put(long trgOffset, Memory memory, long srcOffset, long size)
|
public void put(long trgOffset, Memory memory, long srcOffset, long size)
|
||||||
{
|
{
|
||||||
|
checkBounds(trgOffset, trgOffset + size);
|
||||||
|
memory.checkBounds(srcOffset, srcOffset + size);
|
||||||
unsafe.copyMemory(memory.peer + srcOffset, peer + trgOffset, size);
|
unsafe.copyMemory(memory.peer + srcOffset, peer + trgOffset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,6 +401,19 @@ public class Memory implements AutoCloseable
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ByteBuffer asByteBuffer(long offset, int length)
|
||||||
|
{
|
||||||
|
checkBounds(offset, offset + length);
|
||||||
|
return MemoryUtil.getByteBuffer(peer + offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MUST provide a buffer created via MemoryUtil.getHollowDirectByteBuffer()
|
||||||
|
public void setByteBuffer(ByteBuffer buffer, long offset, int length)
|
||||||
|
{
|
||||||
|
checkBounds(offset, offset + length);
|
||||||
|
MemoryUtil.setByteBuffer(buffer, peer + offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return toString(peer, size);
|
return toString(peer, size);
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ public class SafeMemoryWriter extends AbstractDataOutput implements DataOutputPl
|
||||||
buffer = new SafeMemory(initialCapacity);
|
buffer = new SafeMemory(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void write(byte[] buffer, int offset, int count)
|
public void write(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
long newLength = ensureCapacity(count);
|
long newLength = ensureCapacity(count);
|
||||||
|
|
@ -40,6 +41,7 @@ public class SafeMemoryWriter extends AbstractDataOutput implements DataOutputPl
|
||||||
this.length = newLength;
|
this.length = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void write(int oneByte)
|
public void write(int oneByte)
|
||||||
{
|
{
|
||||||
long newLength = ensureCapacity(1);
|
long newLength = ensureCapacity(1);
|
||||||
|
|
@ -47,6 +49,7 @@ public class SafeMemoryWriter extends AbstractDataOutput implements DataOutputPl
|
||||||
length = newLength;
|
length = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void writeShort(int val) throws IOException
|
public void writeShort(int val) throws IOException
|
||||||
{
|
{
|
||||||
if (order != ByteOrder.nativeOrder())
|
if (order != ByteOrder.nativeOrder())
|
||||||
|
|
@ -56,6 +59,7 @@ public class SafeMemoryWriter extends AbstractDataOutput implements DataOutputPl
|
||||||
length = newLength;
|
length = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void writeInt(int val)
|
public void writeInt(int val)
|
||||||
{
|
{
|
||||||
if (order != ByteOrder.nativeOrder())
|
if (order != ByteOrder.nativeOrder())
|
||||||
|
|
@ -65,6 +69,7 @@ public class SafeMemoryWriter extends AbstractDataOutput implements DataOutputPl
|
||||||
length = newLength;
|
length = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void writeLong(long val)
|
public void writeLong(long val)
|
||||||
{
|
{
|
||||||
if (order != ByteOrder.nativeOrder())
|
if (order != ByteOrder.nativeOrder())
|
||||||
|
|
@ -74,6 +79,7 @@ public class SafeMemoryWriter extends AbstractDataOutput implements DataOutputPl
|
||||||
length = newLength;
|
length = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void write(ByteBuffer buffer)
|
public void write(ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
long newLength = ensureCapacity(buffer.remaining());
|
long newLength = ensureCapacity(buffer.remaining());
|
||||||
|
|
@ -81,10 +87,11 @@ public class SafeMemoryWriter extends AbstractDataOutput implements DataOutputPl
|
||||||
length = newLength;
|
length = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(Memory memory)
|
@Override
|
||||||
|
public void write(Memory memory, long offset, long size)
|
||||||
{
|
{
|
||||||
long newLength = ensureCapacity(memory.size());
|
long newLength = ensureCapacity(size);
|
||||||
buffer.put(length, memory, 0, memory.size());
|
buffer.put(length, memory, offset, size);
|
||||||
length = newLength;
|
length = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +135,7 @@ public class SafeMemoryWriter extends AbstractDataOutput implements DataOutputPl
|
||||||
|
|
||||||
// TODO: consider hoisting this into DataOutputPlus, since most implementations can copy with this gracefully
|
// TODO: consider hoisting this into DataOutputPlus, since most implementations can copy with this gracefully
|
||||||
// this would simplify IndexSummary.IndexSummarySerializer.serialize()
|
// this would simplify IndexSummary.IndexSummarySerializer.serialize()
|
||||||
public SafeMemoryWriter withByteOrder(ByteOrder order)
|
public SafeMemoryWriter order(ByteOrder order)
|
||||||
{
|
{
|
||||||
this.order = order;
|
this.order = order;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,13 @@ public abstract class MemoryUtil
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ByteBuffer getByteBuffer(long address, int length)
|
public static ByteBuffer getByteBuffer(long address, int length)
|
||||||
|
{
|
||||||
|
ByteBuffer instance = getHollowDirectByteBuffer();
|
||||||
|
setByteBuffer(instance, address, length);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteBuffer getHollowDirectByteBuffer()
|
||||||
{
|
{
|
||||||
ByteBuffer instance;
|
ByteBuffer instance;
|
||||||
try
|
try
|
||||||
|
|
@ -133,12 +140,15 @@ public abstract class MemoryUtil
|
||||||
{
|
{
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
|
instance.order(ByteOrder.nativeOrder());
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setByteBuffer(ByteBuffer instance, long address, int length)
|
||||||
|
{
|
||||||
unsafe.putLong(instance, DIRECT_BYTE_BUFFER_ADDRESS_OFFSET, address);
|
unsafe.putLong(instance, DIRECT_BYTE_BUFFER_ADDRESS_OFFSET, address);
|
||||||
unsafe.putInt(instance, DIRECT_BYTE_BUFFER_CAPACITY_OFFSET, length);
|
unsafe.putInt(instance, DIRECT_BYTE_BUFFER_CAPACITY_OFFSET, length);
|
||||||
unsafe.putInt(instance, DIRECT_BYTE_BUFFER_LIMIT_OFFSET, length);
|
unsafe.putInt(instance, DIRECT_BYTE_BUFFER_LIMIT_OFFSET, length);
|
||||||
instance.order(ByteOrder.nativeOrder());
|
|
||||||
return instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getLongByByte(long address)
|
public static long getLongByByte(long address)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue