CoralStore Performance Numbers

CoralStore can write a 256-byte message to disk in around 159 nanoseconds through the FileStore implementation. Moreover, by using the AsyncStore you can get even lower latencies (60 nanoseconds) and variance, as the numbers on this article demonstrate.

The machine used for the benchmarks below was an Intel i7 quad-core (4 x 3.50GHz) Ubuntu box overclocked to 4.50Ghz.

FileStore

With a FileStore you can persist all your messages to disk. As the example below demonstrates, a FileStore by itself (i.e. without being asynchronous) is already very fast, but has some outliers as you can see in the 99.9 percentile:

Messages: 900,000 (256 bytes)
Avg Time: 159.06 nanos
Min Time: 47.0 nanos
Max Time: 98.944 micros
75% = [avg: 51.0 nanos, max: 53.0 nanos]
90% = [avg: 51.0 nanos, max: 55.0 nanos]
99% = [avg: 53.0 nanos, max: 174.0 nanos]
99.9% = [avg: 132.0 nanos, max: 25.571 micros]
99.99% = [avg: 155.0 nanos, max: 27.549 micros]
99.999% = [avg: 158.0 nanos, max: 38.035 micros]


AsyncStore

With the AsyncStore you can get blazing fast performance with no outliers as you can see by the results below:

Messages: 900,000 (256 bytes)
Avg Time: 59.84 nanos
Min Time: 41.0 nanos
Max Time: 10.221 micros
75% = [avg: 49.0 nanos, max: 71.0 nanos]
90% = [avg: 54.0 nanos, max: 84.0 nanos]
99% = [avg: 58.0 nanos, max: 176.0 nanos]
99.9% = [avg: 59.0 nanos, max: 388.0 nanos]
99.99% = [avg: 59.0 nanos, max: 476.0 nanos]
99.999% = [avg: 59.0 nanos, max: 1.748 micros]


FileStore Benchmark Source Code

package com.coralblocks.coralstore.bench;

import java.io.IOException;
import java.nio.ByteBuffer;

import com.coralblocks.coralbits.bench.Benchmarker;
import com.coralblocks.coralstore.FileStore;
import com.coralblocks.coralstore.Store;
import com.coralblocks.coralthreads.Affinity;

public class FileBench {
	
	public static void main(String[] args) throws IOException {
		
		// java -server -verbose:gc -cp target/coralstore-all.jar:lib/jna-3.5.1.jar -DdetailedBenchmarker=true -Xms2g -Xmx8g -XX:NewSize=512m -XX:MaxNewSize=1024m com.coralblocks.coralstore.bench.FileBench 256 100000 1000000 2
		
		int msgSize = Integer.parseInt(args[0]);
		int warmup = Integer.parseInt(args[1]);
		int messages = Integer.parseInt(args[2]);
		int procToBind = args.length > 3 ? Integer.parseInt(args[3]) : -1;
		
		byte[] msgBytes = new byte[msgSize];
		// build a dummy message:
		for(int i = 0; i < msgBytes.length; i++) {
			msgBytes[i] = (byte) String.valueOf(i % 10).charAt(0);	
		}
		ByteBuffer msg = ByteBuffer.wrap(msgBytes);
		
		Store store = new FileStore(".", "fileStoreSession");
		
		Benchmarker bench = Benchmarker.create(warmup);
		
		if (procToBind != -1) {
			System.out.println("Using affinity! procToBind=" + procToBind + " available=" + Affinity.isAvailable());
			Affinity.assignToProcessor(procToBind, Thread.currentThread());
			Affinity.bind();
		}
		
		for(int i = 0; i < messages; i++) {
			msg.position(0);
			bench.mark();
			store.addMessage(msg);
			store.flush();
			bench.measure();
		}
		
		store.close();
		
		bench.printResults();
	}
}


AsyncStore Benchmark Source Code

package com.coralblocks.coralstore.bench;

import java.io.IOException;
import java.nio.ByteBuffer;

import com.coralblocks.coralbits.bench.Benchmarker;
import com.coralblocks.coralstore.FileStore;
import com.coralblocks.coralstore.Store;
import com.coralblocks.coralstore.async.AsyncStore;
import com.coralblocks.coralthreads.Affinity;

public class AsyncBench {
	
	public static void main(String[] args) throws IOException, InterruptedException {
		
		// java -server -verbose:gc -cp target/coralstore-all.jar:lib/jna-3.5.1.jar -DdetailedBenchmarker=true -DcoralThreadsVerbose=true -Xms2g -Xmx8g -XX:NewSize=512m -XX:MaxNewSize=1024m com.coralblocks.coralstore.bench.AsyncBench 256 100000 1000000 2 3
		
		int msgSize = Integer.parseInt(args[0]);
		int warmup = Integer.parseInt(args[1]);
		int messages = Integer.parseInt(args[2]);
		int procToBind = args.length > 3 ? Integer.parseInt(args[3]) : -1;
		int procToBindAsync = args.length > 4 ? Integer.parseInt(args[4]) : -1;
		
		byte[] msgBytes = new byte[msgSize];
		// build a dummy message:
		for(int i = 0; i < msgBytes.length; i++) {
			msgBytes[i] = (byte) String.valueOf(i % 10).charAt(0);	
		}
		ByteBuffer msg = ByteBuffer.wrap(msgBytes);
		
		Store store = new FileStore(".", "asyncStoreSession");
		AsyncStore asyncStore = new AsyncStore(store, msgSize, procToBindAsync);
		
		Benchmarker bench = Benchmarker.create(warmup);
		
		if (procToBind != -1) {
			Affinity.assignToProcessor(procToBind, Thread.currentThread());
			Affinity.bind();
		}
		
		for(int i = 0; i < messages; i++) {
			msg.position(0);
			bench.mark();
			asyncStore.addMessage(msg);
			asyncStore.flush();
			bench.measure();
			
			if ((i + 1) % AsyncStore.getQueueCapacity() == 0) {
				// avoid queue contention because we are measuring latency, not throughput
				asyncStore.drainAndWait();
			}
		}
		
		asyncStore.discard();
		
		bench.printResults();
	}
}


Conclusion

CoralStore delivers blazing fast performance with very low latency and variance. You can persist messages in 70 nanoseconds on average.