[论文笔记] XRP: In-Kernel Storage Functions with eBPF

news2024/11/15 8:03:35

XRP: In-Kernel Storage Functions with eBPF

XRP: 利用 eBPF 的核内存储函数 [Paper] [Slides] [Code]
OSDI’22

摘要

提出了 XRP, 一个允许应用程序从 NVMe 驱动程序中的 eBPF 钩子(hook)执行用户定义的存储函数(例如索引查找或聚合)的框架, 可以安全地绕过大部分内核的存储栈.

1 介绍

随着新的高性能存储技术的兴起, 新的 NVMe 存储设备现在可以实现很高的性能, 内核存储栈成为延迟和开销的主要来源.

现有的解决方案偏激进, 需要侵入式应用程序级的更改或新的硬件.

本文旨在寻求一种易于部署的机制, 可以提供对新兴快速存储设备的快速访问, 而使用现有内核和文件系统时, 无需专门的硬件或对应用程序进行重大更改.
依靠 BPF (Berkeley Packet Filter): 允许应用程序将简单的函数 offload (卸载) 到 Linux 内核, 可消除内核-用户态跨越和上下文切换的开销; 同时操作系统支持, 可以保证隔离性和利用率.

  • Def: I/O 的重提交(resubmission): 需要与其他并发应用程序级操作同步或需要多个函数调用来遍历大型磁盘数据结构的工作负载模式.

使用 BPF 的挑战: 重提交所需的状态在较低层不可用.

本文设计实现了 XRP (eXpress Resubmission Path), 一个使用 Linux eBPF 的高性能存储数据路径.

  • XPR 通过在 NVMe 驱动的中断处理程序中使用钩子来绕过内核存储栈, 以最大提高性能.
  • XRP 的关键挑战是底层 NVMe 驱动程序缺乏高层提供的上下文.
  • 只聚焦 XRP 于一个文件内的操作和在磁盘上具有固定布局的数据结构, 从而 NVMe 驱动程序只需最少量的可由文件系统传递的文件系统映射状态(称为元数据摘要), 使得可以安全执行 I/O 重提交.

本文题提出了 XPR 在 Linux 上的设计和实现, 支持 ext4; 并用 XPR 扩充了 BPF-KV 和 WiredTiger 两个键值存储.

文章贡献:

  1. 新的数据路径. XRP 是第一个支持使用 BPF 将存储函数 offload 到内核的数据路径.
  2. 性能. 与普通系统调用相比, XRP 将 B-树查找的吞吐量提高了 2.5 倍.
  3. 利用率. XRP 提供接近内核旁路的延迟, 但允许内核被相同的线程和进程高效地共享.
  4. 可扩展性. XRP 支持不同的存储用例, 包括不同的数据结构和存储操作(例如, 索引遍历、范围查询、聚合).

2 背景和动机

2.1 软件现在是存储的瓶颈

访问新的 NVMe 存储设备时, 内核存储栈正成为主要的性能瓶颈.
在这里插入图片描述
时间都去哪儿了? 总软件开销占平均延迟的 48.6%.
在这里插入图片描述
为什么不直接绕过内核? 安全问题(用户有对设备的完全访问权限) 和利用率问题(必须轮询设备完成队列, 内核不能共享, 多个轮询线程带来 CPU 争用).

2.2 BPF 入门

BPF (Berkeley Packet Filter) 是一个接口, 允许用户 offload 一个简单的函数由内核执行. Linux 的 BPF 框架称为 eBPF (extended BPF, 扩展BPF).

eBPF 函数在安装时由内核验证以确保安全, 验证后就可以正常被调用.

2.3 BPF 的潜在效益

BPF 可以避免内核空间和用户空间之间的数据移动,当逻辑查找需要一系列会生成应用程序不直接需要的中间数据的"辅助" I/O 请求时.

在辅助 I/O 工作负载中重提交(分派) I/O 的 BPF 函数可以放置在内核的任何层 (如系统调用层、NVMe 驱动层).
在这里插入图片描述

最佳案例加速. XRP 的重提交钩子应驻留在 NVMe 驱动程序中.

io_uring 如何? io_uring 允许进程提交批量异步 I/O 请求, 但每个 I/O 仍会带来完整的存储栈开销. BPF I/O 重提交很大程度上是对 io_uring 的补充: io_uring 提交一批 I/O 触发内核中 BPF 管理的不同 I/O 链.

BPF 可以使传统的读取和 io_uring 系统调用受益.

3 设计挑战和原则

从缺少文件系统层上下文的 NVMe 中断处理程序中执行重提交的两大挑战:

