スレッド間の単純なバイトストリームにPythonキューが必要ですか?
-
08-07-2019 - |
質問
Bluetooth RFCOMM(シリアルポートのような)ソケットからバイトを取得して Queue.Queue
(FIFO)にダンプする単純なスレッドがあり、これは交換する典型的な方法のようですスレッド間のデータ。正常に動作します。
これはやり過ぎですか?バイト配列を使用してから、リーダースレッド .append(somebyte)
と処理関数を .pop(0)
だけで使用できますか? Queueの保護がより複雑な「マルチプロデューサー、マルチコンシューマーキュー」に向けられているかどうかはわかりません。ポイントツーポイントのバイトストリームの無駄。キューをフラッシュする、複数のバイトを取得するなどのことは、キューでは単純なデータ型よりも厄介に思えます。
.pop()
がアトミックである場合、答えはおそらく関係があると思いますが、それでも問題になりますか?...
解決
Queue
を使用すると、Pythonのすべての実装およびバージョンでスレッドセーフであることが保証されます 。 「アトミック」である他のオブジェクトのこのメソッドまたはそのメソッドに依存しています。 (特定の実装およびバージョンで)通常、この「原子性」に翻弄されます。強力な保証ではなく(使用している特定のポイントリリース& cの実装アーティファクトのみ)、したがって、他のPython実装へのアップグレードまたはポートで導入される、微妙で非常にデバッグしにくい競合状態です。
プロファイリングで、 Queue
の強力で一般的な保証が特定の生産者/消費者のユースケースのボトルネックになっていることが示されている場合は、独自のより簡単なスレッドセーフの保証付きFIFOキュー/ストリーム。たとえば、(競合状態のネット) append
および pop
が使用に最適であることがわかっている場合は、それぞれをロックで保護するクラスを作成します取得/リリース( with
ステートメントを使用)- Queue
は、複数のプロデューサーとコンシューマーをサポートするためにわずかなオーバーヘッドを追加し、それらの数ナノ秒を削ることができます!-)
他のヒント
はい、pop()はアトミックですが、パフォーマンスがそれほど重要でない場合は、Queueを使い続けます。
入力の速度が十分に速い場合、バイトを文字列にバッファリングしてからキューにプッシュできます。これはおそらく、受信側で少し余分なレイテンシーを犠牲にして、行われるロックの量を減らすことによってスループットを向上させるでしょう。