我使用以下代码复制大小约为1.1 GB的文件
#include <iostream>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctime>
using namespace std;
int main ()
{
clock_t start, end;
start = clock();
int read_fd;
int write_fd;
struct stat stat_buf;
off_t offset = 0;
/* Open the input file. */
read_fd = open ("source", O_RDONLY);
/* Stat the input file to obtain its size. */
fstat (read_fd, &stat_buf);
/* Open the output file for writing, with the same permissions as the
source file. */
write_fd = open ("destination", O_WRONLY | O_CREAT, stat_buf.st_mode);
/* Blast the bytes from one file to the other. */
sendfile (write_fd, read_fd, &offset, stat_buf.st_size);
/* Close up. */
close (read_fd);
close (write_fd);
end = clock();
cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
cout << "CPU-TIME START " << start << "\n";
cout << "CPU-TIME END " << end << "\n";
cout << "CPU-TIME END - START " << end - start << "\n";
cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
输出是:
CLOCKS_PER_SEC 1000000
CPU-TIME START 0 CPU-TIME END 6140000
CPU-TIME END - START 6140000 TIME(SEC) 6.14
但是,当我实际计算时间时,它(复制)需要大约84秒的时间!!!
现在我将在下面的代码中使用“structure timeval”,输出为:83 456677
它与实际时间几乎相同。
#include <iostream>
#include <sys/sendfile.h> // sendfile
#include <fcntl.h> // open
#include <unistd.h> // close
#include <sys/stat.h> // fstat
#include <sys/types.h> // fstat
#include <ctime>
extern "C" {
#include <sys/time.h>
}
#include <stdio.h>
using namespace std;
int main() {
struct timeval diff, startTV, endTV;
gettimeofday(&startTV, NULL);
int source = open("source", O_RDONLY, 0);
int dest = open("distination", O_WRONLY | O_CREAT /*| O_TRUNC/*/, 0644);
// struct required, rationale: function stat() exists also
struct stat stat_source;
fstat(source, &stat_source);
sendfile(dest, source, 0, stat_source.st_size);
close(source);
close(dest);
gettimeofday(&endTV, NULL);
timersub(&endTV, &startTV, &diff);
printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);
return 0;
}
然后我将使用'pv source&gt; destination'a命令然后输出为1.02e+03MB 0:01:24 [12.1MB/s] [===========================>] 100%
,它与实际时间相同。
此外,当我以图形模式(普通复制/粘贴)复制文件时,需要大约84秒的时间。
问题
答案 0 :(得分:1)
以第一种方式计算的时间是多少?
这是您的程序花在使用CPU上的时间。 clock()测量CPU时间。复制文件 通常花费大部分时间做其他事情(I / O,例如等待硬盘移动或响应,等待内核中的锁定,等等。)。
'pv'或Pipe Viewer是否正确显示了OS复制文件所需的时间?
它显示从收到第一个字节到收到最后一个字节所花费的时间。
请记住,写入文件通常只是写入文件系统缓存,因此它只是写入RAM。操作系统会在闲暇时将该缓存刷新到驱动器,这可能是在您的程序,cp
程序或您使用的任何GUI文件管理器之后表示复制已完成。 (这不是真正的问题,除非你切断电源,从你复制的文件读取通过相同的缓存)。
如果要确保将数据刷新到驱动器,请在文件描述符上调用fdatasync()。
这也意味着您可以轻松地测量复制文件的不同时间。如果文件或其中的一部分恰好驻留在文件系统缓存中,那么您正在从RAM中读取。如果它不在缓存中,则需要从驱动器中读取,这可能要慢一两个数量级。
我们总结一下,sendfile()复制所用的时间与OS几乎相同吗?
对不起,我不知道你在这里问的是什么..
答案 1 :(得分:0)
不是您问题的直接答案,但您可能会发现strace -T
非常有用,除非您绝对需要在您的程序中存储统计信息。
测试
$ cat /dev/urandom > chunk.bin
^C
$ strace -T cp -p chunk.bin dust.bin
输出(参见每个系统调用后三角括号中的数字)
stat("dust.bin", 0x7fff747c5640) = -1 ENOENT (No such file or directory) <0.000303>
stat("chunk.bin", {st_mode=S_IFREG|0664, st_size=19202048, ...}) = 0 <0.000341>
stat("dust.bin", 0x7fff747c5290) = -1 ENOENT (No such file or directory) <0.000281>
open("chunk.bin", O_RDONLY) = 3 <0.000272>
fstat(3, {st_mode=S_IFREG|0664, st_size=19202048, ...}) = 0 <0.000272>
open("dust.bin", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4 <0.000404>
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 <0.000272>
read(3, "\216\330A\27J\373\1a\10\262&\221B\255\271\227\342:\252?\334\3169a\212\27\205=+\300\273\370"..., 32768) = 32768 <0.000684>
write(4, "\216\330A\27J\373\1a\10\262&\221B\255\271\227\342:\252?\334\3169a\212\27\205=+\300\273\370"..., 32768) = 32768 <0.000359>
read(3, "\327\344\343|\243\247\211\200\211\212\331\247WF\324\33\276\317\241[{\24\354D\223\215\332\247\34\376\246W"..., 32768) = 32768 <0.000494>
write(4, "\327\344\343|\243\247\211\200\211\212\331\247WF\324\33\276\317\241[{\24\354D\223\215\332\247\34\376\246W"..., 32768) = 32768 <0.000379>
...
read(3, "", 32768) = 0 <0.000226>
utimensat(4, NULL, {{1392157379, 551638340}, {1392157405, 783308564}}, 0) = 0 <0.000254>
fgetxattr(3, "system.posix_acl_access", 0x7fff747c4f50, 132) = -1 ENODATA (No data available) <0.000234>
fstat(3, {st_mode=S_IFREG|0664, st_size=19202048, ...}) = 0 <0.000223>
fsetxattr(4, "system.posix_acl_access", "\x02\x00\x00\x00\x01\x00\x06\x00\xff\xff\xff\xff\x04\x00\x06\x00\xff\xff\xff\xff \x00\x04\x00\xff\xff\xff\xff", 28, 0) = 0 <0.000285>
close(4) = 0 <0.000250>
close(3) = 0 <0.000267>