[转帖]基于Fuse的用户态文件系统性能优化几点建议
https://zhuanlan.zhihu.com/p/68085075
目前很多文件系统基于Fuse( http://fuse.sourceforge.net/ )开发,在较为深入钻研Fuse实现后,总结出开发此类文件系统时可考虑的优化方案,拿出来与大家讨论讨论,如有不准确的地方,还望大家不吝赐教。阅读本文前,我假设你对Fuse有了足够多的了解(起码知道Fuse有两个模块:Fuse Kernel 和LibFuse以及知道一个应用程序调用行为如何传递至我们自己开发的基于Fuse的文件系统),否则,请先移步。
优化1:延长元数据有效时间
Linux中每个打开文件在内核中拥有两种元数据信息:struct dentry和struct inode,它们是文件在内核的基础结构。所有对文件的操作,都需要先获取文件这两个结构方可继续下去,而这两个结构又是由具体文件系统负责构造填充。以下两点解释了元数据优化的必要性:
- 应用程序调用文件系统操作系统接口时,传入的参数一般为文件路径,如open(“a/b/c/d.txt”),内核需要对路径名进行解析,从根目录开始,根据路径中的每个分量获取其dentry和inode,接着 加粗文字 解析路径的下一个分量,直至解析出目的文件的inode和dentry,如果路径名分量中的dentry没有缓存在内存中,需要从具体文件系统上读出(这就耗时多了)。
- 很多应用程序喜欢调用stat接口以获取文件属性,内核实现其实是找到文件inode,从inode中获取文件属性。如果inode没有被缓存,则需要从具体文件系统中获取(可能会很耗时)。
因为Fuse的内核模块只是一个桥梁,连接了应用程序和我们基于Fuse开发的文件系统。所以,按照道理说,每次获取文件/目录的inode以及dentry的时候Fuse内核模块都应该去LibFuse以及我们的文件系统走一遭。
但是这样做的话缺点非常明显:IO路径拉长,效率变低,而且假如我们基于fuse开发的文件系统是网络文件系统(例如NOS等),可能会导致后端服务器压力增大。
有鉴于此,Kernel Fuse模块中增加了元数据缓存,包含dentry和inode。相比本地文件系统,我们必须时刻警惕一个问题:缓存有效性。所以,如何在提升性能的同时又尽量保证正确性是一个棘手的问题。
利用fuse挂载我们自己文件系统时,可指定dentry以及inode属性有效时间,当然这个有效时间得具体问题具体设置了,无统一答案。
优化方法:fuse挂载指定 –o entry_timeout=T –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挂载指定 –o big_write –o max_write=N
优化建议:五颗星
优化3:开启内核读缓存
Linux文件系统实现充分利用了内存来缓存文件数据,这样应用程序很多时候读文件其实只需从内核缓冲区拷贝数据至用户态缓冲区即可,根本不必启动磁盘IO。
由于Fuse的特殊性,需要严格控制数据缓存行为(看看我们前面提到的元数据缓存吧),因为可能我们实现的基于Fuse的文件系统其实是一个网络文件系统,那么如果使用内核缓存,可能就读到脏数据,因为作为用户态的你是很难控制内核的行为的。
不过Fuse的作者非常周到,它提供了多种挂载选项,来控制缓存行为,但友情提醒:一旦选择开启缓存,请为自己的可能读的过期数据负责。
优化方法:fuse挂载指定 –o kernel_cache –o auto_cache
顺便提一句:我们上面说的都是参数kernel_cache的行为,没有说明auto_cache的行为,留给各位读者仔细研究吧,提个醒:该选项是基于文件修改时间进行内核缓存有效性检测的优化策略。
优化建议:三颗星
优化4:扩大预读窗口
预读是在是一件有趣的事情。Linux内核通过预读改变了应用程序的原始读行为。比如应用程序发起了一个16KB的读请求,内核可能莫名其妙地读取64KB数据等。当然,它这么做肯定有其道理,简单来说:一切为了性能,为了性能的一切。另外,我会在近期推出一篇预读相关文章,详细阐述预读机制,敬请关注。
Fuse允许挂载用户态文件系统时指定预读窗口大小,Fuse会用该设定值作为最大的预读窗口大小,若不指定,会采用Linux默认的最大预读窗口大小128KB。但是其实如果你设置了Fuse的预读窗口超过Linux默认的128KB也是徒劳,因为VFS不允许预读窗口超过128KB限制,所以总的来说,优化的意义不大。
优化方法:fuse挂载指定 –o max_readahead = N
优化建议:一颗星
优化5:使用DirectIO取代BufferIO
某些时候,应用程序希望绕过OS的缓存而自己管理缓存(如数据库),这需要文件系统实现DIRECTIO方法。
同样,Fuse也贴心地为我们提供了directIO方式的读写。相比BufferIO方式,DirectIO的最大优势在于减少了数据从应用程序缓冲区拷贝至内核态的开销,对于大量顺序写的应用场景,性能可能会有一定提升。
当然,如果采用DirectIO,恐怕最大的问题就是read也无法使用内核缓存了,很多时候这是我们无法忍受的,常常来说,文件系统读请求会远多于写,所以,优化前望三思。
优化方法:fuse挂载指定 -o direct_io
优化建议:一颗星
[转帖]基于Fuse的用户态文件系统性能优化几点建议的更多相关文章
- Linux文件系统性能优化 (转)
http://blog.chinaunix.net/uid-7530389-id-2050116.html 由于各种的I/O负载情形各异,Linux系统中文件系统的缺省配置一般来说都比较中庸,强调普遍 ...
- Linux文件系统性能优化
本文绝大部分是转载自CSDN刘爱贵专栏: http://blog.csdn.net/liuben/archive/2010/04/13/5482167.aspx另外根据参考文档增补了一部分内容. 由于 ...
- 用户态文件系统fuse学习【转】
本文转载自:https://blog.csdn.net/ty_laurel/article/details/51685193 FUSE概述 FUSE(用户态文件系统)是一个实现在用户空间的文件系统框架 ...
- 用户态与内核态 & 文件流与文件描述符 简介【转】
转自:https://www.cnblogs.com/Jimmy1988/p/7479856.html 用户态和内核态 程序代码的依赖和调用关系如下图所示: Lib:标准ASCI C函数,几乎所有的平 ...
- 用户态与内核态 & 文件流与文件描述符 简介
用户态和内核态 程序代码的依赖和调用关系如下图所示: Lib:标准ASCI C函数,几乎所有的平台都支持该库函数,因此依赖该库的程序可移植性好: System Function:系统调用函数,与系统内 ...
- C# 读写文件从用户态切到内核态,到底是个什么流程?
一:背景 1. 一个很好奇的问题 我们在学习 C# 的过程中,总会听到一个词叫做 内核态 ,比如说用 C# 读写文件,会涉及到代码从 用户态 到 内核态 的切换,用 HttpClient 获取远端的数 ...
- 内核中dump_stack()的实现,并在用户态模拟dump_stack()【转】
转自:https://blog.csdn.net/jasonchen_gbd/article/details/44066815?utm_source=blogxgwz8 版权声明:本文为博主原创文章, ...
- Linux内核笔记--内存管理之用户态进程内存分配
内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...
- 聊聊Linux用户态驱动设计
序言 设备驱动可以运行在内核态,也可以运行在用户态,用户态驱动的利弊网上有很多的讨论,而且有些还上升到政治性上,这里不再多做讨论.不管用户态驱动还是内核态驱动,他们都有各自的缺点.内核态驱动的问题是: ...
- 用户态使用 glibc/backtrace 追踪函数调用堆栈定位段错误【转】
转自:https://blog.csdn.net/gatieme/article/details/84189280 版权声明:本文为博主原创文章 && 转载请著名出处 @ http:/ ...
随机推荐
- .NET技术分享日活动20221022
2022年10月22日下午,个人组织举办了山东地区的第六次.NET技术分享日活动.围绕.NET.低代码Low Code.云原生 Cloud Native.大数据.算法等方向进行创新技术的实践分享. 本 ...
- 以小博大外小内大,Db数据库SQL优化之小数据驱动大数据
SQL优化中,有一条放之四海而皆准的既定方针,那就是:永远以小数据驱动大数据.其本质其实就是以小的数据样本作为驱动查询能够优化查询效率,在SQL中,涉及到不同表数据的连接.转移.或者合并,这些操作必须 ...
- 华为云MVP高浩:打破AI开发瓶颈,解决数据、算法、算力三大难题
摘要:在高浩看来,大量的数字蓝领人才和AI应用开发人员构成了当前AI行业发展人才之基,这也为高校学生就业初期从事的工作指明了方向,而华为ModelArts平台在教育领域有着天然的数据.算法优势,非常适 ...
- Nacos是什么?
摘要:Nacos是 Dynamic Naming and Configuration Service的首字母简称,相较之下,它更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. 本文分享自华 ...
- 云图说 | 华为云医疗智能体智联大健康:AI医学影像
摘要:华为云医疗智能体面向医学影像领域,提供影像智能标注.算法开发和AI辅助诊断服务. 本文分享自华为云社区<[云图说]第208期 医疗智能体 智联大健康:AI医学影像>,原文作者:阅识风 ...
- Axure App 垂直滚动
拖两个动态面版 最外层[动态面板]用来定义显示区域,高度:692 (根据实际来) 里面的[动态面板],用来放内容,高度根据实际情况来,示例中是:1920 如下图所示 里面的[动态面板]添加垂直滚动 外 ...
- hystrix.stream dashboard
9001 POM.XML <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&quo ...
- logback.xml 配置文件
logback.xml <?xml version="1.0" encoding="UTF-8"?> <configuration> & ...
- 悲报, GIF 之父因新冠去世
今天下午二狗子照常上班摸鱼的时候,突然看到了一则消息,消息说 GIF 的发明人因新冠去世了.作为一个自诩理性的互联网人,二狗子第一反应是看到了一个离谱谣言,可是查看了多方消息后,二狗子难过地发现这是真 ...
- CO40/CO41转生产订单下达时不能创建采购申请
一.配置 CO01创建生产订单,创建时生成采购申请,改为下达时创建采购申请.通过配置,将预留/采购申请 更改为2即可. 但是CO41和CO40通过配置,并不能达到更改预留/采购申请 为2. 二.调试源 ...