skydum

個人的な作業記録とか備忘録代わりのメモ

pythonで非同期処理

最近良く非同期処理を書く。

非同期処理を書くときはthreading.Threadをよく使っていたが、最近はasyncioも使うことがある。

 

asyncioはスレッドを作らなくても良くてイベントループにタスクを追加する?だけで良いので処理が軽いのがメリットかなと考えている。

 

Threadはスレッドを作るときのコストが大きいので処理時間が短いものをThreadにするとスレッドの作成時間 + 処理時間で考えるとスレッドの作成時間分だけasyncioよりも不利になるという認識。

 

処理時間が長くてスレッド数がそれほど多くないならThreadingでも良いのかなと思う。

asyncioならスレッド数や処理時間の長短を考えなくても良いので、何も考えずにasyncioにしたほうがいいのだろうかとも思が、あんまりasyncioについて詳しくないので勉強したほうが良さそう。

 

 

 

GPT-4 Turboに聞いてみた、何度かツッコミを入れたけれども意外とちゃんと答えてくれる。

 

特徴 threading.Thread asyncio
主な用途 タスク間の並行実行が必要な場合 イベントループを用いた非同期I/Oタスクの管理
CPU使用効率 GILによりCPUバウンドのタスクでは複数のスレッドが同時に実行されにくい。しかし、I/Oバウンドのタスクでは有効。 CPUバウンドのタスクには向いていないが、I/Oバウンドの場合に高効率。
メモリ使用量 スレッドごとにメモリが必要とされるため、多くのスレッドを生成するとメモリ使用量が増加する。 タスク管理がイベントループ内で行われるため、多数のタスクを効率的に管理し、メモリ使用量を抑えることができる。
リスク デッドロックやデータ競合といった同期処理に関連する問題が発生しやすい。 正しい非同期コーディングとエラーハンドリングが求められる。不適切なハンドリングではデバッグが難しくなることがある。
スケーラビリティ I/Oバウンドのタスクにおいては良好。CPUバウンドではmultiprocessingの利用が推奨される。 非常に高い。I/Oバウンドのタスクにおいて大量の接続やリクエストを効率的に処理可能。
適用シナリオ 既存のブロッキングI/Oライブラリとの互換性が必要な場合や、簡単なバックグラウンドタスクの実行。 高いレベルのI/O処理性能を必要とするアプリケーション、例えばウェブサーバーやデータ収集ツールなど。

 

使用すべきシナリオと注意点

  • threading.Threadの使用を推奨するシナリオ:

    • 既存の多くのブロッキングI/O操作を含むアプリケーションで効率を上げたい場合。
    • 別々のタスクがCPUをほとんど使わず、主にI/Oに依存する場合。
  • asyncioの使用を推奨するシナリオ:

    • 非同期プログラミングをフル活用し、多くの接続やリクエストを効率的に扱いたい場合。
    • イベントループを利用して、I/O操作が重なるシステムやアプリケーションを開発したい場合。

注意点

  • threading.Thread:

    • GILの影響で、CPUの使用効率が制限されることがある。
    • 大量のスレッドを生成するとメモリ使用量が増加し、パフォーマンスが低下する場合がある。
  • asyncio:

    • 正しい非同期コードの書き方やエラーハンドリングが求められる。
    • バグやデバッグが難しくなる可能性があるため、より注意深い設計が必要。

両技術はそれぞれのシナリオに適した強みを持つが、すべてのタスクに最適とは限らない。特に、CPUバウンドタスクには、プロセスベースの並列性を提供するmultiprocessingモジュールの使用を検討するのが良い。