Skip to content

0-kvspace/2-runtime: shm 零拷贝读写——统一借用接口 + durable 适配 #228

Description

@miaobyte

承接 umbrella #212 第 2/3 项。关联 kvspace#9、kvspace-c#16;参照 kvspace-c#13(shm_set_raw 同尺寸就地覆写,已合)与 #116(跨后端验证范式)。

设计原则(p0/p2/p5)

砍掉所有分支与向后兼容,不做加法式:重定义并删除旧 API,不新增与旧符号并存的东西。每个原语走唯一正确方向,前置条件不满足直接 error,绝不静默"回落"、绝不用 bool/if 包庇两种所有权。durable 无常驻映射,其不可避免的那次拷贝下沉进 frontend 适配层,runtime 侧永不自己拷贝、看到的接口与 shm 一致。

现状

读一个值 = 两次拷贝kvspaceGet 后端 malloc+memcpy + kvlangXvalueCopyMalloc)+ free;写一个标量走 kvspaceSet:runtime 侧 encode 完整 TLV + own 转交 + kvlangKvSet 合并 keys/lens/vals(≈5 malloc + 4 memcpy),即使 shm shm_set_raw 底层同尺寸已就地,这些 runtime 拷贝仍全额付出。shm 数据本在共享 mmap(read_tlv *out=sbo_data+off 即零拷贝指针)。

一、kvspace 代理(frontend + kvspace.h)—— 删旧立新

读:唯一读 = 借用,重定义 kvspaceGet、删拷贝语义

int kvspaceGet(void *h, const char *key, int resolve,
               uint8_t **out, uint32_t *out_len, void **hold);

shm→*out 指向 mmap、*hold=NULL(零拷贝);durable→物化进缓冲、*out=*hold=该缓冲(拷贝下沉、Rust 侧零改动)。释放复用 kvspaceBytesFree(hold,len)(hold=NULL 即 no-op),不发明新符号。旧拷贝签名删除,消费者全迁移。

写:kvspaceSet 拆成两个一等原语,删 kvspaceSetkvspaceXvalueBodyPtr

/* 就地覆写:key 必须已存在、kind 不变、body_len==原 body_len,只改 body raw;
   违反前置条件→非 0 并填 err(绝不静默重分配/回落)。shm 直接 memcpy 进原 box;durable 适配层等价覆写。*/
int kvspaceWriteInPlace(void *h, const char *key, int resolve,
                        const uint8_t *body, uint32_t body_len, char *err, uint32_t err_cap);
/* 新位置写:分配新 box、写完整 TLV(=原 kvspaceSet),用于新建/变 kind/变长。*/
int kvspaceWriteNewPlace(void *h, const char *const *keys, const uint8_t *vals,
                         const uint32_t *lens, uint32_t n, char *err, uint32_t err_cap);

WriteInPlace 封装就地写、不再向 runtime 暴露 mmap 裸指针(取代 kvspaceXvalueBodyPtr);WriteNewPlace = 原 kvspaceSet 改名。

二、kvspace-c

kvspaceShmGet 已零拷贝;写导出 kvspaceWriteInPlace 后端符号(复用 shm_set_raw 同尺寸就地逻辑的 body-only 入口);WriteNewPlace=现有 set。

三、runtime-c —— 借用读 + 二选一写(无 bool、无回落)

  • kvlangXvalue_tvoid *hold(非 bool);Free kvspaceBytesFree(hold,len)(借用 hold=NULL no-op、自持 hold=buffer 释放),消费者侧无 if。
  • 读包装器 KvGetOne/KvWatch 走借用 kvspaceGet,省 CopyMallocKvGetBatch 多值聚合仍 own+hold。
  • 先修悬垂 kvlangBuiltinExecuteCopynw>1 写前物化借用值。
  • kvlangBuiltinWriteResult 按definite条件二选一:目标存在且 kind/长度不变→WriteInPlace(零 encode/合并);否则→WriteNewPlace。判据取自本步刚借用读到的旧 head。

四、runtime-rs

engine.rs get 走借用 + kvspaceBytesFree(hold);写按条件调两原语;ffi.rskvspaceSet/kvspaceXvalueBodyPtr、加两写原语、改 Get 签名。

非目标

多进程并发锁 = 独立 issue:slotsboxmalloc 完全无锁(04_multithread 稳定 FAIL)、零拷贝裸指针+就地 memcpy 并发下有撕裂风险,属既有缺陷、单进程 régime 不触发,补根自旋锁另开(对齐 kvspace-c#13 尾注)。

实施顺序

  1. kvspace-c 导出 WriteInPlace(body-only 就地)。
  2. frontend+头:重定义借用 kvspaceGet、加两写原语、删 kvspaceSet/kvspaceXvalueBodyPtr、装库。
  3. tutorial-c/07_zerocopy.c 对照通过。
  4. runtime-c:hold + 统一 Free + 修 ExecuteCopy + 借用读 + 二选一写。
  5. runtime-rs 同步。
  6. benchmark 复测 + tutorial 237 例三后端全回归。

验证

对照 shm 借用落 mmap 区间/hold==NULL/与拷贝路径 memcmp==0、fs hold!=NULL 且内容一致;对不存在 key/变长调 WriteInPlace 须返回非 0(前置断言生效、不静默成功);tutorial 237×三后端逐字节不变;run.py -k iops 改造前后对比 shm 列落快照。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions