Add DataStore4J and LevelDB benchmark fixtures
This commit is contained in:
@@ -15,7 +15,7 @@ Only the content between the markers below is rewritten, so the rest of this REA
|
||||
|
||||
<!-- BENCHMARK_RESULTS_START -->
|
||||
|
||||
Last updated: 2026-04-05T15:49:01.412343645Z
|
||||
Last updated: 2026-04-05T16:53:23.606653992Z
|
||||
|
||||
### System info
|
||||
|
||||
@@ -31,7 +31,7 @@ Last updated: 2026-04-05T15:49:01.412343645Z
|
||||
|
||||
- Benchmark: `com.benchmark.benchmarks.DataAccessBenchmark.readSingleUser`
|
||||
- Thread count: `12`
|
||||
- Fixtures in this snapshot: `24`
|
||||
- Fixtures in this snapshot: `28`
|
||||
|
||||
### Results
|
||||
|
||||
@@ -39,34 +39,38 @@ Last updated: 2026-04-05T15:49:01.412343645Z
|
||||
|
||||
| Rank | Fixture | Score | Error | Unit |
|
||||
|---:|---|---:|---:|---|
|
||||
| 1 | `in-memory` | 1075.880 | 31.733 | `ops/us` |
|
||||
| 2 | `chronicle-map` | 85.407 | 3.388 | `ops/us` |
|
||||
| 3 | `memory-mapped-file` | 79.393 | 1.957 | `ops/us` |
|
||||
| 4 | `mapdb` | 25.647 | 2.140 | `ops/us` |
|
||||
| 5 | `sqlite-jdbc-memory` | 3.992 | 0.195 | `ops/us` |
|
||||
| 6 | `lmdb` | 3.300 | 1.325 | `ops/us` |
|
||||
| 7 | `kryo` | 2.425 | 0.168 | `ops/us` |
|
||||
| 8 | `gson` | 2.159 | 0.080 | `ops/us` |
|
||||
| 9 | `sqlite-jdbc` | 1.932 | 0.181 | `ops/us` |
|
||||
| 10 | `sqlite-ormlite-memory` | 1.118 | 0.164 | `ops/us` |
|
||||
| 11 | `sqlite-ormlite` | 0.864 | 0.049 | `ops/us` |
|
||||
| 12 | `duckdb-jdbc` | 0.048 | 0.006 | `ops/us` |
|
||||
| 1 | `in-memory` | 1071.748 | 51.460 | `ops/us` |
|
||||
| 2 | `chronicle-map` | 84.556 | 5.034 | `ops/us` |
|
||||
| 3 | `memory-mapped-file` | 78.969 | 1.996 | `ops/us` |
|
||||
| 4 | `datastore4j` | 58.406 | 2.794 | `ops/us` |
|
||||
| 5 | `leveldb` | 32.387 | 5.570 | `ops/us` |
|
||||
| 6 | `mapdb` | 29.448 | 1.222 | `ops/us` |
|
||||
| 7 | `sqlite-jdbc-memory` | 3.847 | 0.463 | `ops/us` |
|
||||
| 8 | `lmdb` | 3.210 | 0.725 | `ops/us` |
|
||||
| 9 | `kryo` | 2.463 | 0.130 | `ops/us` |
|
||||
| 10 | `gson` | 2.198 | 0.057 | `ops/us` |
|
||||
| 11 | `sqlite-jdbc` | 1.862 | 0.492 | `ops/us` |
|
||||
| 12 | `sqlite-ormlite-memory` | 1.018 | 0.347 | `ops/us` |
|
||||
| 13 | `sqlite-ormlite` | 0.835 | 0.279 | `ops/us` |
|
||||
| 14 | `duckdb-jdbc` | 0.048 | 0.007 | `ops/us` |
|
||||
|
||||
#### AverageTime
|
||||
|
||||
| Rank | Fixture | Score | Error | Unit |
|
||||
|---:|---|---:|---:|---|
|
||||
| 1 | `in-memory` | 0.011 | 0.001 | `us/op` |
|
||||
| 2 | `chronicle-map` | 0.143 | 0.007 | `us/op` |
|
||||
| 3 | `memory-mapped-file` | 0.154 | 0.004 | `us/op` |
|
||||
| 4 | `mapdb` | 0.475 | 0.031 | `us/op` |
|
||||
| 5 | `sqlite-jdbc-memory` | 3.093 | 0.154 | `us/op` |
|
||||
| 6 | `lmdb` | 3.757 | 0.868 | `us/op` |
|
||||
| 7 | `kryo` | 4.841 | 0.610 | `us/op` |
|
||||
| 8 | `gson` | 5.561 | 0.416 | `us/op` |
|
||||
| 9 | `sqlite-jdbc` | 6.192 | 0.496 | `us/op` |
|
||||
| 10 | `sqlite-ormlite-memory` | 10.528 | 0.626 | `us/op` |
|
||||
| 11 | `sqlite-ormlite` | 13.744 | 1.040 | `us/op` |
|
||||
| 12 | `duckdb-jdbc` | 255.975 | 30.802 | `us/op` |
|
||||
| 1 | `in-memory` | 0.012 | 0.001 | `us/op` |
|
||||
| 2 | `chronicle-map` | 0.150 | 0.017 | `us/op` |
|
||||
| 3 | `memory-mapped-file` | 0.155 | 0.008 | `us/op` |
|
||||
| 4 | `datastore4j` | 0.228 | 0.016 | `us/op` |
|
||||
| 5 | `leveldb` | 0.288 | 0.018 | `us/op` |
|
||||
| 6 | `mapdb` | 0.481 | 0.032 | `us/op` |
|
||||
| 7 | `sqlite-jdbc-memory` | 2.964 | 0.191 | `us/op` |
|
||||
| 8 | `lmdb` | 3.708 | 1.615 | `us/op` |
|
||||
| 9 | `kryo` | 4.834 | 0.863 | `us/op` |
|
||||
| 10 | `gson` | 5.592 | 0.253 | `us/op` |
|
||||
| 11 | `sqlite-jdbc` | 6.108 | 0.397 | `us/op` |
|
||||
| 12 | `sqlite-ormlite-memory` | 10.541 | 0.393 | `us/op` |
|
||||
| 13 | `sqlite-ormlite` | 17.532 | 7.855 | `us/op` |
|
||||
| 14 | `duckdb-jdbc` | 339.471 | 181.558 | `us/op` |
|
||||
|
||||
<!-- BENCHMARK_RESULTS_END -->
|
||||
|
||||
@@ -87,11 +87,30 @@
|
||||
<version>1.5.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- DataStore4J -->
|
||||
<dependency>
|
||||
<groupId>io.github.theuntamed839</groupId>
|
||||
<artifactId>DataStore4J</artifactId>
|
||||
<version>0.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- LevelDB (Java port) -->
|
||||
<dependency>
|
||||
<groupId>org.iq80.leveldb</groupId>
|
||||
<artifactId>leveldb-api</artifactId>
|
||||
<version>0.12</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.iq80.leveldb</groupId>
|
||||
<artifactId>leveldb</artifactId>
|
||||
<version>0.12</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Silence SLF4J "no binding" warning -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-nop</artifactId>
|
||||
<version>2.0.17</version>
|
||||
<version>2.1.0-alpha1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -20,6 +20,8 @@ public class DataAccessBenchmark {
|
||||
@Param({
|
||||
"in-memory",
|
||||
"memory-mapped-file",
|
||||
"datastore4j",
|
||||
"leveldb",
|
||||
"lmdb",
|
||||
"mapdb",
|
||||
"duckdb-jdbc",
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.benchmark.fixtures;
|
||||
|
||||
import com.benchmark.model.User;
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
import io.github.theuntamed839.datastore4j.db.DB;
|
||||
import io.github.theuntamed839.datastore4j.db.DataStore4J;
|
||||
import io.github.theuntamed839.datastore4j.db.DbOptions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class DataStore4jFixture implements DataFixtures {
|
||||
|
||||
private DB db;
|
||||
private Kryo kryo;
|
||||
private Path dbDir;
|
||||
|
||||
@Override
|
||||
public void setup(List<User> users) throws Exception {
|
||||
kryo = new Kryo();
|
||||
kryo.setRegistrationRequired(false);
|
||||
kryo.register(User.class);
|
||||
|
||||
dbDir = Files.createTempDirectory("benchmark-datastore4j-");
|
||||
DbOptions options = new DbOptions();
|
||||
db = new DataStore4J(dbDir, options);
|
||||
|
||||
for (User user : users) {
|
||||
db.put(toKey(user.getId()), serialize(user));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User findById(long id) throws Exception {
|
||||
byte[] bytes = db.get(toKey(id));
|
||||
return bytes == null ? null : deserialize(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teardown() throws Exception {
|
||||
if (db != null) {
|
||||
db.close();
|
||||
}
|
||||
if (dbDir != null && Files.exists(dbDir)) {
|
||||
Files.walk(dbDir)
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.forEach(path -> path.toFile().delete());
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] toKey(long id) {
|
||||
return ByteBuffer.allocate(Long.BYTES)
|
||||
.order(ByteOrder.BIG_ENDIAN)
|
||||
.putLong(id)
|
||||
.array();
|
||||
}
|
||||
|
||||
private byte[] serialize(User user) {
|
||||
Output output = new Output(256, -1);
|
||||
kryo.writeObject(output, user);
|
||||
byte[] bytes = output.toBytes();
|
||||
output.close();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private User deserialize(byte[] bytes) {
|
||||
try (Input input = new Input(bytes)) {
|
||||
return kryo.readObject(input, User.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ public class FixtureFactory {
|
||||
return switch (type) {
|
||||
case "in-memory" -> new InMemoryFixture();
|
||||
case "memory-mapped-file" -> new MemoryMappedFileFixture();
|
||||
case "datastore4j" -> new DataStore4jFixture();
|
||||
case "leveldb" -> new LevelDbFixture();
|
||||
case "lmdb" -> new LmdbFixture();
|
||||
case "mapdb" -> new MapDbFixture();
|
||||
case "duckdb-jdbc" -> new DuckDbJdbcFixture();
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.benchmark.fixtures;
|
||||
|
||||
import com.benchmark.model.User;
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
import org.iq80.leveldb.DB;
|
||||
import org.iq80.leveldb.Options;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
|
||||
|
||||
public class LevelDbFixture implements DataFixtures {
|
||||
|
||||
private DB db;
|
||||
private Kryo kryo;
|
||||
private Path dbDir;
|
||||
|
||||
@Override
|
||||
public void setup(List<User> users) throws IOException {
|
||||
kryo = new Kryo();
|
||||
kryo.setRegistrationRequired(false);
|
||||
kryo.register(User.class);
|
||||
|
||||
dbDir = Files.createTempDirectory("benchmark-leveldb-");
|
||||
Options options = new Options();
|
||||
options.createIfMissing(true);
|
||||
db = factory.open(dbDir.toFile(), options);
|
||||
|
||||
for (User user : users) {
|
||||
db.put(toKey(user.getId()), serialize(user));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User findById(long id) {
|
||||
byte[] bytes = db.get(toKey(id));
|
||||
return bytes == null ? null : deserialize(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teardown() throws IOException {
|
||||
if (db != null) {
|
||||
db.close();
|
||||
}
|
||||
if (dbDir != null && Files.exists(dbDir)) {
|
||||
Files.walk(dbDir)
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.forEach(path -> path.toFile().delete());
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] toKey(long id) {
|
||||
return ByteBuffer.allocate(Long.BYTES)
|
||||
.order(ByteOrder.BIG_ENDIAN)
|
||||
.putLong(id)
|
||||
.array();
|
||||
}
|
||||
|
||||
private byte[] serialize(User user) {
|
||||
Output output = new Output(256, -1);
|
||||
kryo.writeObject(output, user);
|
||||
byte[] bytes = output.toBytes();
|
||||
output.close();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private User deserialize(byte[] bytes) {
|
||||
try (Input input = new Input(bytes)) {
|
||||
return kryo.readObject(input, User.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user