1. 论文信息
- 文章来自HotStorage 23
- P2Cache:An Application-Directed Page Cache for Improving Performance of Data-Intensive Applications
所有作者及单位
- Dusol Lee, Inhyuk Choi, Chanyoung Lee, Jihong Kim, 首尔大学Seoul National University
- Sungjin Lee, 大邱庆北科学技术院DGIST
2. Background
大多数操作系统在主机DRAM内存中使用页面缓存,以利用I/O访问的局部性。但页面缓存的高速缓存管理策略可能与应用程序的特定I/O特征不太匹配。如果应用程序随机访问I/O地址空间,则页面缓存使用的标准读取策略可能无效。
现有缓存策略的局限性——评估三种常见技术:
2.1操作系统级缓存
采用 LRU 替换策略与预读算法相结合,如果应用程序具有中等局部性,通常可以实现较高的命中率 [11]。现有的数据密集型应用程序通过高度定制的算法处理大量数据,从而导致复杂的 I/O 模式。不幸的是,由于其通用设计,操作系统级页面缓存通常无法捕获各个应用程序的独特行为,从而即使可以实现更高的命中率,也无法提供次优的性能。
下图是Lumos [2],执行图形处理算法 - Pagerank [15]的IO模式和性能趋势(它使用专门的数据结构和优化技术来优化图形处理引擎,因此生成的 I/O 访问模式非常复杂。)
- 性能低下是由于操作系统级页面缓存的内存管理无效,该缓存使用 LRU 和预读策略,而不考虑输入工作负载模式。操作系统级页面缓存优先驱逐最近最少引用的页面,但这些页面实际上很快就会再次被引用,特别是在循环 I/O 模式下。
- 可以观察到,使用具有小数据固定的 MRU 策略(而不是 LRU)会带来更高的性能,如图 1 中的 MRU+PIN 所示,性能提高了 25%。然而,很难改变内部的情况。适应输入工作负载的内核缓存替换策略。
2.2基于提示的操作系统级缓存
作为一种替代方案,一些应用程序(例如 GridGraph [1] 或 SQLite [7])尝试通过 fadvise [16] 和 madvise [17] 向内核提供应用程序级提示来更好地管理缓存数据。在保留内核级缓存管理相同优点(强大的数据保护和高效的数据共享)的同时,它能够通过在应用程序代码中嵌入重要的缓存管理决策(例如,WILLNEED、SEQUENTIAL、DONTNEED)来实现更高的缓存命中率。
然而,它也有缺点。首先,它需要在修改现有应用程序代码方面付出巨大的努力。其次,仅通过注入提示很难精细控制内核级页面缓存。我们在代码中精心添加了提示信息,以MRU方式管理内核缓存。修改后的版本表现出更高的命中率,但性能仍然比使用 MRU 慢得多(参见图 1 中的 FADV)。这是因为缓存抖动。
2.3用户级缓存
为了减轻I/O特征(应用程序)和(内核级页缓存)策略之间的不匹配问题,数据密集型应用程序经常在应用程序级别[3-7]上实现自己的页面缓存。
- 受内核缓存策略干扰,驱逐了有用的页面,违反了应用程序的意图。
- 无法利用内核的保护和共享功能。
下图使用 Simrank [19] 进行了实验,这是一个具有自己的用户级缓存的图形应用程序。
如图 2(a)所示,Simrank 的 I/O 参考模式大多是随机的,因为它将流行数据缓存在用户级缓存中。由于这种特定于应用程序的管理,对于相同的数据集,Graph-Walker 表现出比 Lumos 更高的性能(见图 2(b))。然而,当内存不足时,GraphWalker 的性能下降幅度比 Lumos 更高。
3. 解决的问题
内存密集型程序的I/O更加具有特性,内核级页面缓存由于无法考虑特定于应用程序的 I/O 模式而无法提供高性能。应用程序级提示可以缓解该问题,但与最佳效果相比,效果有限。虽然用户级自定义缓存可以高效工作,但它无法利用内核的基础设施,并且会因内核干预而导致性能下降。于是做了一个允许应用程序开发人员构建与目标应用程序的I/O特征匹配的自定义内核级别的CACHE。
4. 其他学者解决这个问题的思路和缺陷
如果直接实现了用户级页面缓存(例如,如Jaydio [8]或RockSDB的Direct-io [9]),则可能无法对某些内核功能进行介入,例如用于确保数据保护和数据一致性的功能。更重要的是,如果SSD或主机存储系统发生重大变化,则需要重新实现用户级缓存。
5. 围绕该问题作者如何构建解决思路
图 3 显示了 P2Cache 的操作概览。要为应用程序创建自定义页面缓存,可能需要应用程序的特定于应用程序的数据来开发新的缓存策略。如果需要,数据会被移动到内核的受保护内存(1)。为了避免其他应用程序对数据进行未经授权的访问,为每个自定义页面缓存分配了一个密码(passwd)。使用P2C API函数以及应用程序的内核数据,为P2Cache的每个探测点实现一个eBPF程序 (2)。将eBPF程序加载到各自的探测点(3)后,只要内核的执行流到达这些点,就会执行eBPF程序,应用程序的自定义页面缓存就会生效。在执行eBPF程序之前,扩展的eBPF VM会验证程序是否有权访问应用程序拥有的内核数据以及特定于应用程序的数据。这是通过将eBPF程序的passwdprobe与从相应应用程序传递来的passwd进行比较来实现的。
6. 从结果看,作者如何有力证明他解决了问题
实验结果表明,使用我们的P2Cache实施的Cusmom Page缓存可在数据密集型图应用中提高32%的性能,内存容量低于数据集容量时也是相比其他方案性能下降更缓慢。
7. 缺陷和改进思路
8. 创新点
做了一个允许应用程序开发人员构建与目标应用程序的I/O特征匹配的自定义内核级别的CACHE,别人的都是应用层级的。
9. 积累
数据密集型工作负载:Lumos [2] and GraphWalker [4]。目前使用的工作负载,容量如果内存不能容下,则会杀死进程,这里使用这两个工作过负载还可以使得Memory Size / Dataset Size成比例。Lumos 维护多个文件并同时扫描它们,将混合 I/O 模式发送到磁盘。 Lumos 还使用多个元数据文件并重复读取它们,从而产生高度本地化的 I/O 模式。
2.2节的实现手段可以模仿。eBPF程序也能去影响内核。