挑战 1: 地址转换和安全. NVMe 驱动程序无法访问文件系统元数据. BPF 函数可以访问设备上的任何块, 即使是属于用户无访问权限的文件.

挑战2: 并发和缓存. 文件系统发出的写入只会反映在页面缓存中, XRP 不可见. 与读取请求同时发出的修改数据结构布局的写入可能导致 XRP 意外获取错误数据. 可以通过加锁解决, 但在 NVMe 中断处理程序中访问锁开销过大.

观察: 大多数磁盘上的数据结构是稳定的. 许多存储引擎的文件保持相对稳定: 有些数据结构不会就地修改磁盘上的存储结构; 文件区段(extent)长时间保持稳定. 使得可以在 NVMe 驱动中缓存文件系统元数据.

设计原则:

  • 一次一个文件: XRP 仅在单个文件上发布链式重提交.
  • 稳定的数据结构: XRP 以布局 (即指针) 长时间内保持不变的数据结构为目标.
  • 用户管理的缓存: XRP 没有页面缓存的接口.
  • 慢路径回退: XRP 尽力而为, 失败时重试或回退.

4 XBR 的设计与实现

4.1 重提交逻辑

XRP 的核心: 用重提交逻辑扩充 NVMe 中断处理程序.
重提交逻辑组成: BPF 钩子; 文件系统转换步骤; 在新物理偏移处构造和重提交下一个 NVMe 请求.
在这里插入图片描述

重提交逻辑:

  1. NVMe 请求完成时, 设备生成中断, 使内核上下文切换到中断处理程序.
  2. 对于中断上下文中完成的每个 NVMe 请求, XRP 调用其关联的 BPF 函数.
  3. 调用 BPF 函数后, XRP 调用元数据摘要, 使其能够转换下一次重提交的逻辑地址.
  4. XRP 通过在 NVMe 请求中设置相应字段来准备下一个 NVMe 命令重提交, 并将请求附加到该核心的 NVMe 提交队列 (SQ) 中.

对于特定的 NVMe 请求, 根据 NVMe 请求中注册的特定 BPF 函数确定的后续完成所需次数, 调用重提交逻辑.
BPF 函数的上下文是每个请求的, 而元数据摘要在所有内核中断处理程序的所有调用之间共享. 对元数据摘要的安全并发访问依赖于读-拷贝-更新(read-copy-update, RCU).

4.1.1 BPF 钩子

XRP 引入了一种新的 BPF 类型:BPF_PROG_TYPE_XRP, 与其签名匹配的 BPF 函数均可被钩子调用.
在这里插入图片描述
BPF_PROG_TYPE_XRP 程序需要上下文 struct bpf_xrp:

  • 被 BPF 调用者检查或修改的字段:
    • data: 缓存从磁盘读取的数据
    • done: 布尔值, 通知重提交逻辑返回给用户或继续重提交 I/O 请求
    • next_addr: 逻辑地址数组, 指示下个逻辑地址以供重提交 (数组以支持带有扇出的数据结构)
    • size: 逻辑地址对应大小数组
  • BFP 函数私有字段:
    • scratch: 对用户和 BPF 函数私有的暂存空间.

4.1.2 BPF 校验器

BPF 校验器通过跟踪存储在每个寄存器中的值的语义来确保内存安全.

校验器定义了各种指针类型:

  • SCALAR_TYPE: 无法解引用的值
  • PTR_TO_CTX: 指向 BPF 上下文的指针, 只能使用常量偏移量解引用
  • PTR_TO_MEM: 指向固定大小内存区域的指针, 支持使用可变偏移量解引用

每个类型定义了回调函数 is_valid_access(): 对上下文访问执行其他检查, 并返回上下文字段的值类型.

4.1.3 元数据摘要

元数据摘要: XRP 公开的在文件系统和中断处理程序之间共享逻辑-到-物理(logic-to-physical)块映射的接口.

元数据摘要组成:

  • 更新函数: 当逻辑-到-物理映射更新时, 在文件系统中被调用
  • 查找函数: 在中断处理程序中被调用, 返回给定偏移量和长度的映射

在这里插入图片描述

4.1.4 重提交 NVMe 请求

查找物理块偏移后, XRP 准备下一个 NVMe 请求, 重用刚完成请求的现有 NVMe 请求结构体 (即 struct nvme_command), 只需将现有 NVMe 请求的物理扇区和块地址更新为从映射查找中导出的新偏移量.

4.2 同步限制

BPF 目前只支持一个有限的自旋锁用于同步.
校验器只允许 BPF 程序一次获取一个锁, 且必须在返回之前释放.
用户空间不能直接访问 BPF 自旋锁, 必须通过 bpf() 系统调用读写锁保护的结构, 在操作期间会持有锁.

用户可以使用 BPF 原子操作实现自定义自旋锁.

4.3 与 Linux 调度器的交互

进程调度器. 当多个进程共享同一内核时, 即使所有 I/O 均从用户空间发出, 微秒级存储设备也会干扰 Linux 的 CFS (Completely Fair Scheduler, 完全公平调度器).
共享同一内核时, I/O 密集型进程会导致计算密集型进程 CPU 饥饿, XRP 通过生成中断链加剧了该问题.

I/O调度器. XRP 绕过了位于块层的 Linux 的 I/O 调度器.

5 案例研究

XRP 应用程序接口:

  • bpf_prog_load: 加载 BPF_PROG_TYPE_XRP 类型的 BPF 函数并将其 offload 到驱动程序中
  • read_xrp: 将特定 BPF 函数应用于读取请求

在这里插入图片描述
应用程序可以使用 XRP 加载多个 BPF 函数.

本文提出了两个关于如何修改应用程序以使用 XRP 的案例研究.

5.1 BPF-KV

BPF-KV: 简单的键值存储, 与其他基准线对比来评估 XRP.

  • 被设计为存储大量小对象
  • 使用 B+-树索引来查找对象位置
  • 缓存: 为索引块和对象实现了用户空间 DRAM 缓存, 维护最热门键值对的最近最少使用 (least recent use, LRU) 对象缓存
  • 范围查询: 支持返回可变数量的对象的范围查询
  • 聚合: 支持聚合操作, 如 SUMMAXMIN

5.2 WiredTiger

WiredTiger: 流行的键值存储, 作为 MongoDB 的默认后端, 用于实际生产.

  • 提供使用 LSM 树的选项, 其中数据被划分为不同的级别; 每个级别包含一个使用 B-树索引的文件
  • 缓存: 为其 B-树内部页面和叶子页面维护一个最近最少使用的 (LRU) 缓存

6 评估

回答问题:

  1. 使用 BPF 进行存储的开销是多少 (§6.1)?
  2. XRP 如何扩展到多个线程 (§6.2)?
  3. XRP 可以支持哪些类型的操作 (§6.3)?
  4. XRP 能否加速真实世界的键值存储 (§6.4)?

实验设置:

  • 一台 6 核 i5-8500 3GHz 服务器, 16 GB 内存
  • 使用 Ubuntu 20.04 和带有 Intel Optane 5800X 原型的 Linux 5.12.0
  • 使用 O_DIRECT, 关闭超线程, 禁用处理器低功耗模式(C-states)和睿频加速(Turbo Boost), 使用最大性能调节器, 并启用 KPTI
  • 使用 WiredTiger 4.4.0

基准线:
(a) XRP
(b) SPDK (一种流行的内核旁路库)
(c) 标准 read() 系统调用
(d) 标准 io_uring 系统调用

6.1 BPF-KV

延迟:

  • 实验: 执行了一百万次读取操作, 键名随机抽取, 概率均匀, 禁用数据对象和索引节点的缓存.
  • 结果:
    在这里插入图片描述
    在这里插入图片描述
    XRP 比 read() 改善了延迟
    每增加一次 I/O 操作就增加约 3.5-3.9 µs, 这与设备的延迟接近, 实现了接近最佳的延迟
    在 6 级索引的情况下, XRP 仅比 SPDK 慢 45%, 但 XRP 不重排序轮询.
    当使用单个线程运行时, 与 read() 和 io_uring 相比, XRP 将第 99 百分位延迟和 99.9 百分位等待时间减少了 30%.

吞吐量:
在这里插入图片描述
随着索引深度的增加, XRP 的加速比标准系统调用更高.

6.2 线程扩展

XRP 如何作为一些线程的函数进行扩展, 并将其与 SPDK.

  • 实验: 运行了一个开环实验, 其中负载量与 Intel 设备的最大带宽相匹配, 使用 6 个磁盘索引级别来比较 XRP (与 io_uring 集成) 与 SPDK (BPF-KV) 的吞吐量.
  • 结果:
    在这里插入图片描述
    1. 当使用 6 个工作线程 (机器上的 CPU 核数) 时, SPDK 和 XRP 都可实现接近硬件极限的吞吐量
    2. 一旦线程数超过 CPU 内核数, SPDK 的吞吐量就会稳步下降, 而 XRP 仍提供稳定吞吐量

