共计 2548 个字符,预计需要花费 7 分钟才能阅读完成。
本篇内容介绍了“Fuse 文件系统优化的方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
优化 1:延长元数据有效时间
Linux 中每个打开文件在内核中拥有两种元数据信息:struct dentry 和 struct inode,它们是文件在内核的基础。所有对文件的操作,都需要先获取文件这两个结构方可继续下去,而这两个结构又是由具体文件系统负责构造填充。以下两点解释了元数据优化的必要性:
1). 应用程序调用文件系统操作系统接口时,传入的参数一般为文件路径,如 open(“a/b/c/d.txt”),内核需要对路径名进行解析,从根目录开始,根据路径中的每个分量获取其 dentry 和 inode,接着解析路径的下一个分量,直至解析出目的文件的 inode 和 dentry,如果路径名分量中的 dentry 没有缓存在内存中,需要从具体文件系统上读出(这就耗时多了)。
2). 很多应用程序喜欢调用 stat 接口以获取文件属性,内核实现其实是找到文件 inode,从 inode 中获取文件属性。如果 inode 没有被缓存,则需要从具体文件系统中获取(可能会很耗时)。
因为 Fuse 的内核模块只是一个桥梁,连接了应用程序和我们基于 Fuse 开发的文件系统。所以,按照道理说,每次获取文件 / 目录的 inode 以及 dentry 的时候 Fuse 内核模块都应该去 LibFuse 以及我们的文件系统走一遭。
但是这样做的话缺点非常明显:IO 路径拉长,效率变低,而且假如我们基于 fuse 开发的文件系统是网络文件系统(例如 NOS 等),可能会导致后端服务器压力增大。
有鉴于此,Fuse 的作者在 Kernel Fuse 模块中增加了元数据缓存,包含 dentry 和 inode 缓存。相比本地文件系统,我们必须时刻警惕一个问题:缓存有效性。所以,如何在提升性能的同时又尽量保证正确性是一个棘手的问题。
利用 fuse 挂载我们自己文件系统时,可指定 dentry 以及 inode 属性有效时间,当然这个有效时间得具体问题具体设置了,无统一答案。
优化方法:fuse 挂载指定 ndash;o entry_timeout=T ndash;o attr_timeout=T
优化建议:五颗星
优化 2:扩大每次写入页面数
应用程序每次对基于 Fuse 开发的文件系统的文件写入必先经过 Kernel Fuse 模块,Kernel Fuse 其实是有很大权限决定何时将数据写入到用户态文件系统的。写的越频繁,效率必然越低,但一致性可能会更好,控制写入频率其实也是一个权衡的过程。
如果稍微熟悉 Kernel 你可能就会知道内核的 IO 其实是以 Page 为单位的。内核会将应用程序的写入请求按照 PAGE_SIZE 划分成多个 page,然后再对 page 进行 IO,简洁优美。
如果不作优化,Kernel Fuse 对应用程序的每次 page 都会调用一次用户态文件系统的写操作,这样假如我们用户态的 64KB 的写请求,按照默认的 PAGE_SIZE(4KB) 可能会触发 16 次的用户态写,实际 IO 次数被放大,效率严重下降。如果采取优化,Kernel Fuse 默认会每 128KB 才触发一次用户态文件系统写调用,当然亦可指定触发写调用的阈值。
优化方法:fuse 挂载指定 ndash;o big_write ndash;o max_write=N
优化建议:五颗星
优化 3:开启内核读缓存
Linux 文件系统实现充分利用了内存来缓存文件数据,这样应用程序很多时候读文件其实只需从内核缓冲区拷贝数据至用户态缓冲区即可,根本不必启动磁盘 IO。
由于 Fuse 的特殊性,需要严格控制数据缓存行为(看看我们前面提到的元数据缓存吧),因为可能我们实现的基于 Fuse 的文件系统其实是一个网络文件系统,那么如果使用内核缓存,可能就读到脏数据,因为作为用户态的你是很难控制内核的行为的。
不过 Fuse 的作者非常周到,它提供了多种挂载选项,来控制缓存行为,但友情提醒:一旦选择开启缓存,请为自己的可能读的过期数据负责。
优化方法:fuse 挂载指定 ndash;o kernel_cache ndash;o auto_cache
顺便提一句:我们上面说的都是参数 kernel_cache 的行为,没有说明 auto_cache 的行为,留给各位读者仔细研究吧,提个醒:该选项是基于文件修改时间进行内核缓存有效性检测的优化策略。
优化建议:三颗星
优化 4:扩大预读窗口
预读是在是一件有趣的事情。Linux 内核通过预读改变了应用程序的原始读行为。比如应用程序发起了一个 16KB 的读请求,内核可能莫名其妙地读取 64KB 数据等。当然,它这么做肯定有其道理,简单来说:一切为了性能,为了性能的一切。另外,我会在近期推出一篇预读相关文章,详细阐述预读机制,敬请关注。
Fuse 允许挂载用户态文件系统时指定预读窗口大小,Fuse 会用该设定值作为 *** 的预读窗口大小,若不指定,会采用 Linux 默认的 *** 预读窗口大小 128KB。但是其实如果你设置了 Fuse 的预读窗口超过 Linux 默认的 128KB 也是徒劳,因为 VFS 不允许预读窗口超过 128KB 限制,所以总的来说,优化的意义不大。
优化方法:fuse 挂载指定 ndash;o max_readahead = N
优化建议:一颗星
优化 5:使用 DirectIO 取代 BufferIO
有些时候,应用程序希望绕过 OS 的缓存而自己管理缓存(如数据库),这需要文件系统实现 DIRECTIO 方法。
同样,贴心的 Fuse 作者也为我们提供了 directIO 方式的读写。相比 BufferIO 方式,DirectIO 的 *** 优势在于减少了数据从应用程序缓冲区拷贝至内核态的开销,对于大量顺序写的应用场景,性能可能会有一定提升。
当然,如果采用 DirectIO,恐怕 *** 的问题就是 read 也无法使用内核缓存了,很多时候这是我们无法忍受的,常常来说,文件系统读请求会远多于写,所以,优化前望三思。
优化方法:fuse 挂载指定 -o direct_io
优化建议:一颗星
“Fuse 文件系统优化的方法有哪些”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!