2

2023-18: 将 OpenDAL KV 性能提升 1000%

 1 year ago
source link: https://xuanwo.io/reports/2023-18/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

2023-18: 将 OpenDAL KV 性能提升 1000%

这期周报分享一个 OpenDAL 的低垂果实:通过去除额外的复制开销将 OpenDAL KV 性能提升 1000%!

OpenDAL 在很久之前增加了 Kv Adapter:通过将 Key-Value 存储后端的常用 GET/SET 操作抽象出来以大幅度简化对接一个 kv service 的成本。维护者需要简单的实现 GET/SET/DELETE 等函数就能够对接形如 Redis/HashMap 这样的存储后端:

#[async_trait]
pub trait Adapter: Send + Sync + Debug + Unpin + 'static {
    async fn get(&self, path: &str) -> Result<Option<Vec<u8>>>;

    async fn set(&self, path: &str, value: &[u8]) -> Result<()>;

    async fn delete(&self, path: &str) -> Result<()>;
}

但是对于纯内存的数据结构来说,Kv Adapter 并不是零开销的:

  • 写入的时候需要对数据进行额外的多次复制
  • 读取时需要将所有的数据都复制出来

不仅如此,现在的 Kv Adapter 只能存储字节流,无法存储额外的 metadata,使得其使用场景受到了不应该的限制。

Issue kv: Use Bytes as value to avoid copy between read/write 提出可以在 map 中存储 Bytes 而不是 Vec<u8> 来避免额外的复制,而 Alternative implementation for memory backend 则更进一步的指出我们可以在 map 中存储一个自定义的数据结构,里面可以附加上的 metadata。

结合以上两个思路,我提出了新的 Typed Kv Adapter

#[derive(Debug, Clone)]
pub struct Value {
    pub metadata: Metadata,
    pub value: Bytes,
}

#[async_trait]
pub trait Adapter: Send + Sync + Debug + Unpin + 'static {
    async fn get(&self, path: &str) -> Result<Option<Value>>;

    async fn set(&self, path: &str, value: Value) -> Result<()>;

    async fn delete(&self, path: &str) -> Result<()>;
}

在数据结构中引入自行设计的 Value 结构体,存储支持零开销复制的 Bytes 而不是 Vec<u8>,使得我们的 Adapter 不需要额外的复制就能够读写数据。

迁移 moka

将一个 service 从 kv::Adapter 迁移至 typed_kv::Adapter 非常简单,我们只需要将其定义声明修改即可:

- inner: SegmentedCache<String, Vec<u8>>,
+ inner: SegmentedCache<String, typed_kv::Value>,

然后修改对应 Adapter 的接口,比如:

- async fn get(&self, path: &str) -> Result<Option<Vec<u8>>>
+ async fn get(&self, path: &str) -> Result<Option<typed_kv::Value>>

在演示 PR 中,我将 moka 从 kv::Adapter 迁移到了 typed_kv::Adapter。在所有的基准测试中,读写性能都有了显著提高。其中,最低的 read 提升了 10%,最高的提升达到了 1519.8%;write 部分受益于零开销实现的 Bytes 类型,在 service_moka_write_once/16.0 MiB 上取得了 166323% 的性能提升。

下一步计划

接下来,OpenDAL 将把所有的内存后端迁移到 typed_kv::Adapter,并增加更多的 kv 后端支持。然后可以进行一次横向的 bytes 读写性能比较,看看在 OpenDAL 的标准使用场景下,看看哪个内存后端性能更强~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK