read

readは、指定されたファイルディスクリプタから、バイナリデータをバッファに読み込むUNIXシステムコール・・・。

Man page of READ

freadも最終的にはこのreadを呼ぶが、なぜfreadとreadを使い分けるのか・・・。
2パターンのバイナリデータをreadとfreadでそれぞれ読み込んでみて検証する・・・。

まずパターン1・・・。

read_1.cにて、

こちらで用意するバッファbufのサイズは4・・・。

一方、

高水準入出力関数がもともと利用しているバッファのサイズは、stdio.hの中にBUFSIZとして定義されているのでそれを出力・・・。

$ ./read_1
BUFSIZ = 8192

ここでは8192となっている・・・。

そして、test_1.txtというファイルを用意する・・・。
これは"ABCD"という文字列を2048回並べた8192バイトのファイルである・・・。
BUFSIZと同じ・・・。

test_1.txtをopenで開いて、

4バイトのbufに2048回読み込む・・・。

この処理にかかった実時間をtimeコマンドで計測する・・・。

Man page of TIME

$ time ./read_1
BUFSIZ = 8192
read start
read end

real    0m0.030s
user    0m0.002s
sys     0m0.007s
$

0.030秒かかっている・・・。

さて、つづいてはfreadで同じファイルを同じ方法で読み込んでみる・・・。

fread_1.cで、

同じように4バイトのバッファに2048回読み込む・・・。

これをtimeで実行すると、

$ time ./fread_1
BUFSIZ = 8192
fread start
fread end

real    0m0.010s
user    0m0.000s
sys     0m0.004s
$

0.010秒で済んでいる・・・。

場合によってはあまり差がない場合もあるが、たいていはfreadのほうが速い・・・。
BUFSIZ以下のデータを繰り返し読み込む場合、
バッファリング機能のあるfreadは、BUFSIZ分まで実際にはreadを呼ばない・・・。
BUFSIZに到達したら読み込むので、実際にreadが呼ばれて、処理速度の遅い入出力装置にアクセスするのは1回だけである・・・。

一方、たとえ4バイトでもreadを1回呼んだだけでそれなりの時間はかかる・・・。
2048回呼べば、1回readを呼ぶだけのfreadより遅くなるのは合点がいく・・・。
ただ、実際にはこのようにあまり差が出ない場合が多い・・・。

まとめると、BUFSIZ以下のデータを繰り返し読み込む場合はfreadのほうが速い・・・。

次はパターン2・・・。

BUFSIZを超えるデータの読み込みはどうだろうか・・・。

read_2.cで、

バッファbufのサイズを819200、つまりBUFSIZの100倍用意する・・・。

そして、test_1.txtの100倍のサイズである、test_2.txtを用意する・・・。

そのtest_2.txtをopenで開いて、

readで、1回で819200バイト全部読み込む・・・。

$ time ./read_2
BUFSIZ = 8192
read start
read end

real    0m0.009s
user    0m0.000s
sys     0m0.005s
$ time ./read_2

readでは0.009秒かかる・・・。

では、freadの場合はどうだろうか・・・。

同じようにサイズが819200バイトのバッファを自前で用意し、

fopenでtest_2.txtを開いて、

819200バイトをfopenで1回で読み込む・・・。

$ time ./fread_2
BUFSIZ = 8192
fread start
fread end

real    0m0.016s
user    0m0.002s
sys     0m0.003s
$

0.016秒かかっている・・・。

freadは内部ではreadで8192バイトずつ読み込んでいるので、それ以上となると、1回内部バッファをフラッシュして再びreadを呼んで読み込まなければならない・・・。
結果的にreadを100回呼んでいるので時間がかかる・・・。

まとめると、BUFSIZ以上のデータを1回で一気に読み込む場合はreadのほうが速い・・・。

Sample/read_1.c at master · bg1bgst333/Sample · GitHub
Sample/fread_1.c at master · bg1bgst333/Sample · GitHub
Sample/read_2.c at master · bg1bgst333/Sample · GitHub
Sample/fread_2.c at master · bg1bgst333/Sample · GitHub