- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
可以肯定的是,缓冲 I/O 到磁盘上的文件比无缓冲更快。但为什么即使写入内存缓冲区也有好处?
以下基准代码示例是使用 gcc 5.40 使用优化选项 -O3 编译的,链接到 glibc 2.24。 (请注意,通用 glibc 2.23 存在与 fmemopen() 有关的错误。)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
int main() {
size_t bufsz=65536;
char buf[bufsz];
FILE *f;
int r;
f=fmemopen(buf,bufsz,"w");
assert(f!=NULL);
// setbuf(f,NULL); // UNCOMMENT TO GET THE UNBUFFERED VERSION
for(int j=0; j<1024; ++j) {
for(uint32_t i=0; i<bufsz/sizeof(i); ++i) {
r=fwrite(&i,sizeof(i),1,f);
assert(r==1);
}
rewind(f);
}
r=fclose(f);
assert(r==0);
}
缓冲版本的结果:
$ gcc -O3 -I glibc-2.24/include/ -L glibc-2.24/lib test-buffered.c
$ time LD_LIBRARY_PATH=glibc-2.24/lib ./a.out
real 0m1.137s
user 0m1.132s
sys 0m0.000s
无缓冲版本的结果
$ gcc -O3 -I glibc-2.24/include/ -L glibc-2.24/lib test-unbuffered.c
$ time LD_LIBRARY_PATH=glibc-2.24/lib ./a.out
real 0m2.266s
user 0m2.256s
sys 0m0.000s
最佳答案
缓冲版本性能记录:
Samples: 19K of event 'cycles', Event count (approx.): 14986217099
Overhead Command Shared Object Symbol
48.56% fwrite libc-2.17.so [.] _IO_fwrite
27.79% fwrite libc-2.17.so [.] _IO_file_xsputn@@GLIBC_2.2.5
11.80% fwrite fwrite [.] main
9.10% fwrite libc-2.17.so [.] __GI___mempcpy
1.56% fwrite libc-2.17.so [.] __memcpy_sse2
0.19% fwrite fwrite [.] fwrite@plt
0.19% fwrite [kernel.kallsyms] [k] native_write_msr_safe
0.10% fwrite [kernel.kallsyms] [k] apic_timer_interrupt
0.06% fwrite libc-2.17.so [.] fmemopen_write
0.04% fwrite libc-2.17.so [.] _IO_cookie_write
0.04% fwrite libc-2.17.so [.] _IO_file_overflow@@GLIBC_2.2.5
0.03% fwrite libc-2.17.so [.] _IO_do_write@@GLIBC_2.2.5
0.03% fwrite [kernel.kallsyms] [k] rb_next
0.03% fwrite libc-2.17.so [.] _IO_default_xsputn
0.03% fwrite [kernel.kallsyms] [k] rcu_check_callbacks
无缓冲版本性能记录:
Samples: 35K of event 'cycles', Event count (approx.): 26769401637
Overhead Command Shared Object Symbol
33.36% fwrite libc-2.17.so [.] _IO_file_xsputn@@GLIBC_2.2.5
25.58% fwrite libc-2.17.so [.] _IO_fwrite
12.23% fwrite libc-2.17.so [.] fmemopen_write
6.09% fwrite libc-2.17.so [.] __memcpy_sse2
5.94% fwrite libc-2.17.so [.] _IO_file_overflow@@GLIBC_2.2.5
5.39% fwrite libc-2.17.so [.] _IO_cookie_write
5.08% fwrite fwrite [.] main
4.69% fwrite libc-2.17.so [.] _IO_do_write@@GLIBC_2.2.5
0.59% fwrite fwrite [.] fwrite@plt
0.33% fwrite [kernel.kallsyms] [k] native_write_msr_safe
0.18% fwrite [kernel.kallsyms] [k] apic_timer_interrupt
0.04% fwrite [kernel.kallsyms] [k] timerqueue_add
0.03% fwrite [kernel.kallsyms] [k] rcu_check_callbacks
0.03% fwrite [kernel.kallsyms] [k] ktime_get_update_offsets_now
0.03% fwrite [kernel.kallsyms] [k] trigger_load_balance
区别:
# Baseline Delta Shared Object Symbol
# ........ ....... ................. ..................................
#
48.56% -22.98% libc-2.17.so [.] _IO_fwrite
27.79% +5.57% libc-2.17.so [.] _IO_file_xsputn@@GLIBC_2.2.5
11.80% -6.72% fwrite [.] main
9.10% libc-2.17.so [.] __GI___mempcpy
1.56% +4.54% libc-2.17.so [.] __memcpy_sse2
0.19% +0.40% fwrite [.] fwrite@plt
0.19% +0.14% [kernel.kallsyms] [k] native_write_msr_safe
0.10% +0.08% [kernel.kallsyms] [k] apic_timer_interrupt
0.06% +12.16% libc-2.17.so [.] fmemopen_write
0.04% +5.35% libc-2.17.so [.] _IO_cookie_write
0.04% +5.91% libc-2.17.so [.] _IO_file_overflow@@GLIBC_2.2.5
0.03% +4.65% libc-2.17.so [.] _IO_do_write@@GLIBC_2.2.5
0.03% -0.01% [kernel.kallsyms] [k] rb_next
0.03% libc-2.17.so [.] _IO_default_xsputn
0.03% +0.00% [kernel.kallsyms] [k] rcu_check_callbacks
0.02% -0.01% [kernel.kallsyms] [k] run_timer_softirq
0.02% -0.01% [kernel.kallsyms] [k] cpuacct_account_field
0.02% -0.00% [kernel.kallsyms] [k] __hrtimer_run_queues
0.02% +0.01% [kernel.kallsyms] [k] ktime_get_update_offsets_now
深入源码后,发现iofwrite.c中的fwrite
,也就是_IO_fwrite
,只是对实际写入函数的一个包装函数_IO_sputn
。并且还发现:
libioP.h:#define _IO_XSPUTN(FP, DATA, N) JUMP2 (__xsputn, FP, DATA, N)
libioP.h:#define _IO_sputn(__fp, __s, __n) _IO_XSPUTN (__fp, __s, __n)
因为__xsputn
函数实际上是_IO_file_xsputn
,可以找到如下:
fileops.c: JUMP_INIT(xsputn, _IO_file_xsputn),
fileops.c:# define _IO_new_file_xsputn _IO_file_xsputn
fileops.c:versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
最后进入fileops.c中的_IO_new_file_xsputn
函数,相关部分代码如下:
/* Try to maintain alignment: write a whole number of blocks. */
block_size = f->_IO_buf_end - f->_IO_buf_base;
do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
if (do_write)
{
count = new_do_write (f, s, do_write);
to_do -= count;
if (count < do_write)
return n - to_do;
}
/* Now write out the remainder. Normally, this will fit in the
buffer, but it's somewhat messier for line-buffered files,
so we let _IO_default_xsputn handle the general case. */
if (to_do)
to_do -= _IO_default_xsputn (f, s+do_write, to_do);
在 RHEL 7.2 上,如果启用了缓冲区,则 block_size
等于 8192,否则等于 1。
所以有以下情况:
情况 1:启用缓冲区
do_write = to_do - (to_do % block_size) = to_do - (to_do % 8192)
在我们的案例中,to_do = sizeof(uint32)
所以 do_write = 0
,并将调用 _IO_default_xsputn
函数。
new_do_write
函数,之后,to_do
为零。new_do_write
只是对 _IO_SYSWRITE
libioP.h:#define _IO_SYSWRITE(FP, DATA, LEN) JUMP2 (__write, FP, DATA, LEN)
正如我们所见,_IO_SYSWRITE
实际上是 fmemopen_write
调用。因此,性能差异是由 fmemopen_write
调用引起的。之前显示的性能记录证明了这一点。
最后,这个问题很好,我对它很感兴趣,它帮助我学习了一些底层的IO函数。参见 https://oxnz.github.io/2016/08/11/fwrite-perf-issue/有关其他平台的更多信息。
关于c - 为什么缓冲写入 fmemopen()'ed FILE 比无缓冲更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38897807/
好吧,我知道这个问题已经被问了无数次了。但是,对于我在谷歌搜索中似乎无法找到的问题,我还有一个小补充。 我当然不是 FFMPEG 的专家……我一直在使用 FFMPEG 的标准加速/减速模板,我正在使用
考虑这三个文档... [ { _id: "...", _rev: "...", title: "Foo", body: "...
我想知道访问我的全局变量的最快方法...它们只会在 Beta 测试阶段发生变化。在我们上线之前。从那时起,它们将永远不会改变。 我认为从 web.config 中获取内容会产生开销,而且编写 App.
这个问题在这里已经有了答案: 11 年前关闭。 Possible Duplicate: Is there a performance difference between BETWEEN and IN
我很想知道对通常作为查询目标的数字列进行分区是否有性能优势。目前我有一个包含约 5000 万条记录的物化 View 。当使用常规 b 树索引并按此数字列搜索时,我得到的成本为 7,查询结果大约需要 0
我需要编写一个库,它执行许多远程 HTTP 调用来获取内容。我可以按照描述做here ,但是有没有更好的方法(在性能方面)如何做到这一点?如果我按照示例中所述进行操作,我总是会创建一个 URL 对象,
该代码非常不言自明。只是有很多我需要独立随机化的范围。例如,范围('W1:W4')不应与范围('W5:W8')混淆,因此我不能只是随机化范围('W1:W80')。任何帮助或建议都会很棒!多谢。目前,代
我正在使用 ADT 模拟器。我在我的模拟器中使用默认的 Android 虚拟设备。我创建了一个版本 4.0.3。 问题 太慢了。有时我在尝试更改 fragment 时会收到加载点击。 我使用的代码是有
我正在尝试获取一个包含三个表中的信息的数组。结果应该是一个数组,我可以在其中循环遍历第一个表、第二个表中的相关行以及第三个表到第二个表中的相关行。目前,我有三个独立的 SQL 查询,然后将它们重组为一
我已经学会了两种在服务器上上传图像的方法(可能还有更多..)。 1) 创建 NSData 并将其添加到请求正文中 2)创建字节数组并像简单数组一样以json形式发送 1) 创建 NSData 并将其添
我有一个 UItextview,我可以在里面写入数据类,我可以在我的 View 中的任何地方提供数据,在 ViewDidAppear 函数中我传递了我的数据,但它有点慢。文本在 0.2-0.3 秒后出
如何为 discoverAllContactUserInfosWithCompletionHandler 创建优先级高于默认值的 CKOperation? 我找不到不使用 [[CKContainer
我在 unix 模块下编写了一个内核级函数,用于对系统负载进行采样。我在 clock.c 下的 clock() 中调用示例函数,以在每个时钟(例如,我的系统上每 10 毫秒)拍摄系统负载的快照。有没有
我正在制作一个应用程序,该应用程序将根据变量的值使用鼠标/键盘(宏)模拟操作。 这里有我制作的 de 扫描代码: void ReadMemory(int value){ DWORD p
我想知道在计算上调用嵌套在对象中的函数的最快方法是什么,所以我做了一个快速的 jsPerf.com 基准测试,其中我考虑了三种可能性——从数组中调用函数,从“核心”中调用函数对象和函数对象: var
我用 php 做了一个图像缩放器。调整图像大小时,它会缓存一个具有新尺寸的新 jpg 文件。下次您调用确切的 img.php?file=hello.jpg&size=400 时,它会检查是否已经创建了
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Which is best for data store Struct/Classes? 考虑我有一个 Em
我正在尝试为多组列自动计算每行的平均分数。例如。一组列可以代表不同比例的项目。这些列也被系统地命名 (scale_itemnumber)。 例如,下面的虚拟数据框包含来自三个不同比例的项目。(可能会出
所以我知道散列图使用桶和散列码等等。根据我的经验,Java 哈希码并不小,但通常很大,所以我假设它没有在内部建立索引。除非哈希码质量很差导致桶长度和桶数量大致相等,否则 HashMap 比名称-> 值
假设我有一个非常缓慢和大的 for 循环。 如何将其拆分为多个线程以使其运行速度更快? for (int a = 0; a { slowMet
我是一名优秀的程序员,十分优秀!