問題タブ [zero-copy]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - FileChannel zero-copy transferTo が SocketChannel へのバイトのコピーに失敗する
Java でゼロコピーを使用して大きなファイルをファイルからソケットに転送すると、奇妙な動作が見られます。私の環境:
- Windows 7 64 ビット JDK 1.6.0_45 および 1.7.0_79。
- Centos 6.6 64 ビット JDK 1.6.0_35
プログラムの動作: クライアントは入力ファイルをソケットにコピーし、サーバーはゼロコピー メソッド (transferFrom と transferTo) を使用してソケットを出力ファイルにコピーします。ファイル サイズが比較的大きい場合、すべてのバイトがサーバーに到達しているわけではありません。Windows の場合は 100Mb 以上、Centos の場合は 2GB 以上です。クライアントとサーバーは同じマシン上にあり、localhost アドレスを使用してデータを転送します。
OSによって動作が異なります。Windows では、クライアントは transferTo メソッドを正常に完了します。転送されるバイト数は、入力ファイルのサイズと同じです。
long bytesTransferred = fileChannel.transferTo(0, inputFile.length(), socketChannel);
一方、サーバーは、より少ない受信バイト数を報告します。
long transferFromByteCount = fileChannel.transferFrom(socketChannel, 0, inputFile.length());
Linux バイトでは、入力ファイルのサイズが 4Gb であっても、クライアントで転送されるのは 2Gb です。どちらの構成にも十分なスペースがあります。
Windows では、次の回避策のいずれかを使用して 130Mb のファイルを転送できました。1) サーバーで受信バッファ サイズを増やす、2) クライアントにスレッド スリープ メソッドを追加する。これにより、すべてのバイトがサーバーではなくソケット送信バッファーに送信されると、クライアントの transferTo メソッドが完了すると思います。これらのバイトがサーバーに到達するかどうかは保証されていないため、私のユース ケースでは問題が生じます。
Linux では、単一の transferTo 呼び出しで転送できる最大ファイル サイズは 2Gb ですが、少なくともクライアントはサーバーに送信された正しいバイト数を報告します。
私の質問: クライアントがサーバーへのファイルの確実な配信をクロスプラットフォームで保証するための最良の方法は何ですか? Windows で sendfile() をエミュレートするために使用されるメカニズムは何ですか?
コードは次のとおりです。
クライアント - ZeroCopyClient.java:
サーバー - ZeroCopyServer.java:
更新 1:ループで修正された Linux コード。
更新 2:私が検討している回避策の 1 つは、クライアントとサーバーの連携が必要です。送信の最後に、サーバーは受信したデータの長さをクライアントに書き戻し、クライアントはそれをブロッキングモードで読み取ります。
サーバーは次のように応答します。
クライアントは read でブロックします:
その結果、クライアントは、バイトが送信および受信ソケット バッファを通過するのを待ち、実際にはバイトが出力ファイルに格納されるのを待ちます。帯域外の確認応答を実装する必要はありません。また、セクション II.A で提案されているように、クライアントが待機する必要もありません。ファイルの内容は可変です。
「ファイルの同じ部分を書き換える前に、「適切な」時間待機します」
更新 3:
@EJP と @the8472 による修正を組み込んだ修正例。長さとファイルのチェックサムの両方を検証し、出力トレースは使用しません。大きなファイルの CRC32 チェックサムの計算は、完了するまでに数秒かかる場合があることに注意してください。
クライアント:
サーバ:
java - ゼロコピーのためにNettyにtransferFromのような機能はありますか?
かなり大きなサイズのペイロードを処理する HTTP サーバーを開発しています。Netty はゼロコピーを提供するので、Netty のゼロコピーを使用してペイロードのゼロコピーを使用することを考えました。しかし、Nettyはコンテンツを直接ファイルに読み込む方法を提供するだけで、同様の方法を提供しtransferTo(WritableByteChannel target, long position)
ていないようです。transferFrom()
それはただの方法ですか、それとも回避策はありますか?ありがとう。
linux - 贈答の有無にかかわらず、vmsplice(2) のセマンティクスは何ですか?
システムコールの機能を理解しようとしていvmsplice(2)
ます (マニュアルページはこちら)。SPLICE_F_GIFT
フラグの効果について 2 つの質問があります。
man ページには、一度カーネルにページを贈ると、二度とメモリを変更してはならないと書かれています。それはメモリが永遠に固定されていることを意味するのでしょうか、それとも物理メモリではなく、贈与プロセスによってマッピングを解除できる仮想メモリを指しているのでしょうか? 言い換えれば、これの典型的な使用法はどのようなものですか?
を設定しない場合、ベクトル化された write syscall
SPLICE_F_GIFT
と何か違いはありますか?vmsplice(2)
writev(2)
linux - POSIXでゼロコピーメカニズムを実現するにはどうすればよいですか?
ローカル/ネットワークの 2 つのプロセス間でデータを共有/転送したい。一般的な IPC メカニズムの共有メモリとメッセージ キューを使用してデータを転送できます。しかし、これらのメカニズムには複数のコピーが含まれます。
CPU のコピー オーバーヘッドを削減するゼロ コピー メカニズムに出会いました。Linux は、 と を使用してこれをサポートしsendfile
ますsplice
。これらの API は POSIX にありません。POSIX API のみを使用してゼロコピーを実現するにはどうすればよいですか?
java - Java の SendFile と transferTo
CentOs カーネル バージョン 2.6.32 を使用しています。NIO を使用して transferTo(sendFile) の有無にかかわらずテストを行う予定です。私のテストは、1GBのファイルをあるディレクトリから別のディレクトリにコピーすることです。ただし、transferTo()を使用したため、パフォーマンスが大幅に向上することはありませんでした。ファイルからファイルへの sendFile が実際に Linux カーネルで機能するのか、それともファイルからソケットのみが機能するのか教えてください。sendFile を有効にする必要はありますか?
サンプルコード:
java - 配列の一部を参照する方法は?
object が与えられた場合byte[]
、そのようなオブジェクトを操作したい場合、しばしばその断片が必要になります。私の特定の例byte[]
では、最初の 4 バイトがメッセージの長さを記述し、次に別の 4 バイトがメッセージのタイプ (具体的な protobuf クラスにマップされる整数) を表すワイヤから取得し、残りbyte[]
がメッセージの実際の内容です ... このように
このメッセージを解析するには、コンテンツ部分を、そこからインスタンスを解析する方法を知っている特定のクラスに渡す必要があります...問題は、パーサーがどこからどこまでを読み取るかを指定できるように、メソッドが提供されていないことが多いことです配列...
そのため、最終的にその配列の残りのチャンクをコピーすることになりますが、これは効果的ではありません...
私が Java で知る限り、 2 つのインデックスだけでbyte[]
元のより大きな配列を実際に参照する別の参照を作成することはできませんbyte[]
(これは、メモリ リークを引き起こす String のアプローチでした)...
このような状況をどのように解決するのだろうか?一部を提供しないという理由だけでprotobufをあきらめるのは意味がないと思いparseFrom(byte[], int, int)
ます... protobufは単なる例であり、そのAPIが欠けている可能性があります...
では、これは非効率なコードを書かざるを得ないのでしょうか、それともできることはあるのでしょうか? (そのメソッドを追加することを除いて)...
java - HttpServletResponse を使用したゼロ コピー byte[] または ByteBuffer
Google の FlatBuffer を使用する場合、最終的に使用される型は a ですByteBuffer
(これは単に a をラップできますbyte[]
)。これを で使用していHttpServletResponse
ます。問題は、サーブレットが提供または書き込みを PrintWriter
行わないことになります。byte[]
ByteBuffer
/を別の型HttpServletResponse
にコピーせずにから出力できるようにするためのヒントはありますか?ByteBuffer
byte[]