10

私は広範囲にネットワークと対話するアプリケーションにlibuvを使用しており、割り当てられたメモリを再利用するどの手法が同時に効率的であり、実行の libuv コールバック遅延で安全であるかを懸念しています。

libuv ユーザーに公開される非常に基本的なレイヤーでは、ハンドル リーダーの設定と共にバッファー割り当てコールバックを指定する必要があります。

UV_EXTERN int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);

どこuv_alloc_cbですか

typedef void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);

しかし、ここに問題があります: このメモリ割り当てコールバックは、新しいメッセージがハンドルを介して受信されるたびに呼び出され (たとえば、ハンドルからの各 UDP データグラムuv_udp_tが受信されます)、各受信 UDP データグラムに対する新しいバッファの単純な割り当ては非常に非メモリのようです。 -賢い。

したがって、可能な場合は同じ割り当てられたメモリを再利用する一般的な C 手法 (おそらく、libuv コールバック システムによって導入された遅延実行コンテキスト内) を求めています。

また、可能であれば、windows-portable のままにしたいと考えています。

ノート:

  • 私はこの質問を認識しています: libuv はバッファを接続にアタッチして再利用する機能を提供しますか? 受け入れられた答えは、静的に割り当てられたバッファがうまくいかないという事実を述べる以外に、libuvで実際にメモリ割り当てを正しく行う方法には答えません。特に、(ラッパー構造または handle-> のいずれかを介して) ハンドルにアタッチされたバッファーの安全性 (libuv メイン ループの複数の反復にわたる別の読み取りコールバック呼び出しとオーバーラップする可能性がある、同じバッファーでの遅延書き込みコールバック) をカバーしていません。データ コンテキスト)。
  • http://nikhilm.github.io/uvbook/filesystem.htmlを読んで、スニップの下に次のフレーズがあることに気付きましたuvtee/main.c - Write to pipe:

    コピーを作成して、互いに独立して write_data への 2 つの呼び出しから 2 つのバッファーを解放できるようにします。このようなデモ プログラムでは問題ありませんが、主要なアプリケーションでの参照カウント バッファーやバッファーのプールなど、よりスマートなメモリ管理が必要になるでしょう。

    しかし、libuv バッファーでの参照カウントに関する解決策 (これを適切に実行するにはどうすればよいでしょうか?) や、libuv 環境でのバッファーのプールの明示的な例 (そのためのライブラリはありますか?) を見つけることができませんでした。

4

2 に答える 2

1

Linux を使用している場合は、幸運です。Linux カーネルは通常、デフォルトでSLAB Allocatorと呼ばれるものを使用します。このアロケータの利点は、再利用可能なブロックのプールを維持することで、実際のメモリ割り当てを削減できることです。これが意味することは、常に同じサイズ (理想的には PAGE_SIZE の pow2 サイズ) のバッファーを割り当てている限り、malloc()Linux で使用しても問題ないということです。

Linux (または FreeBSD または Solaris) を使用していない場合、またはクロスプラットフォーム アプリケーションを開発している場合は、SLAB アロケータのクロスプラットフォーム実装であるglibとその使用を検討できます。Memory Slicesそれをサポートするプラットフォームでネイティブ実装を使用するため、Linux で使用しても利点はありません (私は自分でいくつかのテストを実行しました)。同じことができる他のライブラリがあるか、自分で実装できると確信しています。

于 2015-05-22T13:20:07.963 に答える