###前提
C言語でシステムコールが遅いと言われる所以について調べました。
write,readなどのシステムコールではバッファリングを行わないためカーネルのコンテキストスイッチが増えオーバーヘッドになっているということがわかりました(一部の要因なのかもしれません)。そこで自前でバッファを確保してそこに入れる様にしてやればオーバーヘッドを減らせるのでは?と思い実験プログラムを書いてみたのですが一部が予想と反した結果になりました。
環境
macOS Sierra
バージョン 10.12.1
xcodeインストール済み
システムコール回数を調べるために使ったコマンド
dtruss -c ./a.out
###該当のソースコード
▼512バイトのバッファ有り
c
1#include <stdio.h> 2#include <stdlib.h> 3#include <unistd.h> 4#include <sys/types.h> 5#include <sys/uio.h> 6#include <fcntl.h> 7 8int main(int argc, char *argv[]){ 9 10 ssize_t n; 11 char buf[512]; 12 int fd; 13 int df; 14 15 if(argc != 3){ 16 fprintf(stderr,"usage:%s [srcfile] [dstfile]\n", argv[0]); 17 exit(EXIT_FAILURE); 18 } 19 20 //読み 21 if((fd = open(argv[1], O_RDONLY)) < 0) perror(argv[1]); 22 23 //書き 24 if((df = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) perror(argv[2]); 25 26 size_t count; //ループの回数 27 28 /*データがなくなるまでループ*/ 29 while((n = read(fd, buf, sizeof(buf))) > 0){ 30 write(df, buf, n); 31 count++; 32 } 33 34 printf("ループカウンタ:%zu\n", count); 35 36 close(fd); 37 close(df); 38 return 0; 39}
▼バッファなし
c
1#include <stdio.h> 2#include <stdlib.h> 3#include <unistd.h> 4#include <sys/types.h> 5#include <sys/uio.h> 6#include <fcntl.h> 7 8int main(int argc, char *argv[]){ 9 10 ssize_t n; 11 char c; 12 int fd; 13 int df; 14 15 if(argc != 3){ 16 fprintf(stderr,"usage:%s [srcfile] [dstfile]\n", argv[0]); 17 exit(EXIT_FAILURE); 18 } 19 20 //読み 21 if((fd = open(argv[1], O_RDONLY)) < 0) perror(argv[1]); 22 23 //書き 24 if((df = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) perror(argv[2]); 25 26 size_t count; //ループの回数 27 28 /*データがなくなるまでループ*/ 29 while((n = read(fd, &c, sizeof(c))) > 0){ 30 write(df, &c, n); 31 count++; 32 } 33 34 printf("ループカウンタ:%zu\n", count); 35 36 close(fd); 37 close(df); 38 return 0; 39}
###実験プログラムの結果
512kバイトの元データをプログラムに与えた場合
------512バイトのバッファ有り-------
・標準出力結果
ループカウンタ:1000
・システムコール回数
write 1000
read 1001
・実行速度
real 0m0.036s
user 0m0.003s
sys 0m0.018s
・コピー先ファイルのサイズ
512kバイト コピーできている
-----バッファなし(1バイトずつ処理)-----
・標準出力結果
ループカウンタ:512000
・システムコール回数
write 8075
read 8076
・実行速度
real 0m0.653s
user 0m0.094s
sys 0m0.552s
・コピー先のファイルサイズ
512kバイト コピーできている
###疑問点
512kバイトのデータを512バイトのバッファに格納して処理する場合、システムコールを1000回呼んで1001回目にデータがもうないのでループを抜けるのはわかります。結果もそのようになったので納得です。
一方、バッファなしで1バイトずつ処理する場合は、readを512000回呼んで512001回目にデータがもうないのでループを抜けると思うし、ループカウンタも512000回になっているのですが、システムコールは8075回という値が示されてしまいます。自分はシステムコール回数の結果も512000回だと思うのですがなぜこの様な結果になってしまうのでしょうか?
コピー先のファイルサイズはちゃんと512kバイトあるのでプログラムとしてはちゃんと動いていそうなのですが...
よろしくお願いします。

回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/12/13 02:16