Python で任意のサイズのバイト チャンクを処理する効率的な FIFO キュー 質問する

Python で任意のサイズのバイト チャンクを処理する効率的な FIFO キュー 質問する

任意のサイズのバイト チャンクを効率的に先頭に追加し、任意のサイズのバイト チャンクを効率的に末尾からポップできる FIFO バッファーを実装するにはどうすればよいですか?

背景:

ファイルのようなオブジェクトから任意のサイズのチャンクでバイトを読み取り、それ自体がファイルのようなオブジェクトであり、クライアントが任意のサイズのチャンクでバイトを読み取ることができるクラスがあります。

私がこれを実装した方法は、クライアントがバイトのチャンクを読み取りたいときはいつでも、クラスが基になるファイルのようなオブジェクト (それらのオブジェクトに適したチャンク サイズを持つ) から繰り返し読み取り、要求されたサイズのチャンクをクライアントに提供するのに十分なバイトがキューにたまるまで、バイトを FIFO キューの先頭に追加することです。その後、それらのバイトをキューの末尾からポップして、クライアントに返します。

基礎となるファイルのようなオブジェクトのチャンク サイズが、クラスから読み取るときにクライアントが使用するチャンク サイズよりもはるかに大きい場合に、パフォーマンスの問題が発生しています。

基礎となるファイルのようなオブジェクトのチャンク サイズが 1 MiB で、クライアントが読み取るチャンク サイズが 1 KiB だとします。クライアントが初めて 1 KiB を要求すると、クラスは 1 MiB を読み取って FIFO キューに追加する必要があります。次に、その要求と後続の 1023 の要求に対して、クラスは FIFO キューの末尾から 1 KiB を取り出す必要があります。FIFO キューのサイズは 1 MiB から 0 バイトまで徐々に減少し、その時点でサイクルが再び始まります。

現在、私はこれを StringIO オブジェクトで実装しています。StringIO オブジェクトの末尾に新しいバイトを書き込むのは高速ですが、先頭からバイトを削除するのは非常に遅くなります。これは、最初のバイト チャンクを除いた以前のバッファ全体のコピーを保持する新しい StringIO オブジェクトを作成する必要があるためです。

同様の問題を扱う SO の質問では、deque コンテナを指す傾向があります。ただし、deque は二重リンク リストとして実装されています。チャンクを deque に書き込むには、チャンクをそれぞれ 1 バイトを含むオブジェクトに分割する必要があります。次に、deque は各オブジェクトに格納用に 2 つのポインターを追加します。これにより、バイト数と比較してメモリ要件が少なくとも 1 桁増加する可能性があります。また、リンク リストをトラバースして各オブジェクトを処理し、チャンクをオブジェクトに分割したり、オブジェクトをチャンクに結合したりするには、長い時間がかかります。

ベストアンサー1

現在、私はこれを StringIO オブジェクトで実装しています。StringIO オブジェクトの末尾に新しいバイトを書き込むのは高速ですが、先頭からバイトを削除するのは非常に遅くなります。これは、最初のバイト チャンクを除いた以前のバッファ全体のコピーを保持する新しい StringIO オブジェクトを作成する必要があるためです。

実際、FIFO を実装する最も一般的な方法は、次のように 2 つのポインターを持つラップアラウンド バッファーを使用することです。

ここに画像の説明を入力してください 画像ソース

StringIO()これを実装するには、.seek()適切な場所から読み取り/書き込みを行います。

おすすめ記事