我使用以下代码复制一个大小约为1.1GB的文件
#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 SEC!现在,我将在下面的代码和输出中使用"structure“,输出是: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>目的‘命令,然后输出是:1.02e+03MB 0:01:24 [12.1MB/s] [===========================>] 100%,它与实际时间相同。
而且,当我以图形方式复制文件(复制/粘贴普通文件)时,大约需要84 SEC。
问题
发布于 2014-02-11 22:21:21
用第一种方式计算的时间是多少?
这是你的程序使用CPU的时间。clock()测量CPU时间。复制文件通常会花费大部分时间做其他事情(I/O,例如等待硬盘移动或响应,等待内核中的锁,等等)。
“pv”或“管道查看器”是否正确地显示了操作系统“复制文件所需的时间”?
它显示了从接收到第一个字节到接收到最后一个字节所花费的时间。
请记住,写入文件通常只是写到文件系统缓存,所以它只是写到RAM。操作系统会在空闲时将该缓存刷新到驱动器上,这可能是在您的程序、cp程序或您使用的任何GUI文件查询程序之后,即复制已经完成。(这不是真正的问题,除非您切断电源,读取从您复制到的文件通过相同的缓存)。
如果要确保数据被刷新到驱动器,请在文件描述符上调用Fdat异步()。
这也意味着您可以轻松地测量复制文件的非常不同的时间。如果该文件或其部分恰好驻留在文件系统缓存中,则您正在从RAM中读取。如果它不在缓存中,则需要从驱动器中读取,这可能会慢一个数量级或两个数量级。
我们是否可以得出结论,sendfile()复制所用的时间与OS几乎相同?
对不起,我不知道你在问什么。
发布于 2014-02-11 22:18:48
不是直接回答您的问题,但您可能会发现strace -T相当有用,除非您绝对需要将统计数据存储在程序中。
测试
$ cat /dev/urandom > chunk.bin
^C
$ strace -T cp -p chunk.bin dust.bin输出(见每个syscall后面三角形括号中的数字)
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>https://stackoverflow.com/questions/21713714
复制相似问题