预分配——fallocate的前世今生

       最近比较懒,还是加班写点东西吧,不然过段时间又把这些整理的东西弄丢了。

       写什么呢?写一些跟工作相关的吧!因为笔者从事多媒体录像相关的开发工作,因此常常涉及到优化写卡策略、提升写卡性能相关的方面的事情。此话怎讲呢?如行车记录仪类的录像产品,录像可能持续多日,越往后写卡速度会越来越慢,直观感受是取出视频文件进行回放时,时间约往后的视频文件卡顿越来越严重。

  怎样解决呢?一种方案从硬件解决,换一张好卡!但是这不能一劳永逸解决问题,因为录着录着写卡速度又掉下来了。另外一种方案从软件层面解决,就是卡速变慢了后,将卡格式化,但是这种方案对于用户来讲不太友好(有些用户可能不知道这个功能,或者文件删除前备份不方便)。还有一种方案,也是从软件层面解决问题,就是优化写卡策略。优化写卡策略,有一些可行的方案,例如文件预分配、待写数据进行缓冲写、编码与封装解耦,直写(DirectIO)。下面内容介绍预分配的内容。

1. fallocate介绍

  linux man手册说明:

  

  fallocate即预分配,英文为preallocate。什么意思呢?还往文件中没写数据,但是已经给文件分配了足额的物理空间来存储数据。创建了文件,再调用这个接口预分配了一定量的空间后,后续就可以往这个文件中写数据了。

  另外一点需要注意,这个接口需要文件系统的支持。常用TF卡录像,而卡的文件系统类型一般为fat32,就需要fat32文件系统相关的实现才能使用该功能。

  再有,这是一个不可移植的linux专用系统调用,用于确保文件空间被提前分配,成功执行后,可以确保写卡速度较快,也能保证不会因为磁盘空间不足而出现写失败。

2 .   接口声明

函数原型

int fallocate(int fd,int mode,off_t offset,off_t len);

fd

文件句柄

mode

创建模式

offset

偏移

len

文件大小

  其中,在创建了文件后和写数据前,需要调用该接口进行预分配,第二个参数mode一般设置为1,第三个参数设置为0,第四个参数填上期望预分配值。

3. 应用场景及目标

  应用场景:持续写卡场景,例如行车记录仪、运动相机。

  目标:减少磁盘碎片化,提高写卡速度。

  其他说明:录像设备的瓶颈常常是写卡,因为要随时将视频文件记录下来。并且,对持续写卡速度要求较高,因为录像设备工作周期可能是以day为单位,不仅要求录像刚启动时写卡正常,而且要求工作了几天写卡速度也不能掉太多。至于每秒钟写入的数据量,视编码器输出码率和几路录像而定,对于单路1080p录制,视频码率设置为10mbps,那么卡速至少要保证2MB/s,这里面还不包括写log以及录像中拍照所用的。

  虽然目前时间节点上(2019年末),市面上卡都是C10(10MB/s)及其以上,但是如果写策略不合理或卡中太多零碎文件,写速度可能很低。很常见的一个例子,拷贝一个视频文件到T卡的速度,要远远大于拷贝同样大小的源文件包。另一个例子是,一个刚格式化的T卡与一个内部已经存在了很多文件的T卡(卡品牌、容量、速度等参数都一样),拷贝同样大小的文件,刚格式化的那张卡速度更快。

4. 实现原理

  TF卡(TransCard)和SSD(SolidStateDisk)作为常见的存储设备,内部组成非常类似,都主要由controler和nand flash组成。对于任何存储设备,我们都最关心三个参数:容量、读/写速度、寿命。

  “容量”这个参数勿用介绍,“读速度”也不介绍,下面主要说下“寿命”和“写速度”这两个参数。介绍这两个参数后,再来介绍预分配。

4.1  寿命相关:

  寿命主要由存储介质决定,即nand flash这种介质的可擦写次数,nand flash介质类型的发展经历了slc、mlc、tlc、qlc(目前市面上还较少)几个阶段,单位面积的容量也越来越大,因为介质类型反映了存储密度。小小的TF卡,就目前2019年末的这个时间节点上,市面上已经出现了512GB容量的TF卡,存储多个图书馆书籍的文字信息应该毫无压力!但是,凡事有利有弊,随着容量的提升,TF内部的最小存储单元的可擦写次数也越来越少。

  SLC(SingleLevelCell)出现最早,可擦写次数10多万次;后来出现的MLC(MultiLevelCell)可擦写次数3000-10000次左右,目前主流的TLC的可擦写次数在500-1000次左右。在某东上随便查看了lexar的某款500GB 容量的SSD,其参数如下:

  从中看到闪存类型为TLC,还有TBW=250T这个参数,这个是什么以及怎么得来的呢?

  TBW,即TeraBytesWritten,以TB为单位的写入的数据量。这个值这样算:总容量*可写次数,即500GB*500 = 250TB。其中的500代表平均可写次数为500,是根据闪存类型TLC来估算的。一般企业级的用的sdd,价格较民用的高不少,例如编译/数据库服务器,相同容量的TBW值通常是以PBW(=1024TBW)为单位的,不太追求读写速度,但非常看重寿命和可靠性,毕竟数据是无价的。

