提供相同的程序,该程序读取随机生成的输入文件并回显相同的字符串,然后将其读取到输出.唯一的区别是,在一边,我提供的读取和写入从Linux系统调用的方法,并在另一边我用FREAD/FWRITE.
使用大小为10Mb的输入来定时我的应用程序并将其回显到/ dev/null,并确保文件没有被缓存,我发现当使用非常小的缓冲区时,libc的fwrite速度更快(1个字节)案件).
这是我的时间输出,使用fwrite:
real 0m0.948s
user 0m0.780s
sys 0m0.012s
Run Code Online (Sandbox Code Playgroud)
并使用syscall写:
real 0m8.607s
user 0m0.972s
sys 0m7.624s
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一可能性是内部libc已经缓冲了我的输入......不幸的是我无法在网络上找到那么多信息,所以也许这里的大师可以帮助我.
我一直在Google上搜索一种在mac os下进行原始(有时称为直接)i/o的方法.操作系统页面缓存的原始i/o转动使应用程序可以更直接地访问磁盘.这很有用,因为我使用的某些文件结构使用LRU页面替换效率不高.实现我们需要的页面替换算法是相当直接的,但首先我们需要关闭os x默认缓冲.我们已经在打开文件时使用O_DIRECT标志在linux下完成了这个.有没有人知道如何在mac os下关闭页面缓冲?
干杯蒂姆
从我可以收集,然后使用POSIXO_DIRECT与open()阻断设备文件的工作方式的方式既结合同FILE_FLAG_WRITE_THROUGH,并FILE_FLAG_NO_BUFFERING与CreateFile()在Windows上-这是正确的我假设?
打开:
O_DIRECT尽量减少进出该文件的 I/O 的缓存影响。通常这会降低性能,但它在特殊情况下很有用,例如当应用程序执行自己的缓存时。文件 I/O 直接进出用户空间缓冲区。
创建文件:
如果FILE_FLAG_WRITE_THROUGH使用,但FILE_FLAG_NO_BUFFERING 是不是也规定,使系统缓存中的效果,然后将数据写入到系统缓存,但被刷新到磁盘刻不容缓。如果FILE_FLAG_WRITE_THROUGH和FILE_FLAG_NO_BUFFERING 都被指定,那么系统缓存没有生效,那么数据会立即刷新到磁盘而不经过 Windows 系统缓存。操作系统还请求将硬盘的本地硬件缓存写入持久性媒体。
如果我打开带有O_DIRECT标志的文件,是否意味着每当对该文件的写入(阻塞模式)返回时,数据都在磁盘上?
在阅读 本文时,我找到了一个合理的答案,其中说:
案例1:直接写入磁盘上的文件
Run Code Online (Sandbox Code Playgroud)100 times x 1 ms = 100 ms
我明白.下一个,
案例3:在写入磁盘上的文件之前在内存中缓冲
Run Code Online (Sandbox Code Playgroud)(100 times x 0.5 ms) + 1 ms = 51 ms
我不明白1毫秒.将100个数据写入磁盘和将1个数据写入磁盘之间有什么区别?为什么两个都花费1毫秒?
在我的代码中,我有一种情况需要将数据从一个文件复制到另一个文件.我想出的解决方案如下:
const int BUF_SIZE = 1024;
char buf[BUF_SIZE];
int left_to_copy = toCopy;
while(left_to_copy > BUF_SIZE)
{
fread(buf, BUF_SIZE, 1, fin);
fwrite(buf, BUF_SIZE, 1, fout);
left_to_copy -= BUF_SIZE;
}
fread(buf, left_to_copy, 1, fin);
fwrite(buf, left_to_copy, 1, fout);
Run Code Online (Sandbox Code Playgroud)
我的主要想法是可能有类似memcpy的东西,但是对于文件中的数据.我只给它两个文件流和总字节数.我搜索了一下,但我找不到任何这样的东西.
但是如果没有这样的东西,我应该使用什么缓冲区大小来实现最快的传输?更大意味着更少的系统调用,但我认为它可能会破坏系统上的其他缓冲或缓存.我应该动态分配缓冲区,以便只进行一对读/写调用吗?在这种特定情况下,典型的传输大小是从几KB到十几MB.
编辑:对于操作系统特定信息,我们使用的是Linux.
EDIT2:
我尝试使用sendfile,但它没有用.它似乎写了适量的数据,但它是垃圾.
我用上面这样的东西替换了我的例子:
fflush(fin);
fflush(fout);
off_t offset = ftello64(fin);
sendfile(fileno(fout), fileno(fin), &offset, toCopy);
fseeko64(fin, offset, SEEK_SET);
Run Code Online (Sandbox Code Playgroud)
我添加了flush,offest,并且一次寻找一个,因为它似乎没有工作.