SD卡写入性能

5

我正在编写一个小应用程序,它以恒定的速度在SD卡上写入jpeg图像。我选择了EXT3文件系统,但在EXT2文件系统中观察到了相同的行为。

我的写入循环如下:

get_image()
fwrite()
fsync()

或者像这样:
get_image()
fopen() 
fwrite()
fsync()
fclose()

我也显示了一些时间统计数据,我可以看到我的程序有时会被阻塞几秒钟。平均速率还不错,因为如果我将传入的图像保留在FIFO中,那么在这样的停顿之后,我将在短时间内写入许多图像。你知道这是操作系统的问题还是与SD卡本身有关吗?我该如何更接近实时?我不需要强实时性,但被阻塞几秒钟是不可接受的。
一些精度: 是的,每个文件后都需要执行fsync,因为我希望图像在磁盘上而不是在某些用户或内核缓冲区中。没有进行fsync,我有更好的吞吐量,但仍然有无法接受的停顿。我不认为这是一个缓冲问题,因为第一个停顿发生在写入50 Mbytes之后。根据手册,fsync的目的是确保没有数据被缓冲。
关于平均写入速率的精度: 我正在以该卡可持续的速率进行写入。如果我在等待fsync完成时堆积传入的图像,那么在此停顿之后,写入传输速率将增加,我将快速返回平均速率。平均传输速率约为1.4 MBytes / s。
该系统是运行Ubuntu 8.04的现代笔记本电脑,使用的是默认内核(2.6.24.19)。
7个回答

4
尝试使用O_DIRECT打开文件,并在应用程序级别进行缓存。我们实现STB Box中的PVR(个人视频记录)功能时遇到了类似的问题。最终,O_DIRECT技巧满足了我们的需求。(*)如果没有O_DIRECTwrite()的数据将首先被缓存在内核缓冲区中,然后在调用fsync或内核缓存缓冲区已满时刷新到介质中。(**)有了O_DIRECT,内核将直接对指向作为参数传递给write系统调用的用户空间缓冲区的物理内存进行DMA。因此,在用户空间内存和内核缓存之间的复制中不会花费CPU和内存带宽,在缓存管理方面也不会花费内核中的CPU时间(例如缓存查找、每页锁等)。(从here复制)不确定它是否也可以解决您的问题,但您可能想尝试一下。

*尽管Linus批评了O_DIRECT,但它确实解决了我们的问题。

**假设您没有使用O_DSYNCO_SYNC打开文件。


非常有趣。我认为缓存的问题在于所有I/O请求(在这个特定的系统上)都通过一个单一的队列进行。 如果块设备(磁盘)正在刷新其日志信息,则对另一个块设备(SD卡)的非相关写入将被阻止。我会尝试使用O_DIRECT。 - shodanex

3

每个文件都需要进行fsync()吗?你可以让操作系统决定何时将所有排队的图像写入SD卡(通过在多个图像上分摊操作SD卡文件系统的启动成本,而不是为每个图像承担它)。

您能提供有关您平台的更多详细信息吗?慢速I/O时间可能与系统中的其他进程、慢速I/O控制器等有关。

您还可以考虑使用更适合闪存工作方式的文件系统。FAT32比extN更常见,但专门为SD构建的文件系统也是必要的。JFFS是一个很好的例子。与旋转磁介质相比,使用为闪存设计的文件系统会获得更好的性能,并且具有更好的耐用性和设备寿命/可靠性属性。


请注意,对于一些具有自己的磨损平衡功能的闪存设备(如CompactFlash),JFFS等可能不是一个好主意。 - Hasturkun
1
它们是一个坏主意,还是CompactFlash磨损平衡只是抵消了JFFS的好处?这是一个诚实的问题,我不知道。我同意对于“原始”闪存设备来说,它肯定是更好的选择。 - Matt J

2
据我所知,一些闪存盘的写入性能非常差(尤其是廉价品牌)。因此,如果您测量应用程序的写入速度(包括执行fsync所需的时间),您得到什么结果?这很容易只有几兆字节每秒 - 只是因为硬件没有更好的表现。
此外,如果您写许多小块而不是一个大块,编写速度可能会慢得多(在糟糕的情况下,闪存可能只完成约10次写入每秒)。这可能是可以通过内核缓冲区缓解的问题,因此频繁使用fsync可能会降低写入速度...
顺便问一下,您是否在FAT32上测量了写入性能?我猜它大致相同,但如果不是,则可能仍然有一些优化可用?

1

也许这会有所帮助 - 文件系统基准测试

...我很惊讶ext3在整体上有多慢,因为许多发行版使用它作为默认文件系统...

还有"ext3 fsync批处理"

...这个补丁测量将交易提交到磁盘所需的时间,并根据底层磁盘的速度进行睡眠。


1

我在这个领域不是很有知识,但你描述的症状听起来非常像填充缓冲区。您可能正在文件编写器或与SD卡通信的I/O设备中填充缓冲区。然后,您必须等待它实际将数据写入卡片(从而清空缓冲区)才能继续写入更多数据。SD卡的写入速度并不特别快。如果您可以找到一种方法来检查在这些暂停期间是否实际写入了数据到卡片上,那么这将验证我的理论。一些读卡器在访问数据时会闪烁LED - 这可能是一个很好的指标。

只是一个直觉...带点儿盐吧 :)


0

对于任何正在使用2.6.28以上内核的人,建议使用ext4而不是ext3,这是一个可以调整以获得更好性能的文件系统。最佳性能是在data=writeback模式下获得的,其中数据未被日志记录。请阅读https://www.kernel.org/doc/Documentation/filesystems/ext4.txt中的Data Mode部分。

如果您已经创建了一个分区,比如说/dev/sdb1,那么以下是一些可以用来格式化它为ext4而不进行日志记录的步骤:

mkfs.ext4 /dev/sdb1 -L jp  # Creates the ext4 filesystem
tune2fs -o journal_data_writeback /dev/sdb1 # Set to writeback mode
tune2fs -O ^has_journal /dev/sdb1 # Disable journaling
sudo e2fsck -f /dev/sdb1 # Filesystem check is required

然后,您可以使用相应的标志挂载此分区(或者如果您知道自己在做什么,则可以设置一个条目/etc/fstab):

mount -t ext4 -O noatime,nodirame,data=writeback /dev/mmcblk0p1 /mnt/sd

从ext3文件系统切换到优化的ext4文件系统应该会有显著的差异。当然,如果您的SD卡更快,那应该会有所帮助(即class 10)。

另请参阅https://developer.ridgerun.com/wiki/index.php/High_performance_SD_card_tuning_using_the_EXT4_file_system


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接