ディスクのスループット

HDD 買うかなーと思ったのですが、 IDE より SATA の方が安いとかいうことを受けて適当に調べてみました。適当に Wikipedia とかから。

 12Mbps  USB-1.0   1.5MB/s
 100Mbps ethernet 12.5MB/s
 400Mbps USB-2.0  50.0MB/s
 UDMA 0  ATA-4    16.7MB/s
 UDMA 1  ATA-4    25.0MB/s
 UDMA 2  ATA-4    33.3MB/s
 UDMA 3  ATA-5    44.4MB/s
 UDMA 4  ATA-5    66.6MB/s
 UDMA 5  ATA-6   100.0MB/s
 UDMA 6  ATA-7   133.3MB/s
         SATA-1  150.0MB/s
         SATA-2  300.0MB/s

SATA 速すぎっす。てか本当かよとしか思えないというか本当にこの速度出るんすか。ヘタなメモリ並に速いだろコレ。あと USB-2.0 ってネットワークの 10 倍遅いとかそいう認識だったけど、つまり私の中では USB-1.0 が現役だったとかそいうことだと思う。

次に手元のマシン達に hdparm -ft をしてみました。

 u4 (SATA 120GB)  40.9MB/s
 uk (IDE   80GB)  28.4MB/s
 u  (IDE   80GB)  14.2MB/s
 u3 (IDE    6GB)  20.2MB/s

u ってつまりゴルフ場なんですが、なんでこんなに遅いのかな。。。

次に dd で 1GB 程度書いてみました。コマンドはこんなかんじ。

 dd if=/dev/zero of=hoge count=1024 bs=1M && sync

sync してるのは linux が dirty フラグかなんか立てて write はすぐ終わるとかでです。

 u4 (SATA 120GB)  24.1MB/s  (190MB/s)
 um (SATA  80GB)  24.9MB/s  ( 26MB/s)
 uk (IDE   80GB)  14.3MB/s

um って OSX なので hdparm の記録取れなかったんですが、まぁノートの SATA 2 つは似たようなもんでした。 u と u3 は dd してたらマシンの命の危険を感じたのでやめた。

次はネットワーク。若い者は知らんだろうけど昔は ftp というものがあってな…などと ftpgopher とか finger レベルの扱いになるんだろうなぁとか思いながら ftpd の設定してたら、なんとうまくいかなかったので http で。さらば ftp 。コマンドは適当に curl で。

 curl http://u4/hoge > hoge && sync

結果。

 u4-airmac-um HTTP 1.7MB/s
 u4-uk        HTTP 5.0MB/s
 u4-uk        SCP  1.5MB/s

なんか scp って圧縮するから速いと思ってたのに /dev/zero 100% のデータなのに遅い。でネットワーク越しにバックアップとかする時はこの速度に律速されるわけで… SATA とか USB 2.0 とか考えるまでもないということがよくわかりました。

ついでに memcpy 。コード。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main() {
    static const int N = 500 * 1024 * 1024;
    char* src = (char*)malloc(N);
    char* dst = (char*)malloc(N);
    clock_t s = clock();
    memcpy(dst, src, N);
    printf("%f\n", ((double)clock() - s) / CLOCKS_PER_SEC);
}

結果。

 u4              510.2MB/s
 um              270.3MB/s

u4 (Core 2 Duo 2.0GHz) のこの数値は、 1 byte の転送に 4 clock 程度かかってる、とか考えられる。

ついでに昔の memcpyベンチとか見て、

    int i;
    for (i = 0; i < N/8; i++) {
        asm("movq (%0), %%mm0;"
            "movntq %%mm0, (%1);"
            :: "r"(src), "r"(dst));
        src+=8;
        dst+=8;
    }

とかやってみたが速度は変わらず。なんか glibc の memcpy はそれなりに頑張ってるだろうし。あと 1 byte ずつのコピーを

    int i;
    for (i = 0; i < N; i++) *dst++ = *src++;

とかにしたら 357.1MB/s とかまで遅くなった。まぁ memcpy はいいや。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h