C write还是printf,哪个更快?
执行以下测试后:C write还是printf,哪个更快?,c,performance,unix,io,system-calls,C,Performance,Unix,Io,System Calls,执行以下测试后: for( i = 0; i < 3000000; i++ ) { printf( "Test string\n" ); } for( i = 0; i < 3000000; i++ ) { write( STDOUT_FILENO, "Test string\n", strlen( "Test string\n" ) ); } (i=0;i
for( i = 0; i < 3000000; i++ ) {
printf( "Test string\n" );
}
for( i = 0; i < 3000000; i++ ) {
write( STDOUT_FILENO, "Test string\n", strlen( "Test string\n" ) );
}
(i=0;i<3000000;i++)的{
printf(“测试字符串\n”);
}
对于(i=0;i<3000000;i++){
写入(STDOUT_FILENO,“测试字符串”,strlen(“测试字符串”);
}
结果表明,对printf的调用总共需要3秒,而对write的调用则需要46秒。有了printf
所具有的所有奇特的格式化魔法,以及printf
本身调用write
,这怎么可能呢?有什么我遗漏的吗
感谢您的任何想法和输入。您不是在对苹果进行比较,因为
write
的循环会运行strlen
<3000000次,而printf
不会执行任何操作;它也不做任何格式化,所以“奇特的格式化魔法”几乎不适用
size_t len = strlen( "Test string\n" );
for( i = 0; i < 3000000; i++ ) {
write( STDOUT_FILENO, "Test string\n", len );
}
size\u t len=strlen(“测试字符串”);
对于(i=0;i<3000000;i++){
写入(标准输出文件号,“测试字符串”,len);
}
另一个重要的区别是,printf
每次通过\n
时都会刷新,而write
则不会。您应该从两个字符串中删除\n
,以使基准测试更加公平
如何,与。。。printf本身调用write,这可能吗?有什么我遗漏的吗
是的,有些东西你遗漏了printf
不一定每次都调用write
。相反,printf
缓冲其输出。也就是说,它通常将其结果存储在内存缓冲区中,仅在缓冲区已满时或在某些其他条件下调用write
write
是一个相当昂贵的调用,比将数据复制到printf
的缓冲区要昂贵得多,因此减少write
调用的数量可以获得净性能优势
如果stdout指向终端设备,则每次看到\n
--在您的情况下,每次调用它时,printf
都会调用write
。如果stdout指向文件(或/dev/null
),则printf
仅在其内部缓冲区已满时调用write
假设您正在重定向输出,并且printf
的内部缓冲区是4Kbytes,那么第一个循环调用write
3000000/(4096/12)==8780次。但是,第二个循环调用write
3000000次
除了对write
调用较少的影响之外,还有对write
调用的大小。硬盘中的存储量是一个扇区,通常为512字节。要写入的数据量小于扇区,可能需要读取扇区中的原始数据,对其进行修改,然后将结果写回。但是,使用完整扇区调用write
,可能会更快,因为您不必读入原始数据printf
的缓冲区大小被选择为典型扇区大小的倍数。这样系统可以最有效地将数据写入磁盘
我希望你的第一圈比第二圈快得多。真的吗?您每次都在计算字符串长度,然后将其作为计时的一部分进行测量?@K-ballo经过优化,在编译过程中只应计算一次。您的输出是发送到控制台还是发送到文件?如果是控制台,那么它的成本将淹没一切。@MikeDunlavey甚至将stdout重定向到一个文件make
write
需要相当长的时间,而printf
的速度非常快。然而,重定向到/dev/null
,两者都很快。然后,write
需要更少的用户时间,但是更多的系统时间和更长的时间,但是时间是相同的数量级(Linux x86_64,gcc-4.5.1)。put
应该更快。在我的系统上,gcc-4.5.1在编译时评估strlen
,即使没有优化。冲洗/缓冲似乎是造成差异的原因。@Danielfisher谢谢!很高兴知道,gcc
足够聪明,可以将strlen
表达式折叠成一个常量。printf
不会在每个\n
上刷新,如果输出重定向到文件。另外,更准确的说法是,write
每次刷新,不包含任何内容——毕竟,在这个上下文中,“flush”只意味着“callswrite
”@dasblinkenlight指出,要将以null结尾的字符串复制到目的地,必须计算其长度,或者一个字符一个字符地复制。@ChrisStratton但是当您一个字符一个字符地输出一个字符串时,您仍然只能从内存中读取每个字符一次,而不是两次。write
和printf
都需要将字符串中的所有字符移动到I/O系统拥有和管理的内存中的某个位置,这些字符最终从该位置进入磁盘或tty(我有意避免使用“缓冲区”一词)<当到达\0
字符时,code>printf将停止<当传入的计数用完时,code>write将停止。这很好地解释了一切。非常感谢。关于您对数据大小的评论…为什么不需要读取原始数据,因为它完全适合该行业?write调用是否仍然需要知道需要写入的数据?