[解決済み] FileInputStreamを使用する場合、理想的なバッファサイズはどのように決定するのですか?
質問
ファイルからMessageDigest(ハッシュ)を作成するメソッドがあるのですが、これを大量のファイル(>=100,000)に対して実行する必要があります。パフォーマンスを最大化するために、ファイルからの読み込みに使用するバッファをどの程度の大きさにすればよいでしょうか?
ほとんどの人は基本的なコードを知っていると思います(念のためここで繰り返します)。
MessageDigest md = MessageDigest.getInstance( "SHA" );
FileInputStream ios = new FileInputStream( "myfile.bmp" );
byte[] buffer = new byte[4 * 1024]; // what should this value be?
int read = 0;
while( ( read = ios.read( buffer ) ) > 0 )
md.update( buffer, 0, read );
ios.close();
md.digest();
スループットを最大化するための理想的なバッファのサイズは?これはシステムに依存するのは分かっていて、OS、FileSystem, と HDDに依存し、他のハードウェア/ソフトウェアが混在している可能性があります。
(私はややJava初心者なので、これは私が知らないJava APIコールがあるだけかもしれないことを指摘しておきます)。
編集する どのようなシステムで使われるのか事前に分からないので、一概に決めつけることはできませんが。(そのためにJavaを使っています)。
編集する 上のコードは、投稿を小さくするためにtry..catchなどが抜けています。
解決方法は?
最適なバッファサイズは、ファイルシステムのブロックサイズ、CPUのキャッシュサイズ、キャッシュのレイテンシーなど、多くの事柄に関連しています。
ほとんどのファイルシステムは、4096または8192のブロックサイズを使用するように設定されています。 理論的には、ディスクブロックより数バイト多く読み取るようにバッファサイズを設定すると、ファイルシステムでの操作が極めて非効率になります(例えば、一度に4100バイト読み取るようにバッファを設定した場合、各読み取りにファイルシステムで2ブロック読み取る必要が生じます)。 ブロックがすでにキャッシュにある場合、RAM -> L3/L2キャッシュのレイテンシという代償を支払うことになります。 運悪くブロックがまだキャッシュにない場合、ディスク->RAMのレイテンシの代償を支払うことになります。
このため、ほとんどのバッファのサイズは2の累乗であり、一般にディスクのブロックサイズより大きい(または等しい)ことがわかります。 つまり、1つのストリームリードが複数のディスクブロックリードになる可能性がありますが、これらのリードは常にフルブロックを使用するため、無駄なリードが発生しないのです。
ディスクから読み取られたブロックは、次の読み取りを行うときにまだメモリ内にあるため(結局のところ、ここではシーケンシャル読み取りを行っています)、次の読み取りで RAM -> L3/L2 キャッシュのレイテンシを支払うことになりますが、ディスク-> RAM レイテンシは発生しないため、通常のストリーミング シナリオではこれがかなり相殺されます。 そのため、次の読み出し時に RAM の L3/L2 キャッシュのレイテンシを支払うことになりますが、ディスクのレイテンシを支払う必要はありません。
ですから、もし異なるキャッシュサイズでテストを行った場合(私自身は行っていませんが)、おそらくファイルシステムブロックのサイズまでなら、キャッシュサイズの大きな影響が見られると思います。 それ以上では、物事はすぐに平準化されると思われます。
があります。 トン L3 -> L2キャッシュの転送を理解するだけでも気が遠くなるほど複雑で、CPUの種類によって変化します)。
これが「現実世界」の答えにつながります。 もしあなたのアプリが99%そうなら、キャッシュサイズを8192に設定し、次に進みましょう(さらに良いのは、パフォーマンスよりもカプセル化を選び、BufferedInputStreamを使って詳細を隠蔽することです)。 ディスクスループットに大きく依存する1%のアプリの場合、異なるディスク相互作用戦略を交換できるように実装を工夫し、ユーザーがテストして最適化できるようにノブやダイヤルを提供します(または自己最適化システムを考え出します)。
関連
-
スレッド "main "での例外をEclipseで解決 java.lang.Error: 未解決のコンパイル問題、コンパイラとパッケージの不整合
-
Eclipse起動エラー:javaは起動したが、終了コード=1を返した(ネット上の様々な落とし穴)
-
SocketTimeoutExceptionです。読み込みがタイムアウトしました
-
[解決済み] Javaで、オブジェクトの大きさを決定する最も良い方法は何ですか?
-
[解決済み] この日付形式は何ですか?2011-08-12T20:17:46.384Z
-
[解決済み] Javaインターフェースでスタティックメソッドを定義できないのはなぜですか?
-
[解決済み] インスタンスオブの「ネゲート」する最良の方法
-
[解決済み] なぜJavaではsuper.super.method();が許されないのですか?
-
[解決済み】JSP 2を使用して、JSPファイル内のJavaコードを回避するにはどうすればよいですか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
eclipse アクセス制限です。タイプ 'xxx' は API ではありません(必須ライブラリ '' の制限)。
-
Spring Boot による HTTPS アクセスの設定
-
final, finally, finalizeの違いについて話してください。
-
SpringBootApplication を型解決できない。
-
eclipse の実行時に java 仮想マシンが見つからなかった
-
Methodのinvokeメソッド実装のJavaリフレクション
-
アイデア Springboot Web プロジェクトを jar にパッケージ化する場合、Error: 無効または破損した jarfile x.jar 解決策
-
Eclipse起動エラー:javaは起動したが、終了コード=1を返した(ネット上の様々な落とし穴)
-
javax.net.ssl.SSLException: 読み取りエラー: ssl=0xdeae5100: システムコール中の I/O エラー、接続 res
-
あるコードに出会いましたが、何に使うのか理解できません。 List<String> list = new ArrayList<String>() { { a