4.2  速度相关:

  写速度是个比较玄乎的东西,由许多因素综合导致,例如,闪存类型、主控算法(固件磨损平衡算法)、文件系统写策略、卡的碎片化程度、卡的文件系统类型和block大小、内部是否带Cache以及其大小,等等诸多因素。

  但是,针对确定下来的一张卡,我们需要找到一些方法,来提高写卡速度。其中一种方法就是预分配——fallocate。

  接下来先介绍文件存储相关的内容后,再来介绍这个预分配接口的作用。

  对于fat32的文件系统,存储设备中的某文件,其内容主要包括两部分:一部分是属性信息metadata(创建/修改时间、文件名称、文件大小等),另一部分是真正的数据内容。常用的fdatasync操作只会强制将真正的数据内容刷新到存储设备中,而fsync会将两部分内容都刷新到设备中。对于真正的数据内容那部分,有一个链表来管理各个块内容所在的SectorId,即以sector链表的形式来完整表述数据内容。因此,某文件的存储物理地址可能是某连续sector区所在的一整片区域,也可能分布于多个不连续的物理区域。

  存储设备的碎片化与内存碎片化非常类似,即某文件希望尽可能利用连续的物理存储空间来存储数据,但是由于卡已处于高度碎片化状态,当真正写入完这个文件时,这个文件在物理空间上是“支离破碎”的。即使是一个刚刚格式化的卡,当两个线程同时分别写两个不同文件时,在物理空间上(内部连续的物理block或sector),这两个文件可能处于交织状态(交错),英文为interleave。做过音频开发的同事也可以回想一下alsa-lib在打开设备进行参数配置时,针对双声道pcm数据采集,有interleave和non-interleave的配置,这个选择决定了左右声道pcm数据在一个period内如何排列,类似对比,卡中存储的多个文件,对于物理block就是这个意思。

  设想一种写文件场景,使用正常fopen-fwrite-fclose的操作流程,只写一路,当每次将kernel cache中的数据刷到卡中前,需要现场去找(类似于写磁盘时的寻道)哪个物理sector是available的,当发现某个block中的某个sector是可用的,但是其他sector是其他文件占用的,那么接下来的策略就是copy-modify-write,即出现了“写放大”(WriteAmplification)。

  为什么出现这个状况,需要了解闪存的基本组成:页page(也称sector,大小4KB) -> 块block(通常64或128个page组成一个block) -> 面plane(多个block组成) –> die(plane就是一个die) -> 闪存片(多个die组成) –> SSD或TF(多颗闪存片组成)。

  下面描述下写放大过程:先把整个block中的数据完全拷贝到ddr,再将某个sector中的数据修改为期望写入的数据,擦掉ssd中这个block的内容,然后再整体将ddr中的已修改好的数据写入到ssd中这个block位置。为什么要这样做?因为写入是按block为最基本单位进行的。所以写入一笔数据,涉及了多次基本操作,不仅减慢了写速度,而且减少了寿命。然而,当进行了预分配后,提前为某文件划分了“势力范围”,标定某些位置已经被占用,可以减少后续的写放大和寻找可用空间的过程。

4.3  预分配原理:

  介绍了文件存储结构的相关内容后,对于预分配的功能我们就有了大致的猜测!fallocate这个接口,其要实现的目的,就是在数据内容还未写入到设备前,提前为文件分配好若干大小的空间,并且使这个空间尽可能是物理连续的,这样可以减少后续写放大的出现频率,以及不需在写入过程中寻找可用空间,更不会出现写数据时磁盘空间不足的问题!

5. 其他问题

  使用预分配一个最大的问题是——磁盘空间利用率不高!这个如何说起?文件刚创建还未写入数据,我们就抢先为文件设置了文件的大小并占用了固定大小的物理空间,但通常可能未写入那么大size的数据量就fclose了这个文件,那么这个文件内未写入的空间就不能被其他文件利用了。一个文件预分配了100MB,即使只写入1MB就关闭,那么就有99MB的空间浪费。但是,使用预分配对于行车记录仪类产品是个较优的选择,因为文件切换是定时切换的,如果编码器输出码率是相对稳定的,就可以预估最终文件大小,预分配的大小再留些余量就可以了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


