性能与可靠性近期变更
本文汇总最近一天 SonnetDB.Core 的主要工程变更,便于评审、测试和发布说明复核。重点集中在热路径降分配、读多写少快照、Segment v6 格式整合、WAL/Checkpoint 崩溃恢复,以及可持续的 analyzer 治理。
写入与 MemTable
MemTable.EstimatedBytes、MinTimestamp、MaxTimestamp改为由Append、WAL replay 和 flush reset 生命周期增量维护,ShouldFlush不再遍历全部 series。MemTableSeries在 append 字符串字段时增量累加 UTF-8 byte count,避免EstimatedBytes每次全量扫描并重复调用Encoding.UTF8.GetByteCount。MemTableSeries增加快照缓存与 immutable snapshot swap 思路:无追加且数据已排序时,重复Snapshot/range 查询复用已排序快照,并避免暴露可变内部数组。SnapshotRange在有序数据上先二分命中区间,只复制范围内点,保持空范围、单点和 inclusive 边界语义。- 读写并发路径改为减少查询长时间持锁,
Snapshot/TryGetAggregate不再长期阻塞 append。
SegmentReader 与查询热路径
SegmentReader.Open构建只读SeriesId -> BlockDescriptor[]内存索引,FindBySeries和FindBySeriesAndField不再线性扫描所有 block。- 增加按时间范围查找 block 的内存索引,保留 block 顺序稳定、重叠区间和 inclusive 边界语义。
QueryEngine.BuildReaderMap与SegmentManager的 Readers/Index 绑定快照关联,snapshot 未变化时复用 reader map;segment add、compaction swap 和 dispose 会发布新快照以避免使用过期 reader。QueryEngine.Execute(PointQuery)的 tombstone 过滤热路径去除 LINQWhere,改为手写迭代器,并对 tombstone 时间窗做预筛。SegmentReader增加 block 解码 LRU 缓存,key 包含(SegmentId, BlockIndex, Crc32),缓存值为解码后的点数组,Dispose 时释放引用。- 新增可选 mmap 读取路径,用 safe-only
MemoryMappedViewAccessor读取大 segment,默认 byte[] reader 仍作为回退。
编码与解码专用化
TimestampCodec增加直接把 delta-of-delta 时间戳写入DataPoint目标视图的重载。ValuePayloadCodecV2新增全量与范围DecodeInto路径,直接填充已有时间戳的DataPoint目标视图。BlockDecoder对 V2 全量和范围解码走手写 fast path,避免中间long[]/FieldValue[]分配。CodecSpecializationBenchmark对比旧组合式解码与生产快路径。短跑结果显示 V2 全量生产路径分配从约1984 KB降至约1024 KB,V2 range 分配降至约128 KB。
窗口函数与聚合
- 窗口函数执行接口增加 typed evaluator,优先支持 double 路径,减少
object?[]与逐行装箱。 - 新增流式窗口状态接口,
SelectExecutor可按 row/chunk 推进窗口计算,旧接口保留适配层。 moving_average、running_sum、running_min、running_max等内部实现改为ReadOnlySpan/Span批量处理,减少临时数组。- 数值聚合
sum/min/max/count增加可选 SIMD 快路径,使用System.Numerics.Vector<T>,不支持硬件加速或语义不适合时自动回退标量。 - 扩展聚合快路径新增 TDigest 与 HyperLogLog sketch,v6 新段内嵌 sketch section,旧
.SDBAIDXsidecar 仍可按需回退读取。
Segment v6 与向量索引
- Segment 写入版本升级到 v6,把原先为保持 v5 而外置的 HNSW
.SDBVIDX与扩展聚合.SDBAIDX内容整合进.SDBSEGextension section。 SegmentHeader保留区写入 mini-footer 摘要副本,包含 IndexCount、IndexOffset、FileLength 与 IndexCrc32,用于尾部损坏时诊断与受控 fallback。SegmentReader继续兼容 v4/v5 段文件,并保留旧 sidecar 懒加载回退路径。- HNSW vector index 不再在
Open时 eager 加载,而是在TryGetVectorIndex时按需加载,并受统一 LRU 预算控制。
WAL、Checkpoint 与 Tombstone
- 新写入 WAL record 在不改变 32 字节 header 尺寸的前提下启用 header checksum,增强 torn-write 检测;旧 WAL record 继续兼容读取。
- Replay 遇到第一条坏 record 会停止并忽略尾部,覆盖 header 截断、payload 截断、长度字段损坏和 CRC 错误。
- Checkpoint LSN 持久化改为 tmp 写入、flush、原子 rename,并在可用平台 best-effort flush 父目录。恢复时只有对应 segment 文件存在且长度匹配才采用 checkpoint。
- Tombstone manifest 增加周期性 checkpoint,可按删除数量或时间间隔保存快照,降低大量删除后崩溃恢复对 WAL 全量 replay 的依赖。
WalSegmentSet.ReplayWithCheckpoint改为单遍扫描,并利用 WAL segmentLastLsn元数据跳过 checkpoint 之前的整段。
Catalog、配置与 Analyzer
- 启动后读多写少的
SeriesCatalog、MeasurementCatalog、MeasurementSchema和TagInvertedIndex改为发布FrozenDictionary/FrozenSet快照,写入更新时原子替换。 - Options/config 类型改为
sealed record与 init-only 属性,保留对象初始化器兼容,并通过值语义减少运行时共享配置被修改带来的并发不确定性。 - SQL Lexer 的空白、标识符、数字、duration 后缀与运算符判断改为
SearchValues<char>ASCII 快路径,并保留 Unicode fallback。 SonnetDB.Core增加低噪声性能 analyzer 配置,覆盖热路径 LINQ、重复分配、Count/Any、Dictionary 查询、SearchValues与字符串比较建议;新增 warning 命中点均通过代码修复,无 suppress。
诊断能力
Tsdb.Dispose中 final flush 失败仍保持不抛异常,但会写入Tsdb.LastError并触发Tsdb.DiagnosticEvent。- 诊断事件订阅者抛错不会影响关闭语义,测试可以观测 LastError/DiagnosticEvent。
验证建议
建议发布前至少运行:
dotnet build SonnetDB.slnx
dotnet test SonnetDB.slnx --configuration Release --no-build
dotnet run -c Release --project tests\SonnetDB.Benchmarks\SonnetDB.Benchmarks.csproj -- --filter *CodecSpecialization*
连接器验证依赖 CMake、C/C++ 编译器、.NET NativeAOT 工具链和 JDK。Windows x64 推荐:
cmake -S connectors/c --preset windows-x64
cmake --build artifacts/connectors/c/win-x64 --config Release
.\artifacts\connectors\c\win-x64\Release\sonnetdb_quickstart.exe
cmake -S connectors/java --preset windows-x64
cmake --build artifacts/connectors/java/windows-x64 --config Release
cmake --build artifacts/connectors/java/windows-x64 --target run_sonnetdb_java_quickstart --config Release
cmake --build artifacts/connectors/java/windows-x64 --target run_sonnetdb_java_quickstart_ffm --config Release