导读:NFSClient 对大多数的应用写入没有做对齐优化,本文根据 IO 不对齐的原因给出了若干实践建议。

作者 | 裴晓辉

背景

最近团队小伙伴弗曼统计了线上用户数据写入对齐情况,通过统计数据发现了一个有趣的现象: 用户写入请求中近 70% 的数据块 4K 不对齐,这也就是说 NFSClient 对大多数的应用写入没有做对齐优化。

下面会从 NFSClient BufferWrite 实现流程的维度解释 IO 不对齐的原因,最后据此给出了若干实践建议。

场景分析

应用程序一般可以使用 DirectIO 或 BufferIO 两种方式向文件写入数据。在 DirectIO 模式时 NFSClient 直接将用户 IO 通过 RPC 发送给服务端,因此 DirectIO 方式写入 NFSClient 不会做对齐,但考虑到应用程序使用 DirectIO 时一般会在应用侧做对齐,因此非对齐 IO 的多数应该是 BufferIO 方式。

内核使用 struct nfs_req 对象记录某个缓存页更改情况,同时使用 struct page 对象的 private 字段保存,因此只需分析 BufferIO 时 nfs_req 的处理逻辑就能够知道对齐规则。NFSClient 调用 nfs_updatepage() 更新 nfs_req 对象,其核心代码如下:

从上图红色框中代码可以看出来,NFSClient 会尝试按照缓存页大小对 offset/count 对齐,继续查看 nfs_can_extent_write() 函数实现:

从上述代码可知:

1) 若为同步写,则不尝试对齐,这是因为对同步写做对齐并没有明显收益还会放大 IO;

2) 若缓存页内容不是最新,则不允许对齐,否则就要读惩罚,注意 nfs_write_begin() 函数已处理是否需要读惩罚;

3) 若持有 Write Delegation,则允许对齐,因为 Write Delegation 保证本地缓存数据一定是最新,关于 Delegation 可参考文章《NFSClient Delegation 实现与陷阱》;

4) 若不持有文件锁,则允许对齐,注意此处依据 NFSClient 设计哲学的一个假设:应用在不持有文件锁写入数据时,应用侧应该保证文件不会被多客户端修改;

5) 若持有全文件的写锁,则允许对齐,因为写锁保证了本地缓存数据肯定是有效的且不存在多客户端更改,此外这里要求全文件锁的原因是为了简化代码逻辑。

合并规则

上面提到内核使用 struct nfs_req 对象表示每个缓存页的更改情况,考虑到 struct nfs_req 只能表示单区间,因此 BufferIO 需合并同一个缓存页的多次更改,合并规则较为简单:

两个写合并后必须是一个连续的区间。

相关代码实现可参考 nfs_try_to_update_request() 函数,代码较为简单,故不再详细描述。从合并规则还可以知道:同一个缓存页上的两个非连续 IO 需要两次 RPC 写入。

缓存页 UpdateToDate 设置

从场景分析中知道缓存页是否设置了 UpdateToDate 标记是同一缓存页上的两个 IO 能否合并的重要前提条件,那 NFSClient 是什么时候将缓存页设置为 UpdateToDate 状态的呢?总的来说,NFSClient 在两个地方尝试设置该标记:

1) 将缓存页加入到 address space 时,实现代码是 nfs_write_begin() 函数,相关逻辑如下:

继续查看 nfs_want_read_modify_write() 函数实现:

上图中蓝色框中是 pNFS 相关处理暂时不做讨论,红色框则是一般情况下将缓存页加入到 address space 时是否需要读惩罚(读取数据后缓存页内容自然为最新),具体的需满足如下几个条件:

a) 若应用打开文件模式允许读,则允许读惩罚,这是因为根据数据的局部性原理,刚写入的数据很可能再次读;

b) 缓存页内容不是最新,若已经是最新很显然没必要再次读老数据;

c) 当前缓存页没有正在进行的 IO,也就是说没有向服务端有读写请求,注意 nfs_req 只能表示单个 IO,显然此时不允许读;

d) 本次修改只是缓存页的局部内容,显然如果全覆盖是没有必要读入老数据;

2) 当内核将待修改的数据拷贝到缓存页后会调用 nfs_write_end() 函数通知 NFSClient 数据已经拷贝到缓存页,此时 NFSClient 需根据写入情况设置缓存页是否为最新的状态:

通过上面代码可知:

a) 蓝色框中表示缓存页是文件变大时新追加的缓存页,此时缓存页内容为全零,自然可设置为最新;

b) 红色框中表示缓存页中所有的有效数据均被覆盖,此时缓存页内容必然为最新;

总之,数据写入后若完全覆盖该缓存页的所有原有效数据,则设置为最新。

实践建议

至此基本搞清楚了 NFSClient BufferWrite 的对齐实现逻辑,感兴趣的同学可自行编写测试用例验证。结合对齐实现和测试验证,初步的可给出如下建议:

1) O_SYNC 方式不会做缓存页对齐;

2) 当文件被大量小块 IO 重复覆盖写时,可考虑用 O_RDWR 方式打开(注意副作用是会有读惩罚),有利于聚合同一个缓存页的写 IO,减少 RPC 次数;

3) 使用 O_WRONLY 方式打开时,同一缓存页的不连续更改不会做聚合,每个 IO 都会触发一次 RPC,降低访问性能;

4) 使用类 MPI 方式多客户端并发修改同一文件时,条带大小应该做到缓存页对齐,否则可能会导致数据被错误覆盖;

5) 不恰当的使用文件锁会导致不做缓存页对齐;

6) 不使用文件锁时小块 IO 可能会缓存页对齐,导致 IO 放大。

总结

缓存页对齐是提高 BufferIO 访问性能地有效手段,NFSClient 在设计上尽量会尝试缓存页对齐,但受限于 NFS 共享特性的约束,也只能对较为有限的情况做缓存页对齐,这就潜在地要求应用侧配合才可以达到最优性能。

放大缩小保证div对齐_NFS Write IO 不对齐深度分析相关推荐

  1. 放大缩小保证div对齐_GraphPad Prism 绘图教程 | 如何在图表中对齐对象

    自动捕捉 Prism默认会自动捕捉对象以使其与坐标轴或其他对象对齐. 例如,你可以在一个或一组条形图上拖动一个文本框,Prism将尝试对齐该文本框以使其与条形图的中心线对齐. Prism也可以将文本调 ...

  2. Jquery鼠标滚轮放大缩小图片

    使用Jquery鼠标点击图片,划动鼠标滚轮放大缩小图片. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...

  3. jquery 控制字体放大缩小

    上周结了一个学校门户网站前端页面制作的工作(改版又改版,修改又修改),有很多js效果我是利用jquery来实现的,其中有个新闻正文字体放大缩小效果,比较简单,在这里提出来做个小小demo.(写几句又多 ...

  4. bootstrap缩小后div互相叠加_纯 JS 实现放大缩小拖拽踩坑之旅

    点击上方"前端公虾米",选择"置顶或者星标" 你的关注意义重大! 前言 最近团队需要做一个智能客服悬浮窗功能,需要支持拖动.放大缩小等功能,因为这个是全局插件, ...

  5. js 实现 H5 div的内容 放大缩小拖拽功能 vue可用

    大佬写的组件 , 虽然我看不懂 但不妨碍我会用啊 想去看大佬代码的点这里 下面的无脑的代码时刻 一.复制代码到一个单独的.vue文件然后 走人去下一步 // 放大缩小页面组件 <template ...

  6. html 图片在一个div中放大缩小效果

    图片放大,缩小也是前端中经常遇到得问题,以下就根据这个需求,做如下示范: <!DOCTYPE html> <html> <head><title>图片放 ...

  7. html图片自动在div里放大,HTML5+CSS3实现图片的放大/缩小

    原标题:HTML5+CSS3实现图片的放大/缩小 最近做项目时,经常遇到需要图片缓慢放大的效果.我做的时候想到了几种方法,所以来总结一下. 1. 利用css改变图片的宽高,做出视觉上的放大. 首先,将 ...

  8. HTML5 canvas处理图片的各种效果,包括放大缩小涂鸦等

    http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/201502151385.html jQuery 缩放 旋转 裁剪图片 Image Cropper ...

  9. vue图片查看器,支持放大 缩小 还原

    Vue中使用图片查看器 如何使用 项目中使用的是 vue + element-ui 要求查看图片时能够实现 图片放大缩小翻转等功能,于是找到一个适合的插件,首先看下效果: 功能与我们设想的一样,下面看 ...

最新文章

  1. 你之所以没成为成就,就是因为太刻苦了!
  2. 新兴经济体助力BCH长足发展
  3. 李宏毅深度学习——优化方法
  4. 操作数数据类型 char 对于 sum 运算符无效。_数据类型和运算符
  5. LeetCode(2)——两数相加(JavaScript)
  6. 什么是防病毒网关 防病毒网关的功能特点
  7. Unity LitJson的读写使用
  8. Win10一键更换系统字体
  9. 人口logistic模型公式_人口的logistic模型
  10. 电子计算机和量子力学,通俗讲解一下量子计算机究竟是怎么运作的?其实量子力学并不深奥...
  11. Intel 系统级架构概述
  12. 如何在微信小程序开发中添加组件?
  13. 第一章 SpringMvc---Web MVC简介
  14. 全球顶级黑客对决AI GeekPwn2017黑客大赛看点曝光
  15. 兰州工业学院有计算机专业,兰州工业学院计算机协会
  16. 干净卸载mac上的软件
  17. 世界读书日之所思所想
  18. 选择排序、冒泡排序、插入排序、快速排序、希尔排序、归并排序、堆排序和希尔排序的java实现比较
  19. 2022.1.20-笔记-JSON格式转换(JSON类型str->int\double\string)
  20. 中软国际华为携手赋能合作伙伴做大云市场

热门文章

  1. Hapoxy+keepalived实现双主高可用负载均衡
  2. Hadoop Mapreduce分区、分组、二次排序过程详解[转]
  3. 中鸣投篮机器人怎么组装_1000余人参加洛阳市青少年机器人竞赛
  4. linux下VI模式中上下左右键和回退键出现字母
  5. ORA-04063: view DAILY.TMP_TBX_100_0_S4 有错误
  6. 计算机论文答辩2分钟演讲稿,毕业答辩发言稿三分钟
  7. android开发方法数,Android减少App方法数
  8. kotlin 查找id_Kotlin程序查找立方体区域
  9. timer purge_Java Timer purge()方法与示例
  10. python true_True关键字,带Python示例