linux常用进程通信方式包括管道(pipe)、有名管道(FIFO)、信号(signal)、消息队列、共享内存、信号量、套接字(socket)。管道用于具有亲缘关系的进程间通信,有名管道的每个管道具有名字,使没有亲缘关系的进程间也可以通信。信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除
Linux性能观测工具按类别可分为系统级别和进程级别,系统级别对整个系统的性能做统计,而进程级别则具体到进程,为每个进程维护统计信息。

按实现原理分,可分为基于计数器和跟踪以及剖析。含义如下:

计数器:内核维护的统计数据,通常为无符号整型,用于对发生的事件计数,比如,网络包接收计数器,磁
本文详细介绍了curl命令基础和高级用法,包括跳过https的证书验证,详细追踪整个交互过程,可用于调用网络后端接口,诊断http和https网络服务故障。
本文包含作者工作中常用到的一些命令,用于诊断网络、磁盘占满、fd泄漏等问题。命令包括ping、fping、tcpdump、lsof、netstat、/proc/$pid/fd、du、grep、traceroute、dig。
linux的平均负载表示运行态和就绪态及不可中断状态(正在io)的进程数目,用uptime查看到负载很高,既有可能是CPU利用率高,也可能是大量在等待io的进程导致,用mpstat查看每个CPU的使用情况,查看CPU的使用率或者CPU花在等待io的时间,接着用pidstat定位具体的进程
CPU上下文频繁切换会导致系统性能下降,切换分为进程切换、线程切换及中断切换,进程切换的开销较大,除了需要保存寄存器和程序计数器中的值还需保存全局变量、栈等到内存中,以便下次运行恢复,而同一进程中的线程切换开销会小很多,只需更新寄存器和线程独有的栈,共享资源如打开的文件、全局变量等无需切换,当硬件中
1.top命令 作用:该命令可以按CPU使用.内存使用和执行时间对任务进行排序,常用来监控系统中占用CPU或内存较高的程序及CPU和内存的负载。 默认视图: 当想看系统负载时,可观察汇总的%CPU中的us用户进程和sy系统进程是否占用CPU很高,相加接近100%就说明占用很高了,有些程序可能得不到及
文章浏览阅读1.8k次,点赞63次,收藏54次。Linux下的目录权限!!!粘滞位!!!超详解!!!
文章浏览阅读1.6k次,点赞44次,收藏38次。关于Qt的安装、Windows、Linux、MacBook_mack book 安装qt
本文介绍了使用shell脚本编写一个 Hello
文章浏览阅读1.5k次,点赞37次,收藏43次。【Linux】初识Linux——了解操作系统的发展历史以及初次体验Linux编程环境
文章浏览阅读3k次,点赞34次,收藏156次。Linux超详细笔记,个人学习时很认真的记录的,觉得好的麻烦点个赞。
文章浏览阅读6.8k次,点赞109次,收藏114次。【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.5p1(亲测无问题,建议收藏)_openssh_9.5p1
文章浏览阅读3.5k次,点赞93次,收藏78次。初识Linux中的线程,理解线程的各种概念,理解进程地址空间中的页表转换,介绍pthread线程库并理解线程库!
文章浏览阅读863次。出现此问题为Linux文件权限问题,解决方案为回到引擎目录执行命令。输入用户密码后运行./UnrealEditor。_increasing per-process limit of core file size to infinity.
文章浏览阅读2.9k次。使用文本编辑器:打开CSV文件,并使用文本编辑器(如Notepad++、Sublime Text、Visual Studio Code等)来查看文件的字符编码格式。通常在编辑器的底部状态栏或设置中可以找到当前编码的显示。请注意,上述方法并非绝对准确,特别是当文件没有明确的编码标识时。因此,如果你发现CSV文件在不同的工具或方法中显示不同的编码格式,可能需要进行进一步的分析和判断,或者尝试使用不同的编码转换方法。该命令将输出文件的MIME类型和编码信息。使用命令行工具:在命令行中,你可以使用。_shell读取csv文件逐行处理
本文介绍了如何在Linux系统中升级gcc版本,以便更好地支持C++11及以上版本的新特性。通过升级gcc,可以提升编译器的功能和性能,获得更好的开发体验。详细的步骤和方法请参考原文链接。
文章浏览阅读4.4k次,点赞6次,收藏19次。Mosquitto是一个开源的MQTT消息代理服务器。MQTT是一个轻量级的、基于发布/订阅模式的消息传输协议。 mosquitto的安装使用比较简单,可以方便的来进行一些测试。_linux mosquitto
文章浏览阅读7.2k次,点赞2次,收藏12次。Linux中,用于根目录下有一个.ssh目录,保存了ssh相关的key和一些记录文件。_~/.ssh/
文章浏览阅读4.5k次,点赞5次,收藏18次。首先需要安装 snmp ,使用下面的命令进行安装安装完毕之后,使用下面的命令查看是否安装成功当命令行显示如图即为安装成功。_snmp工具