2014-02-11 20 views
1

我使用下面的代碼將一個文件複製與大小約1.1 GB什麼是計算「在Linux上使用C++複製二進制文件」所消耗時間的最佳方法?

#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 !!! 現在我將在下面的代碼中使用「結構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源> destination'a命令時輸出爲:1.02e+03MB 0:01:24 [12.1MB/s] [===========================>] 100%和它與實際的時間相同。

而且,當我在模式圖形(複製/粘貼普通)中複製文件需要大約84秒的時間。

問題

  1. 什麼是在第一時間的方式計算?
  2. 'pv'或Pipe Viewer是否正確顯示操作系統「複製文件所耗費的時間」?
  3. 得出結論,我們通過sendfile()複製的時間與OS幾乎相同?
+0

此網站上查看許多與會者/讀取標籤的問題。我把你的C++標籤改爲C. –

+2

@CaptainGiraffe他使用'iostream'和'ctime'頭......這是C++代碼,儘管他正在做的大部分都是C. –

+1

@SchighSchagh Mea culpa,謝謝。我重新添加了C++標籤。 OP,當你說你計算你的意思是你看你的手錶的時間是正確的? –

回答

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> 
1

是什麼時候在所述第一方式計算的?

這是您的程序使用CPU的時間。 clock()用於測量CPU時間。拷貝文件 通常花費大部分時間去做其他事情(I/O,例如,等待硬盤驅動器移動或響應,等待內核中的鎖,等等)。

「pv」或Pipe Viewer是否正確顯示操作系統「複製文件所耗費的時間」?

它顯示了從接收到第一個字節到接收到最後一個字節爲止所花費的時間。

請記住寫入文件通常只是寫入文件系統緩存,所以它只是寫入RAM。操作系統將緩存刷新到閒置的驅動器中,可能是在程序,cp程序或您使用的任何GUI文件管理器之後說複製完成。 (除非您切斷電源,從您複製的文件中讀取並通過相同的緩存,否則這不是真正的問題)。

如果要確保將數據刷新到驅動器,請在文件描述符上調用fdatasync()。

這也意味着您可以輕鬆地測量大量不同的時間來複制文件。如果文件或部分文件恰好位於文件系統緩存中,那麼您正在從RAM讀取數據。如果它不在高速緩存中,則需要從驅動器讀取數據,該數據速度可能低一個數量級或兩個數量級。

得出結論,我們發現sendfile()複製的時間與OS幾乎相同?

對不起,我不知道你問這裏有什麼..

+0

感謝您的回答,這意味着,我們可以得出結論,我們通過sendfile()複製二進制文件所花費的時間等於'cp'所消耗的時間(複製)? – Code

+0

@代碼我不知道你測量的是什麼。如果你的2.代碼示例與'cp'顯示的時間相同,那麼顯然是的。 – nos

相關問題