Skip to content

Commit

Permalink
2X performance improvement, and better tests (#1884)
Browse files Browse the repository at this point in the history
* 2X performance improvement, and better tests
  • Loading branch information
SergioDemianLerner authored Sep 22, 2022
1 parent aec2eda commit 9d23e67
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
19 changes: 19 additions & 0 deletions rskj-core/src/main/java/co/rsk/core/bc/ReadWrittenKeysTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,33 @@ public Map<Long, Set<ByteArrayWrapper>> getWrittenKeysByThread() {
@Override
public synchronized void addNewReadKey(ByteArrayWrapper key) {
long threadId = Thread.currentThread().getId();
addNewReadKeyToThread(threadId,key);
}

public synchronized void addNewReadKeyToThread(long threadId,ByteArrayWrapper key) {
Set<ByteArrayWrapper> readKeys = readKeysByThread.containsKey(threadId)? readKeysByThread.get(threadId) : new HashSet<>();
readKeys.add(key);
readKeysByThread.put(threadId, readKeys);
}
public synchronized void removeReadKeyToThread(long threadId,ByteArrayWrapper key) {
Set<ByteArrayWrapper> readKeys = readKeysByThread.containsKey(threadId)? readKeysByThread.get(threadId) : new HashSet<>();
readKeys.remove(key);
readKeysByThread.put(threadId, readKeys);
}

@Override
public synchronized void addNewWrittenKey(ByteArrayWrapper key) {
long threadId = Thread.currentThread().getId();
addNewWrittenKeyToThread(threadId,key);

}
public synchronized void removeWrittenKeyToThread(long threadId,ByteArrayWrapper key) {
Set<ByteArrayWrapper> writtenKeys = writtenKeysByThread.containsKey(threadId)? writtenKeysByThread.get(threadId) : new HashSet<>();
writtenKeys.remove(key);
writtenKeysByThread.put(threadId, writtenKeys);
}

public synchronized void addNewWrittenKeyToThread(long threadId,ByteArrayWrapper key) {
Set<ByteArrayWrapper> writtenKeys = writtenKeysByThread.containsKey(threadId)? writtenKeysByThread.get(threadId) : new HashSet<>();
writtenKeys.add(key);
writtenKeysByThread.put(threadId, writtenKeys);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,104 @@ public void setup() {
this.key2 = new ByteArrayWrapper(new byte[]{2});
}

ByteArrayWrapper getKey(int thread, int readWrite,int i ) {
// Supports upto 65536 keys
return new ByteArrayWrapper(new byte[]{(byte)thread, (byte) readWrite,
(byte) (i >> 8), (byte) (i & 0xff)});
}

@Test
public void collisionWithLongerSets() {
//..
ReadWrittenKeysTracker myTracker = (ReadWrittenKeysTracker) this.tracker;
int keysPerThread = 10;
int maxThreads = 4;

// Add read 10 distinct keys for each one of 4 threads
for (int thread=0; thread<maxThreads; thread++) {
for (int i = 0; i < keysPerThread; i++) {
ByteArrayWrapper key = getKey(thread,0,i);
myTracker.addNewReadKeyToThread(thread,key);
}
}
// No collisions at this point
assertFalse(tracker.detectCollision());

// Now add 10 distinct written keys per thread
for (int thread=0;thread<maxThreads;thread++) {
for (int i = 0; i < keysPerThread; i++) {
ByteArrayWrapper key = getKey(thread,1,i);

myTracker.addNewWrittenKeyToThread(thread,key);
}
}

// No collisions at this point
assertFalse(tracker.detectCollision());

// Now add 3 read keys to thread 0, shared with keys read by threads 1,2,3
for (int i = 0; i < maxThreads-1; i++) {
ByteArrayWrapper key = getKey(i+1,0,i);
myTracker.addNewReadKeyToThread(0,key);
}
// No collisions at this point
assertFalse(tracker.detectCollision());

ByteArrayWrapper readKeyAdded = getKey(1,1,5);

// Now add a single read key to thread 3 that collides with a key written in thread 1
myTracker.addNewReadKeyToThread(3,readKeyAdded);

// Collision must be detected
assertTrue(tracker.detectCollision());

// Now remove that key.
myTracker.removeReadKeyToThread(3,readKeyAdded);

// all back to normal, no collision
assertFalse(tracker.detectCollision());

// Now add a write-write collision
ByteArrayWrapper writeKeyAdded = readKeyAdded; // the same key, but written
// Now add a single read key to thread 3 that collides with a key written in thread 1
myTracker.addNewWrittenKeyToThread(3,writeKeyAdded);

// Collision must be detected
assertTrue(tracker.detectCollision());

myTracker.removeWrittenKeyToThread(3,writeKeyAdded);

// all back to normal, no collision
assertFalse(tracker.detectCollision());

/////////////////////////////////////////////////////////
// Now we'll do the same, but in the opposite direction
// between threads 1 and 3
/////////////////////////////////////////////////////////

readKeyAdded = getKey(3,1,5);

// Now add a single read key to thread 1 that collides with a key written in thread 3
myTracker.addNewReadKeyToThread(1,readKeyAdded);

// Collision must be detected
assertTrue(tracker.detectCollision());

// Now remove that key.
myTracker.removeReadKeyToThread(1,readKeyAdded);

// all back to normal, no collision
assertFalse(tracker.detectCollision());

// Now add a write-write collision
writeKeyAdded = readKeyAdded; // the same key, but written
// Now add a single read key to thread 1 that collides with a key written in thread 3
myTracker.addNewWrittenKeyToThread(1,writeKeyAdded);

// Collision must be detected
assertTrue(tracker.detectCollision());
}

@Test
public void createATrackerShouldHaveEmptyKeysForThisThread() {
assertEquals(0, tracker.getThisThreadReadKeys().size());
Expand Down

0 comments on commit 9d23e67

Please sign in to comment.