8

ローカルファイルから読み取られたinputstreamオブジェクトとネットワークソース(この場合はAmazon S3)から読み取られたinputstreamオブジェクトに違いがあるとは思わなかったので、誰かが私を教えてくれることを願っています。

これらのプログラムは、Centos6.3を実行しているVMで実行されました。どちらの場合も、テストファイルは10MBです。

ローカルファイルコード:

    InputStream is = new FileInputStream("/home/anyuser/test.jpg");

    int read = 0;
    int buf_size = 1024 * 1024 * 2;
    byte[] buf = new byte[buf_size];

    ByteArrayOutputStream baos = new ByteArrayOutputStream(buf_size);

    long t3 = System.currentTimeMillis();
    int i = 0;
    while ((read = is.read(buf)) != -1) {
        baos.write(buf,0,read);
        System.out.println("reading for the " + i + "th time");
        i++;
    }
    long t4 = System.currentTimeMillis();
    System.out.println("Time to read = " + (t4-t3) + "ms");

このコードの出力は次のとおりです。5回読み取ります。これは、読み込まれるバッファサイズが2MBで、ファイルが10MBであるため意味があります。

reading for the 0th time
reading for the 1th time
reading for the 2th time
reading for the 3th time
reading for the 4th time
Time to read = 103ms

これで、同じ10MBのテストファイルで同じコードを実行できますが、今回はソースがAmazonS3からのものです。S3からのストリームの取得が完了するまで、読み取りを開始しません。ただし、今回は、読み取りループが数千回実行されていますが、読み取りは5回のみである必要があります。

    InputStream is;
    long t1 = System.currentTimeMillis();
    is = getS3().getFileFromBucket(S3Path,input);
    long t2 = System.currentTimeMillis();

    System.out.print("Time to get file " + input + " from S3: ");
    System.out.println((t2-t1) + "ms");

    int read = 0;
    int buf_size = 1024*1024*2;
    byte[] buf = new byte[buf_size];

    ByteArrayOutputStream baos = new ByteArrayOutputStream(buf_size);
    long t3 = System.currentTimeMillis();
    int i = 0;

    while ((read = is.read(buf)) != -1) {
        baos.write(buf,0,read);
        if ((i % 100) == 0)
        System.out.println("reading for the " + i + "th time");
        i++;
    }
    long t4 = System.currentTimeMillis();

    System.out.println("Time to read = " + (t4-t3) + "ms");

出力は次のとおりです。

Time to get file test.jpg from S3: 2456ms
reading for the 0th time
reading for the 100th time
reading for the 200th time
reading for the 300th time
reading for the 400th time
reading for the 500th time
reading for the 600th time
reading for the 700th time
reading for the 800th time
reading for the 900th time
reading for the 1000th time
reading for the 1100th time
reading for the 1200th time
reading for the 1300th time
reading for the 1400th time
Time to read = 14471ms

ストリームの読み取りにかかる時間は、実行ごとに異なります。60秒かかることもあれば、15秒かかることもあります。15秒より速くなることはありません。ローカルファイルの例のように、読み取りループは5回だけであると思いますが、プログラムの各テスト実行で1400回以上ループします。

これは、ネットワークソースからのファイルの取得が完了した場合でも、ソースがネットワークを経由している場合のinputstreamの動作方法ですか?よろしくお願いします。

4

2 に答える 2

6

私はそれがJavaに固有のものではないと思います。ネットワークから読み取る場合、オペレーティングシステムへの実際の読み取り呼び出しは、割り当てたバッファの大きさに関係なく、一度にデータのパケットを返します。読み取ったデータ(読み取り変数)のサイズを確認すると、使用されているネットワークパケットのサイズが表示されます。

これが、人々が別のスレッドを使用してネットワークから読み取り、非同期I/O技術を使用してブロックを回避する理由の1つです。

于 2012-11-13T00:36:49.103 に答える
1

@ imel96が指摘しているように、ドキュメントには、期待する動作を保証するものは何もありません。ソケットの受信バッファは通常、帯域幅などの他の要因とは別にそれほど大きくないため、ソケットから一度に2MBを読み取ることはありません。

于 2012-11-13T03:06:33.177 に答える