[ISSUE #10334] Support native CqCompactionFilter with cross-platform JNI shim#10335
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #10335 +/- ##
=============================================
- Coverage 48.97% 48.89% -0.09%
+ Complexity 13472 13455 -17
=============================================
Files 1375 1376 +1
Lines 100452 100547 +95
Branches 12973 12984 +11
=============================================
- Hits 49193 49159 -34
- Misses 45267 45378 +111
- Partials 5992 6010 +18 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
4e18a29 to
79a9006
Compare
|
@lizhanhui @leizhiyuan Please help review this pr |
|
意见 1: loadNativeShim 未捕获 UnsatisfiedLinkError + 缺少 ARM 架构 shim 问题: loadNativeShim() 中 System.load() 调用可能抛出 UnsatisfiedLinkError(例如在 Linux aarch64 上加载 x86-64 的 .so),但当前只捕获了 IOException。由于该方法在 static {} 块中调用,未捕获的 UnsatisfiedLinkError 当前打包的原生库只有:
这意味着在 Linux aarch64(云环境中非常常见)加载必然失败,且由于缺少 UnsatisfiedLinkError 的捕获,不会优雅降级,而是直接崩溃。 建议修复:
System.load(tempLib.getAbsolutePath());
loaded = true;
log.info("[CqCompactionFilterJni] Native library loaded from classpath: {}", tempLib.getAbsolutePath());
} catch (IOException e) {
log.error("[CqCompactionFilterJni] Failed to load native shim", e);
} catch (UnsatisfiedLinkError e) {
log.error("[CqCompactionFilterJni] Failed to load native shim library, "
+ "platform may not be supported: {}", e.getMessage());
}
──────────────────────────────────────────────────────────────────────────────── EnglishIssue: System.load() in loadNativeShim() can throw UnsatisfiedLinkError (e.g., when loading an x86-64 .so on Linux aarch64), but only IOException is caught. Since this method is called from a static {} initializer, The bundled native libraries currently only cover:
This means on Linux aarch64 (very common in cloud environments) and macOS x86_64, loading will inevitably fail, and without catching UnsatisfiedLinkError, the system won't degrade gracefully — it will crash. Suggested fix:
System.load(tempLib.getAbsolutePath());
loaded = true;
log.info("[CqCompactionFilterJni] Native library loaded from classpath: {}", tempLib.getAbsolutePath());
} catch (IOException e) {
log.error("[CqCompactionFilterJni] Failed to load native shim", e);
} catch (UnsatisfiedLinkError e) {
log.error("[CqCompactionFilterJni] Failed to load native shim library, "
+ "platform may not be supported: {}", e.getMessage());
}
──────────────────────────────────────────────────────────────────────────────── 问题: setMinPhyOffset() 方法在每次调用时以 INFO 级别记录日志。该方法由 cleanExpired() 周期性触发(通常每隔几秒到几十秒一次),在生产环境中会产生大量重复日志,增加日志存储压力且淹没真正有价值的信息。 建议修复: 将日志级别改为 DEBUG: public static void setMinPhyOffset(long minPhyOffset) {
long ptr = NATIVE_FILTER_PTR.get();
if (ptr != 0) {
setMinPhyOffset0(ptr, minPhyOffset);
log.debug("CqCompactionFilter setMinPhyOffset={}", minPhyOffset);
}
}──────────────────────────────────────────────────────────────────────────────── Issue: setMinPhyOffset() logs at INFO level on every invocation. This method is called periodically by cleanExpired() (typically every few seconds), which produces high-volume repetitive log output in production, Suggested fix: Change the log level to DEBUG: public static void setMinPhyOffset(long minPhyOffset) {
long ptr = NATIVE_FILTER_PTR.get();
if (ptr != 0) {
setMinPhyOffset0(ptr, minPhyOffset);
log.debug("CqCompactionFilter setMinPhyOffset={}", minPhyOffset);
}
} |
|
Re: Already added support for the ARM platform, the size of this log is small. |
…him for Linux The original commit only bundled libcq_compaction_filter.so for x86_64. Add libcq_compaction_filter_aarch64.so and update CqCompactionFilterJni.java to select the correct native library based on os.arch on Linux.
996ca04 to
8d5f975
Compare
…library crash The JaCoCo agent conflicts with dynamically loaded native libraries (libcq_compaction_filter) during JVM shutdown, causing "forked VM terminated without properly saying goodbye" on macOS. Coverage is already collected by the dedicated coverage.yml workflow on Linux. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rm JaCoCo skip The previous inline expression was split incorrectly on Windows, causing Maven to receive ".skip=true" as a separate argument. Use explicit bash shell with a conditional variable instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
about: #10334
Summary
CqCompactionFilterJNI shim for ConsumeQueue compaction, supporting Linux, macOS (x86_64/aarch64), and Windows platformsConsumeQueueCompactionFilterFactorywith a native compaction filter that runs entirely in RocksDB's C++ compaction threads, avoiding JNI callback overhead per keymanualCompactionlogging withestimateNumKeysbefore/after and reduction ratiominPhyOffsetparameter fromAbstractRocksDBStorage.manualCompactionMotivation
The existing Java
CompactionFilterFactorycreates aRemoveConsumeQueueCompactionFilterper compaction job, which incurs JNI cross-boundary calls for every key during compaction. For ConsumeQueue databases with millions of entries, this overhead is significant.A native C++ compaction filter:
minPhyOffsetthreshold updated from Java via a single JNI callChanges
CqCompactionFilterJni.java— JNI loader with platform detection, RocksDB native library co-location forDT_NEEDED/LC_LOAD_DYLIBresolutionNativeCqCompactionFilter.java— Thin wrapper withdisOwnNativeHandle()to prevent use-after-free when options close before DBcq_compaction_filter.cpp— Native C++ filter implementation withstd::atomic<int64_t>threshold and JNI exportslibcq_compaction_filter.so(Linux),.dylib(macOS)AbstractRocksDBStorage— Enhanced compaction logging, removed unusedminPhyOffsetparamConsumeQueueRocksDBStorage— Integrates native filter on startup with graceful fallbackdocs/en/Native_RocksDB.md— Build instructions for all platformsTest Plan
CqCompactionFilterJniTest— verifies native library loading, filter creation, minPhyOffset update, and actual compaction filteringConsumeQueueRocksDBStorageintegration tests passCloses #10334