Compare commits

...

2 Commits

Author SHA1 Message Date
Mikhail Yevchenko b472274ce2 Fix: remove fallback LLM slop-crap 2026-04-05 18:02:18 +00:00
Mikhail Yevchenko c0d00dead9 Update benchmark results in README with latest data 2026-04-05 18:02:02 +00:00
3 changed files with 46 additions and 74 deletions
+28 -32
View File
@@ -15,7 +15,7 @@ Only the content between the markers below is rewritten, so the rest of this REA
<!-- BENCHMARK_RESULTS_START --> <!-- BENCHMARK_RESULTS_START -->
Last updated: 2026-04-05T17:19:53.068450463Z Last updated: 2026-04-05T17:50:24.432296204Z
### System info ### System info
@@ -31,7 +31,7 @@ Last updated: 2026-04-05T17:19:53.068450463Z
- Benchmark: `com.benchmark.benchmarks.DataAccessBenchmark.readSingleUser` - Benchmark: `com.benchmark.benchmarks.DataAccessBenchmark.readSingleUser`
- Thread count: `12` - Thread count: `12`
- Fixtures in this snapshot: `30` - Fixtures in this snapshot: `26`
### Results ### Results
@@ -39,40 +39,36 @@ Last updated: 2026-04-05T17:19:53.068450463Z
| Rank | Fixture | Score | Error | Unit | | Rank | Fixture | Score | Error | Unit |
|---:|---|---:|---:|---| |---:|---|---:|---:|---|
| 1 | `ikv-store` | 1085.094 | 32.267 | `ops/us` | | 1 | `in-memory` | 1089.340 | 31.288 | `ops/us` |
| 2 | `in-memory` | 1076.857 | 17.298 | `ops/us` | | 2 | `memory-mapped-file` | 79.877 | 2.664 | `ops/us` |
| 3 | `chronicle-map` | 85.276 | 2.529 | `ops/us` | | 3 | `datastore4j` | 62.734 | 2.530 | `ops/us` |
| 4 | `memory-mapped-file` | 79.549 | 1.791 | `ops/us` | | 4 | `leveldb` | 31.035 | 4.986 | `ops/us` |
| 5 | `datastore4j` | 61.163 | 2.313 | `ops/us` | | 5 | `mapdb` | 30.965 | 1.710 | `ops/us` |
| 6 | `leveldb` | 31.796 | 5.871 | `ops/us` | | 6 | `sqlite-jdbc-memory` | 4.250 | 0.107 | `ops/us` |
| 7 | `mapdb` | 28.615 | 6.765 | `ops/us` | | 7 | `lmdb` | 3.350 | 1.844 | `ops/us` |
| 8 | `sqlite-jdbc-memory` | 4.153 | 0.249 | `ops/us` | | 8 | `kryo` | 2.648 | 0.213 | `ops/us` |
| 9 | `lmdb` | 3.115 | 0.864 | `ops/us` | | 9 | `gson` | 2.314 | 0.125 | `ops/us` |
| 10 | `kryo` | 2.549 | 0.150 | `ops/us` | | 10 | `sqlite-jdbc` | 2.032 | 0.320 | `ops/us` |
| 11 | `gson` | 2.154 | 0.183 | `ops/us` | | 11 | `sqlite-ormlite-memory` | 1.215 | 0.049 | `ops/us` |
| 12 | `sqlite-jdbc` | 1.970 | 0.162 | `ops/us` | | 12 | `sqlite-ormlite` | 0.931 | 0.037 | `ops/us` |
| 13 | `sqlite-ormlite-memory` | 1.071 | 0.255 | `ops/us` | | 13 | `duckdb-jdbc` | 0.054 | 0.002 | `ops/us` |
| 14 | `sqlite-ormlite` | 0.886 | 0.039 | `ops/us` |
| 15 | `duckdb-jdbc` | 0.050 | 0.004 | `ops/us` |
#### AverageTime #### AverageTime
| Rank | Fixture | Score | Error | Unit | | Rank | Fixture | Score | Error | Unit |
|---:|---|---:|---:|---| |---:|---|---:|---:|---|
| 1 | `ikv-store` | 0.011 | 0.000 | `us/op` | | 1 | `in-memory` | 0.011 | 0.000 | `us/op` |
| 2 | `in-memory` | 0.011 | 0.000 | `us/op` | | 2 | `memory-mapped-file` | 0.151 | 0.005 | `us/op` |
| 3 | `chronicle-map` | 0.142 | 0.005 | `us/op` | | 3 | `datastore4j` | 0.190 | 0.013 | `us/op` |
| 4 | `memory-mapped-file` | 0.154 | 0.004 | `us/op` | | 4 | `leveldb` | 0.330 | 0.017 | `us/op` |
| 5 | `datastore4j` | 0.204 | 0.010 | `us/op` | | 5 | `mapdb` | 0.583 | 0.066 | `us/op` |
| 6 | `leveldb` | 0.387 | 0.046 | `us/op` | | 6 | `sqlite-jdbc-memory` | 2.885 | 0.233 | `us/op` |
| 7 | `mapdb` | 0.403 | 0.031 | `us/op` | | 7 | `lmdb` | 3.364 | 1.158 | `us/op` |
| 8 | `sqlite-jdbc-memory` | 3.005 | 0.504 | `us/op` | | 8 | `kryo` | 4.503 | 0.211 | `us/op` |
| 9 | `lmdb` | 3.665 | 0.355 | `us/op` | | 9 | `gson` | 5.175 | 0.574 | `us/op` |
| 10 | `kryo` | 4.820 | 0.338 | `us/op` | | 10 | `sqlite-jdbc` | 5.827 | 0.302 | `us/op` |
| 11 | `gson` | 5.416 | 0.368 | `us/op` | | 11 | `sqlite-ormlite-memory` | 9.907 | 0.441 | `us/op` |
| 12 | `sqlite-jdbc` | 6.056 | 0.441 | `us/op` | | 12 | `sqlite-ormlite` | 12.929 | 0.427 | `us/op` |
| 13 | `sqlite-ormlite-memory` | 10.431 | 0.868 | `us/op` | | 13 | `duckdb-jdbc` | 226.375 | 13.410 | `us/op` |
| 14 | `sqlite-ormlite` | 13.394 | 0.376 | `us/op` |
| 15 | `duckdb-jdbc` | 235.873 | 22.582 | `us/op` |
<!-- BENCHMARK_RESULTS_END --> <!-- BENCHMARK_RESULTS_END -->
@@ -8,14 +8,11 @@ import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.ChronicleMapBuilder; import net.openhft.chronicle.map.ChronicleMapBuilder;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
public class ChronicleMapFixture implements DataFixtures { public class ChronicleMapFixture implements DataFixtures {
private ChronicleMap<Long, byte[]> usersById; private ChronicleMap<Long, byte[]> usersById;
private Map<Long, byte[]> fallbackUsersById;
private Kryo kryo; private Kryo kryo;
@Override @Override
@@ -24,11 +21,9 @@ public class ChronicleMapFixture implements DataFixtures {
kryo.setRegistrationRequired(false); kryo.setRegistrationRequired(false);
kryo.register(User.class); kryo.register(User.class);
Map<Long, byte[]> encodedUsers = new HashMap<>(users.size());
int maxValueSize = 1; int maxValueSize = 1;
for (User user : users) { for (User user : users) {
byte[] encoded = serialize(user); byte[] encoded = serialize(user);
encodedUsers.put(user.getId(), encoded);
maxValueSize = Math.max(maxValueSize, encoded.length); maxValueSize = Math.max(maxValueSize, encoded.length);
} }
@@ -40,19 +35,22 @@ public class ChronicleMapFixture implements DataFixtures {
.averageValue(new byte[maxValueSize]) .averageValue(new byte[maxValueSize])
.create(); .create();
for (Map.Entry<Long, byte[]> entry : encodedUsers.entrySet()) { for (User user : users) {
usersById.put(entry.getKey(), entry.getValue()); usersById.put(user.getId(), serialize(user));
} }
fallbackUsersById = null; } catch (Throwable t) {
} catch (Throwable ignored) {
usersById = null; usersById = null;
fallbackUsersById = encodedUsers; throw new IllegalStateException(
"ChronicleMap initialization failed. Cause: "
+ t.getClass().getSimpleName() + " - " + t.getMessage(),
t
);
} }
} }
@Override @Override
public User findById(long id) { public User findById(long id) {
byte[] encoded = usersById != null ? usersById.get(id) : fallbackUsersById.get(id); byte[] encoded = usersById.get(id);
return encoded == null ? null : deserialize(encoded); return encoded == null ? null : deserialize(encoded);
} }
@@ -61,7 +59,6 @@ public class ChronicleMapFixture implements DataFixtures {
if (usersById != null) { if (usersById != null) {
usersById.close(); usersById.close();
} }
fallbackUsersById = null;
} }
private byte[] serialize(User user) { private byte[] serialize(User user) {
@@ -4,17 +4,11 @@ import com.benchmark.model.User;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class IkvStoreFixture implements DataFixtures { public class IkvStoreFixture implements DataFixtures {
private static final AtomicBoolean FALLBACK_WARNING_PRINTED = new AtomicBoolean(false);
private final InMemoryFixture fallback = new InMemoryFixture();
private Object reader; private Object reader;
private Object writer; private Object writer;
private boolean useFallback;
@Override @Override
public void setup(List<User> users) throws Exception { public void setup(List<User> users) throws Exception {
@@ -24,10 +18,10 @@ public class IkvStoreFixture implements DataFixtures {
String mountDirectory = getenv("IKV_MOUNT_DIRECTORY"); String mountDirectory = getenv("IKV_MOUNT_DIRECTORY");
if (accountId == null || accountPassKey == null || storeName == null || mountDirectory == null) { if (accountId == null || accountPassKey == null || storeName == null || mountDirectory == null) {
useFallback = true; throw new IllegalStateException(
fallback.setup(users); "IKV fixture requires IKV_ACCOUNT_ID, IKV_ACCOUNT_PASSKEY, IKV_STORE_NAME, and IKV_MOUNT_DIRECTORY. "
printFallbackWarning("IKV fixture: required env vars missing (IKV_ACCOUNT_ID, IKV_ACCOUNT_PASSKEY, IKV_STORE_NAME, IKV_MOUNT_DIRECTORY). Using in-memory fallback."); + "Results are invalid without a real IKV backend."
return; );
} }
try { try {
@@ -80,25 +74,21 @@ public class IkvStoreFixture implements DataFixtures {
// IKV is eventually consistent for reads. Small delay before measurement starts. // IKV is eventually consistent for reads. Small delay before measurement starts.
Thread.sleep(200); Thread.sleep(200);
useFallback = false;
} catch (Throwable t) { } catch (Throwable t) {
useFallback = true;
fallback.setup(users);
closeQuietly(reader, "shutdownReader"); closeQuietly(reader, "shutdownReader");
closeQuietly(writer, "shutdownWriter"); closeQuietly(writer, "shutdownWriter");
reader = null; reader = null;
writer = null; writer = null;
printFallbackWarning("IKV fixture: initialization failed, using in-memory fallback. Cause: " throw new IllegalStateException(
+ t.getClass().getSimpleName() + " - " + t.getMessage()); "IKV fixture initialization failed. Cause: "
+ t.getClass().getSimpleName() + " - " + t.getMessage(),
t
);
} }
} }
@Override @Override
public User findById(long id) throws Exception { public User findById(long id) throws Exception {
if (useFallback) {
return fallback.findById(id);
}
String key = Long.toString(id); String key = Long.toString(id);
String name = (String) reader.getClass().getMethod("getStringValue", String.class, String.class) String name = (String) reader.getClass().getMethod("getStringValue", String.class, String.class)
.invoke(reader, key, "name"); .invoke(reader, key, "name");
@@ -117,11 +107,6 @@ public class IkvStoreFixture implements DataFixtures {
@Override @Override
public void teardown() throws Exception { public void teardown() throws Exception {
if (useFallback) {
fallback.teardown();
return;
}
closeQuietly(reader, "shutdownReader"); closeQuietly(reader, "shutdownReader");
closeQuietly(writer, "shutdownWriter"); closeQuietly(writer, "shutdownWriter");
reader = null; reader = null;
@@ -143,10 +128,4 @@ public class IkvStoreFixture implements DataFixtures {
// Ignore cleanup issues for benchmark fixture shutdown. // Ignore cleanup issues for benchmark fixture shutdown.
} }
} }
private static void printFallbackWarning(String message) {
if (FALLBACK_WARNING_PRINTED.compareAndSet(false, true)) {
System.out.println(message);
}
}
} }