2

私のコードは、0 から 255 までの整数値を取り、それを文字列としてファイルに書き込む必要があります。非常に高速に繰り返し呼び出される可能性があるため、高速である必要があるため、負荷が高い場合に最適化が顕著になります。ここには、大量のデータをファイルに書き込む効率的な方法を扱う他の質問がありますが、少量のデータはどうですか?

これが私の現在のアプローチです:

public static void writeInt(final String filename, final int value)
{
    try
    {
        // Convert the int to a string representation in a byte array
        final String string = Integer.toString(value);
        final byte[] bytes = new byte[string.length()];
        for (int i = 0; i < string.length(); i++)
        {
            bytes[i] = (byte)string.charAt(i);
        }

        // Now write the byte array to file
        final FileOutputStream fileOutputStream = new FileOutputStream(filename);
        fileOutputStream.write(bytes, 0, bytes.length);
        fileOutputStream.close();
    }
    catch (IOException exception)
    {
        // Error handling here
    }
}

ここでは a は役に立たないと思いBufferedOutputStreamます: バッファのフラッシュを構築するオーバーヘッドは、おそらく 3 文字の書き込みには逆効果ですよね? 他に改善できる点はありますか?

4

5 に答える 5

5

これは、0 ~ 255 の範囲要件の要件を考えると、ほぼ同じくらい効率的だと思います。バッファ付きライターを使用すると、書き込まれるバイト数が非常に少なく、作成する必要のない一時的な構造が作成されるため、効率が低下します。

static byte[][] cache = new byte[256][];
public static void writeInt(final String filename, final int value)
{
    // time will be spent on integer to string conversion, so cache that
    byte[] bytesToWrite = cache[value];
    if (bytesToWrite == null) {
        bytesToWrite = cache[value] = String.valueOf(value).getBytes();
    }

    FileOutputStream fileOutputStream = null;
    try {
        // Now write the byte array to file
        fileOutputStream = new FileOutputStream(filename);
        fileOutputStream.write(bytesToWrite);
        fileOutputStream.close();
    } catch (IOException exception) {
        // Error handling here
    } finally {
        if (fileOutputStream != null) {
            fileOutputStream.close()
        }
    }
}
于 2013-09-25T14:34:55.497 に答える
3

IMOを高速化することはできません。そうでなければ、ここでは BufferedOutputStream は役に立たないでしょう。src を見ると、FileOutputStream.write(byte b[], int off, int len) はバイト配列をネイティブ メソッドに直接送信し、BufferedOutputStream.write(byte b[], int off, int len) は最初に配列を同期してそのバッファーにコピーし、閉じるときにバイトをバッファーから実際のストリームにフラッシュします。

この場合の最も遅い部分は、ファイルの開閉です。

于 2013-09-25T14:20:10.327 に答える
0

パーティーに遅刻してすみません:)

コードを最適化しようとすることは、おそらく正しいアプローチではないと思います。同じ小さなファイルを繰り返し書き込んでおり、アプリケーションでバッファリングするのではなく毎回書き込む必要がある場合、最大の考慮事項はファイルシステムとストレージ ハードウェアです。

重要なのは、実際に毎回ハードウェアを叩いていると、ハードウェアがひどく動揺することになるということです。ただし、システムが書き込みをキャッシュしている場合は、ハードウェアに頻繁にヒットしないようにすることができます。データはそこに到達する前に上書きされ、新しいデータのみが書き込まれます。

しかし、これは2つのことに依存します。1 つには、古いファイルが書き込まれる前に新しい書き込みが行われると、ファイルシステムは何をしますか? ファイルシステムによっては、ジャーナルに余分なエントリを書き込んだり、古いファイルをある場所に書き込んでから新しいファイルを別の物理的な場所に書き込んだりすることさえあります。それは殺人者でしょう。

別の例として、何かを上書きするように求められたとき、ハードウェアは何をしますか? 従来のハード ドライブの場合は、おそらく古いデータが上書きされるだけです。フラッシュ メモリの場合 (これが Android の場合と同様)、ウェア レベリングが開始され、ドライブのさまざまなビットに書き込みが行われます。

キャッシュをディスクにプッシュする前に 1000 件の更新を送信した場合に、最後の更新のみが書き込まれるようにするために、ディスク キャッシングとファイル システムに関してできる限りのことを行う必要があります。

これは Android なので、おそらく ext2/3/4 を見ているでしょう。ジャーナリング オプションを注意深く見て、ext4 での割り当ての遅延の影響を調べてください。おそらく最善の選択肢は ext4 を使用することですが、ジャーナリングはオフにします。

于 2014-09-02T19:06:06.487 に答える
0

ここでのボトルネックは IO であり、次の 2 つの改善が役立つと思います。

  • 更新の粒度について考えます。つまり、アプリから 1 秒あたり 20 を超える更新が必要ない場合は、1/20 秒あたり 1 を超える更新を書き込まないようにアプリを最適化できます。これは、環境によっては非常に有益な場合があります。
  • Java NIO は、大きいサイズでははるかに高速であることが証明されているため、小さいサイズで実験することも理にかなっています。たとえばChannelInputStream.
于 2013-09-25T23:05:14.857 に答える
-1

Google で簡単に検索すると、さまざまなサイズのファイルに対するさまざまな書き込み/読み取り操作のベンチマークが表示されます。

http://designingefficientsoftware.wordpress.com/2011/03/03/effective-file-io-from-csharp/

WinFileIO.WriteBlocks著者は、I/O 操作がオペレーティング システムのファイル キャッシング、ファイルのインデックス作成、ディスクの断片化、ファイル システムのキャッシングなどの複数の要因に大きく依存しているにもかかわらず、ファイルへのデータの書き込みで最速のパフォーマンスを発揮するという結論に達しました。

于 2013-09-25T14:22:06.820 に答える