【发布时间】:2013-01-31 15:34:22
【问题描述】:
我有一个关于文件 IO(C 语言)及其性能问题的问题。
我有一个执行大量文件 I/O 的应用程序(在其生命周期内大约 3-6 小时,大约 0.5-0.75TB,主要是文件输出)。
目前我的应用程序sprintf()s 将所有内容转换为一个字符字符串,并在write()s 行的末尾转换为file_descriptor。我的字符串长度为 1024 个字符,但可以在 64 到 1024 之间变化。无论如何。
问题是:
在执行write() 之前先将一个更大的字符字符串(比如1MB?)和sprintf() 全部放入其中是否更有意义?或者,假设缓冲由write() 负责,那么完全直接跳过write() 到文件中是否更有意义?
我想到了一些东西,但不确定它是否真的会在性能方面取得任何成就:
如果我有一个结构来存储字符串、数字和字符串的各个部分,并改为对结构执行 mem_copy 呢?我猜类似于二进制写入?
我正在尝试实现“缓冲”方法或任何可以最大限度提高性能的方法。 后者是我需要使用该文件进行进一步处理。 有什么建议吗?
编辑
我与printf(); + redir 和sprintf(); write(); 做了一些简单的性能比较
我只是将~20GB 复制到一个文件中。
char string[1024];
for(i=0;i<(1<<20)*20;i++)
printf("%s",string);
~/tmp/tests$ time ./printf.out > testing
real 2m22.101s
user 0m28.214s
sys 0m29.294s
相对于:
char string14[256]; ...etc
for(i=0;1<<(1<<20)*20;i++){
sprintf(dst_string,"%s%s",dst_string, string14);
sprintf(dst_string,"%s%s",dst_string, string24);
sprintf(dst_string,"%s%s",dst_string, string34);
sprintf(dst_string,"%s%s",dst_string, string44);
write(fd, dst_string, 1024);
}
~/tmp/tests$ time ./write.out
real 1m48.206s
user 0m58.544s
sys 0m41.079s
多个sprintf()s的原因是模拟copy->buffer再写buffer。 时间(无论如何都是真实的)并不像某些 cmets 所暗示的那样微不足道。当然这是一个简单的例子,也许在计算 + IO 的方案中可能不会。
在 printf 示例中我有点困惑,额外的时间都去哪儿了?用户+系统不加起来是真实的,他们至少不应该在球场上吗?因为缺了整整 1:30m。
此测试是否显示任何结论? sprintf + write > 简单地打印+redir?
无论如何,谢谢大家的cmets。
【问题讨论】:
-
仅使用
printf可能(几乎可以肯定)优于sprintf,然后是write。 -
你不应该假设缓冲是由
write处理的。实际上,您应该假设write根本没有缓冲。 -
但这会写入标准输出,我必须重定向它,这很慢,受终端限制,不是吗?哦,我没有可用的 fprintf。
-
操作系统会为您完成大部分缓冲工作。要真正了解发生了什么,请查看操作系统文档。
-
重定向并不慢,为什么你认为它是'受终端限制'?它是从一个进程到另一个进程的管道。