6.3 范围查询

  • 实验: 比较使用 XRP 运行范围查询与使用 read() 系统调用执行查询的平均延迟和吞吐量. 索引深度为 6.
  • 结果: XRP 范围查询只增加了微不足道的开销, 性能加速保持相对恒定.
    在这里插入图片描述

6.4 WiredTiger

评估了 YCSB 上使用和不使用 XRP 的 WiredTiger 的性能

  • 实验: 运行不同的 YCSB 工作负载:
    YCSB A、B、C 和 E 使用 10M 操作, D 使用 50M 操作, E 使用 3M 操作.
    基准线 WiredTiger 使用 pread() 读取 B-数页面, 而带有 XRP 的 WiredTiger 使用read_xrp().
    用 10 亿个键值对填充数据库, 并将键值的大小设置为 16 B. 数据库的总大小为 46 GB.
    WiredTiger 驱逐线程的数量设置为 2.

吞吐量:
XRP 可以将大多数工作负载的速度提高 1.25 倍.
当 Zipfian 常数变大时, XRP 的效益会降低.
在这里插入图片描述

尾端延迟:
XRP 可以将第 99 百分位延迟降低 40%.
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/188139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中国电子学会2022年09月份青少年软件编程Python等级考试试卷一级真题(含答案)

分数:100 题数:37 测试时长:60min 一、单选题(共25题,共50分) 1.表达式len("学史明理增信 ,读史终生受益") > len(" reading history will benefit you ")的结果是?(…

vue3全局组件自动注册

前言:本文主要讲述vue3的全局公共组件的自动注册第一步:建文件需要在src/components 下创建一个文件夹用于存放封装的公共组件(这里我起名叫coms)需要在src/components 下创建一个js文件用于存放引入组件并注册(这里我…

前端经典面试500题【下】

面试 一、vue 说说vue动态权限绑定渲染列表&#xff08;权限列表渲染&#xff09; 首先请求服务器,获取当前用户的权限数据,比如请求 this.$http.get(“rights/list”); 获取到权限数据之后,在列表中使用v-if v-if-else的组合来展示不同的内容 <template><div>&…

JavaScript基础复盘3

流程控制 在一个程序执行的过程中&#xff0c;各条代码的执行顺序怼程序的结果是有直接影响的。很多时候我们药通过控制代码的执行顺序来实现我们药完成的功能。 简单理解&#xff1a;流程控制就是来控制我们的代码按照什么结构顺序来执行 JavaScript作为一门程序语言&#x…

JDBC-Mysql数据库连接池

传统数据库连接的弊端 一个java程序多个正常要开启多个mysql连接-正常开发中次数在1w次往上&#xff08;还可能有多个java程序-并发编程&#xff09;&#xff0c;但是如果很多歌连接的话&#xff0c;数据库可能就瘫痪了 测试一个程序连接5000次 抛出一个&#xff0c;太多连接的…

离校毕业生刚去新的陌生城市,需要提高警惕的几点

很多大学毕业生其实阅历还不是特别的多&#xff0c;从小在自己熟悉的环境长大&#xff0c;即便是读了大学&#xff0c;可能也是在自己熟悉的学校附近活动&#xff0c;同学们集体出去逛个街&#xff0c;放假了就回家了。 但一旦大学毕业要离校&#xff0c;可能你会去一个陌生的新…

论文笔记:Learning Disentangled Representations of Video with Missing Data

2020 Neurips 1 intro & abstract 视频表征的一个挑战是高维、动态、各个像素之间多模态分布 最近的一些研究通过探索视频的inductive bias&#xff0c;并将高维数据映射到低微数据中—>这种方法通过将视频的各帧分解成语义上有意义的因子&#xff0c;来获得视频的解耦…

Maven初级(二)

目录 四.第一个Maven项目&#xff08;手工制作&#xff09; 4.1 Maven工程目录结构 4.2 手工制作Maven项目的步骤 4.2.1 手工制作项目的目录结构或使用插件创建项目的目录结构 4.2.2 在项目的src同层目录下创建pom.xml文件 4.2.3 在cmd中使用Maven项目构建命令 四.第一个…

自动驾驶感知——物体检测与跟踪算法|4D毫米波雷达

文章目录1. 物体检测与跟踪算法1.1 DBSCAN1.2 卡尔曼滤波2. 毫米波雷达公开数据库的未来发展方向3. 4D毫米波雷达特点及发展趋势3.1 4D毫米波雷达特点3.1.1 FMCW雷达角度分辨率3.1.2 MIMO ( Multiple Input Multiple Output)技术3.2 4D毫米波雷达发展趋势3.2.1 芯片级联3.2.2 专…

[docker]-docker安装prometheus和grafana

导语&#xff1a;需要排查部分出问题的私有化环境。直接上一个docker的node_exporter prometheus grafana 最方便。 所用到的安装包在最下面的云盘。 解压安装自定义node_exporter # 这个abc的包名可以忽略 tar zxvf abc.tgz cd abc cp node_exporter /usr/local/ cat <…

Mybatis 动态sql的编写|开启二级缓存

❤️作者主页&#xff1a;微凉秋意 ✅作者简介&#xff1a;后端领域优质创作者&#x1f3c6;&#xff0c;CSDN内容合伙人&#x1f3c6;&#xff0c;阿里云专家博主&#x1f3c6; ✨精品专栏&#xff1a;数据结构与课程设计 &#x1f525;系列专栏&#xff1a;javaweb 文章目录前…

Linux-主要目录

/: 根目录&#xff0c;一般根目录下只存放目录&#xff0c;在Linux下有且只有一个根目录&#xff0c;所有的东西都是从这里开始当在终端里输入 /home,其实是在告诉电脑&#xff0c;先从/&#xff08;根目录&#xff09;开始&#xff0c;再进入到home目录/bin、/usr/bin:可执行二…

java基于ssm的旅游景点门票预订网站

通过本系统&#xff0c;能够实现用户进行登录后&#xff0c;在网站上对旅游景点信息进行门票预订&#xff0c;也可以通过在线留言系统&#xff0c;了解景点相关信息&#xff0c;为用户提供全方位的服务&#xff0c;同时为节省用户的时间&#xff0c;本系统采用分地名的方式&…

2022尚硅谷SSM框架跟学(七)Spring MVC基础二

2022尚硅谷SSM框架跟学 七 Spring MVC基础二4.SpringMVC获取请求参数4.1.通过ServletAPI获取4.2.通过控制器方法的形参获取请求参数4.3.RequestParam4.4.RequestHeader4.5.CookieValue4.6.通过POJO获取请求参数4.7.解决获取请求参数的乱码问题5.域对象共享数据5.1.使用ServletA…

LCX端⼝转发

LCX是一款十分经典的内网端口转发工具&#xff0c;基于Socket套接字&#xff0c;具有端口转发和端口映射的功能。但是目前很多杀软已经将其加入了特征库&#xff0c;在实际利用的时候需要自行做免杀处理。lcx有三个功能&#xff1a;第一个功能将本地端口转发到本地另一个端口上…

红米10A 一键root教程 跳过 秒过 168小时解锁BL 限制完美面具root保数据救黑砖刷机 解决无法解锁BL 新版本问题

新版本红米10A 无法秒解锁BL。root bootloader 要刷机、线刷救砖、获取Root权限都需要解除bootloader锁 我们称解除刷机限制的这个操作就叫解锁BL&#xff0c;只有解锁BL后&#xff0c;才可以进行刷机、刷Root权限等等一些列的操作。&#xff08;注&#xff1a;bootloader锁不…

Spring为什么这么火 之 五大类注解

目录 前言 存储Bean对象 1、配置扫描路径 2、将Bean存储到容器中 2.1、5大注解实现&#xff08;Controller、Service、Repository、Component、Configuration) Controller Service Repository Configuration Component 为什么需要五个类注解&#xff1f; 五大类注解的关…

Jmeter分布式

Jmeter的分布式控制&#xff0c;就是指远程启动功能。执行原理&#xff1a; 1、一台作为调度机(master)&#xff0c;其它机器做为执行机(slave) 2、执行时&#xff0c;master会把脚本发送到每台slave上&#xff0c;slave 拿到脚本后就开始执行 3、执行完成后&#xff0c;sla…

go语言编译文件踩坑

目录 1 no required module provides package xxx go.mod file not found in current directory or any parent directory; see go help modules 方式1 执行 go env -w GO111MODULEauto后再编译 方式2 创建go.mod 2 报错syscall.go:84:16: undefined: unsafe.Slice 3 b…

ArrayList集合类和对象数组案例区别讲解

目录 对象数组案例讲解 集合 ArrayList类的构造方法和成员方法 对象数组案例讲解 创建一个学生数组&#xff0c;存储三个学生对象并遍历 package com.demo01; /*** * author 无限嚣张菜菜* 分析&#xff1a;* A&#xff1a;定义学生类* B&#xff1a;创建学生数组* C&am…