首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算“在linux上复制c++中的二进制文件”所用时间的最佳方法是什么?

计算“在linux上复制c++中的二进制文件”所用时间的最佳方法是什么?
EN

Stack Overflow用户
提问于 2014-02-11 21:45:46
回答 2查看 325关注 0票数 1

我使用以下代码复制一个大小约为1.1GB的文件

代码语言:javascript
复制
#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;
}

产出如下:

代码语言:javascript
复制
   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,它与实际时间几乎相同。

代码语言:javascript
复制
#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。

问题

  1. 用第一种方式计算的时间是多少?
  2. “pv”或“管道查看器”是否正确地显示了操作系统“复制文件所需的时间”?
  3. 我们是否可以得出结论,sendfile()复制所用的时间与OS几乎相同?
EN

回答 2

Stack Overflow用户

发布于 2014-02-11 22:21:21

用第一种方式计算的时间是多少?

这是你的程序使用CPU的时间。clock()测量CPU时间。复制文件通常会花费大部分时间做其他事情(I/O,例如等待硬盘移动或响应,等待内核中的锁,等等)。

“pv”或“管道查看器”是否正确地显示了操作系统“复制文件所需的时间”?

它显示了从接收到第一个字节到接收到最后一个字节所花费的时间。

请记住,写入文件通常只是写到文件系统缓存,所以它只是写到RAM。操作系统会在空闲时将该缓存刷新到驱动器上,这可能是在您的程序、cp程序或您使用的任何GUI文件查询程序之后,即复制已经完成。(这不是真正的问题,除非您切断电源,读取从您复制到的文件通过相同的缓存)。

如果要确保数据被刷新到驱动器,请在文件描述符上调用Fdat异步()。

这也意味着您可以轻松地测量复制文件的非常不同的时间。如果该文件或其部分恰好驻留在文件系统缓存中,则您正在从RAM中读取。如果它不在缓存中,则需要从驱动器中读取,这可能会慢一个数量级或两个数量级。

我们是否可以得出结论,sendfile()复制所用的时间与OS几乎相同?

对不起,我不知道你在问什么。

票数 1
EN

Stack Overflow用户

发布于 2014-02-11 22:18:48

不是直接回答您的问题,但您可能会发现strace -T相当有用,除非您绝对需要将统计数据存储在程序中。

测试

代码语言:javascript
复制
$  cat /dev/urandom > chunk.bin
^C
$  strace -T cp -p chunk.bin dust.bin

输出(见每个syscall后面三角形括号中的数字)

代码语言:javascript
复制
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>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21713714

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档