Skip to content

Commit

Permalink
Flush on byte size
Browse files Browse the repository at this point in the history
  • Loading branch information
tomfran committed Feb 16, 2024
1 parent fd0d85b commit 1ec7983
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 28 deletions.
20 changes: 7 additions & 13 deletions src/main/java/com/tomfran/lsm/memtable/Memtable.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,14 @@
public class Memtable implements Iterable<ByteArrayPair> {

SkipList list;
long byteSize;

/**
* Initialize a Memtable with default list size.
*/
public Memtable() {
list = new SkipList();
}

/**
* Initialize a Memtable with an expected number of elements.
*
* @param numElements the expected max size of the underlying list.
*/
public Memtable(int numElements) {
list = new SkipList(numElements);
byteSize = 0L;
}

/**
Expand All @@ -32,6 +25,7 @@ public Memtable(int numElements) {
*/
public void add(ByteArrayPair item) {
list.add(item);
byteSize += item.size();
}

/**
Expand All @@ -54,12 +48,12 @@ public void remove(byte[] key) {
}

/**
* Get size of the underlying list.
* Return the size in bytes of the skiplist.
*
* @return the list size.
* @return bytes indicating size of underlying list.
*/
public int size() {
return list.size();
public long byteSize() {
return byteSize;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/tomfran/lsm/memtable/SkipList.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/
public class SkipList implements Iterable<ByteArrayPair> {

static final int DEFAULT_ELEMENTS = 1 << 16;
static final int DEFAULT_ELEMENTS = 1 << 20;

final Node sentinel;

Expand Down
20 changes: 10 additions & 10 deletions src/main/java/com/tomfran/lsm/tree/LSMTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*/
public class LSMTree {

static final int DEFAULT_MEMTABLE_MAX_SIZE = 1 << 10;
static final long DEFAULT_MEMTABLE_MAX__BYTE_SIZE = 1024 * 1024 * 256;
static final int DEFAULT_TABLE_LEVEL_MAX_SIZE = 5;
static final int DEFAULT_SSTABLE_SAMPLE_SIZE = 1 << 10;
static final String DEFAULT_DATA_DIRECTORY = "LSM-data";
Expand All @@ -34,7 +34,7 @@ public class LSMTree {
final Object immutableMemtablesLock = new Object();
final Object tableLock = new Object();

final int mutableMemtableMaxSize;
final long mutableMemtableMaxSize;
final int tableLevelMaxSize;
final String dataDir;

Expand All @@ -48,22 +48,22 @@ public class LSMTree {
* Creates a new LSMTree with a default memtable size and data directory.
*/
public LSMTree() {
this(DEFAULT_MEMTABLE_MAX_SIZE, DEFAULT_TABLE_LEVEL_MAX_SIZE, DEFAULT_DATA_DIRECTORY);
this(DEFAULT_MEMTABLE_MAX__BYTE_SIZE, DEFAULT_TABLE_LEVEL_MAX_SIZE, DEFAULT_DATA_DIRECTORY);
}

/**
* Creates a new LSMTree with a memtable size and data directory.
*
* @param mutableMemtableMaxSize The maximum size of the memtable before it is flushed to disk.
* @param mutableMemtableMaxByteSize The maximum size of the memtable before it is flushed to disk.
* @param dataDir The directory to store the data in.
*/
public LSMTree(int mutableMemtableMaxSize, int tableLevelMaxSize, String dataDir) {
this.mutableMemtableMaxSize = mutableMemtableMaxSize;
public LSMTree(long mutableMemtableMaxByteSize, int tableLevelMaxSize, String dataDir) {
this.mutableMemtableMaxSize = mutableMemtableMaxByteSize;
this.tableLevelMaxSize = tableLevelMaxSize;
this.dataDir = dataDir;
createDataDir();

mutableMemtable = new Memtable(mutableMemtableMaxSize);
mutableMemtable = new Memtable();
immutableMemtables = new LinkedList<>();
tables = new ObjectArrayList<>();
tables.add(new LinkedList<>());
Expand Down Expand Up @@ -132,18 +132,18 @@ public byte[] get(byte[] key) {
/**
* Stop the background threads.
*/
public void stop() throws InterruptedException {
public void stop() {
memtableFlusher.shutdownNow();
tableCompactor.shutdownNow();
}

private void checkMemtableSize() {
if (mutableMemtable.size() <= mutableMemtableMaxSize)
if (mutableMemtable.byteSize() <= mutableMemtableMaxSize)
return;

synchronized (immutableMemtablesLock) {
immutableMemtables.addFirst(mutableMemtable);
mutableMemtable = new Memtable(mutableMemtableMaxSize);
mutableMemtable = new Memtable();
memtableFlusher.execute(this::flushLastMemtable);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/tomfran/lsm/types/ByteArrayPair.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

public record ByteArrayPair(byte[] key, byte[] value) implements Comparable<ByteArrayPair> {

public int size() {
return key.length + value.length;
}

@Override
public int hashCode() {
return Arrays.hashCode(key);
Expand Down
7 changes: 7 additions & 0 deletions src/test/java/com/tomfran/lsm/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ public static ByteArrayPair getRandomPair() {
);
}

public static ByteArrayPair getRandomPair(int keyLen, int valueLen) {
return new ByteArrayPair(
getRandomByteArray(keyLen),
getRandomByteArray(valueLen)
);
}

public static byte[] getRandomByteArray(int length) {
byte[] bytes = new byte[length];
rn.nextBytes(bytes);
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/com/tomfran/lsm/tree/LSMTreeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ class LSMTreeTest {
public void writeFlush() throws InterruptedException {
LSMTree tree = new LSMTree(maxSize, levelSize, tempDirectory + "/test1");

IntStream.range(0, maxSize + 2).forEach(i -> tree.add(getRandomPair()));
IntStream.range(0, 10).forEach(i -> tree.add(getRandomPair(2, 2)));

Thread.sleep(500);

assert tree.mutableMemtable.size() >= 1 : "mutable memtable size is " + tree.mutableMemtable.size();
assert tree.mutableMemtable.byteSize() >= 1 : "mutable memtable size is " + tree.mutableMemtable.byteSize();
assert !tree.tables.get(0).isEmpty() : "table is null";

tree.stop();
Expand All @@ -36,8 +36,8 @@ public void writeFlow() throws InterruptedException {

Object2ObjectArrayMap<byte[], byte[]> items = new Object2ObjectArrayMap<>();

IntStream.range(0, 10 * maxSize).forEach(i -> {
var it = getRandomPair();
IntStream.range(0, 10).forEach(i -> {
var it = getRandomPair(2, 2);
tree.add(it);
items.put(it.key(), it.value());
});
Expand Down

0 comments on commit 1ec7983

Please sign in to comment.