0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

  • 同期処理 vs 非同期処理
  • 並行処理 vs 並列処理
  • プロセス vs スレッド
  • I/Oバウンド vs CPUバウンド
  • イベントループ vs スレッドプール
  • GIL (Global Interpreter Lock)

皆さんは,これらの用語の関係性を他人にわかりやすく説明できますか?

「なんとなく async def を使っている」「重い処理は await すればいいんでしょ?」
もしそう思っているなら,あなたのFastAPIアプリケーションは本来の性能を発揮できていないかもしれません.

本記事では,あやふやになりがちなこれらの概念を整理し,FastAPIが裏側でどのようにリクエストを捌いているのかを,図解を交えて解説します.
※ 本記事はFastAPI(Python)を主軸に解説します.

1. 概念の整理:処理の「進め方」と「実行環境」

まず,「同期・非同期」と「並行・並列」という,よく混同される2つの対比軸を明確にします.

1-1. 同期処理 vs 非同期処理

これは「タスクの待ち時間をどう扱うか」という,時間の使い方の話です.カフェの注文を例に考えると直感的です.

同期処理(Sync)

「前の人が終わるまで,列から動けない」状態です.

  1. レジで注文する
  2. 店員がコーヒーを淹れ終わるまで,レジの前でじっと待つ(ブロッキング)
  3. コーヒーを受け取ってから,ようやく次の人が注文できる

非同期処理(Async)

「注文だけして,出来上がるまで別のことをする」状態です.

  1. レジで注文する
  2. 番号札(Future/Task)を受け取り,列を離れる(すぐに次の人の注文を受け付ける)
  3. 席でスマホを見たり(別の処理),他の作業をする
  4. 呼び出されたら(完了通知),コーヒーを受け取る

image.png

特徴 同期処理 (Sync) 非同期処理 (Async)
実行順序 コードの記述順通り 完了順(前後する可能性がある)
待ち時間 何もしない(ブロック) 別のタスクを処理する
メリット 直感的でデバッグしやすい I/O待ちが多いシステムで高効率
デメリット 大量のリクエストで詰まる 制御が複雑になる

1-2. 並行処理 vs 並列処理

これは「いくつの作業主体(手)で実行するか」という,リソースの使い方の話です.こちらはキッチンのシェフを例にします.

並行処理(Concurrency)

「1人のシェフが,複数の料理を同時進行する」状態です.

  • シェフは1人
  • 「野菜を切る」→「鍋を火にかける」→「煮込んでいる間に肉を切る」といったように,タスクを細かく切り替えながら作業する
  • ある「瞬間」を見れば,やっていることは1つだけ.しかし,素早い切り替え(コンテキストスイッチ)により,人間からは同時に進んでいるように見える

並列処理(Parallelism)

「複数のシェフが,完全に同時に料理する」状態です.

  • シェフは複数人(マルチコア)
  • シェフAが「野菜を切る」のと全く同じ瞬間に,シェフBが「肉を焼く」
  • 物理的に同時に動いている

image.png

特徴 並行処理 (Concurrency) 並列処理 (Parallelism)
作業主体 論理的に複数(実体は1つの場合も) 物理的に複数(マルチコア)
動作原理 タスクの高速な切り替え 同時実行
得意分野 I/Oバウンド(待ち時間の有効活用) CPUバウンド(計算速度の向上)

2. 知っておくべき重要用語

仕組みを理解するための「部品」について定義します.より深く理解したい方は,リンク先の良記事も併せて参照してください.

プロセスとスレッド

プログラムが動くときの「箱(プロセス)」と「作業者(スレッド)」の関係です.

I/OバウンドとCPUバウンド

処理の遅延原因(ボトルネック)が「通信などの待ち時間」にあるか,「計算処理」にあるかの違いです.

GIL (Global Interpreter Lock)

Python(CPython)において,1つのプロセス内では同時に1つのスレッドしかPythonコードを実行できないという制約です.これにより,Pythonでは単純なマルチスレッド化がCPUバウンドな処理の高速化に繋がりにくい特徴があります.

3. Pythonの非同期戦略:イベントループとスレッドプール

これまでの知識を前提に,Python(FastAPI)がどうやって効率的に動いているかを可視化します.

イベントループ (Event Loop) の動き

async def の世界です.
作業者(スレッド)は1人しかいません.しかし,I/O待ち(await)が発生すると,即座に別のタスクに切り替えて処理を進めます.これにより,待ち時間を極限まで減らします.

スレッドプール (ThreadPool) の動き

def(同期関数)の世界です.
イベントループとは別に,複数の作業者(スレッド)を用意します.タスクが来たら空いている作業者に割り振るため,物理的に複数の処理が同時に進みます.

4. FastAPIのアーキテクチャ

FastAPI(Uvicorn)は,上記のイベントループとスレッドプールを組み合わせて動作します.

  1. Worker(プロセス): リクエストを捌く独立した店舗のようなもの
  2. Event Loop: 各Workerの中に1つだけ存在する司令塔.async def の処理はここで行われる
  3. ThreadPool: 各Workerに付属する裏方集団.def の処理はここへ飛ばされる

5. よくある間違いとベストプラクティス

FastAPIでやりがちなミスと,正しい実装方法を紹介します.

❌ 間違い:async def の中でブロッキング処理をする

async def はイベントループ上で動きます.ここで time.sleep や重い計算を行うと,イベントループ自体が停止し,サーバー全体がフリーズして他のリクエストを受け付けなくなります.

@app.get("/bad")
async def bad_handler():
    time.sleep(5) 
    return {"msg": "これは危険"}

⭕️ 正解1:非同期ライブラリを使う

asyncio.sleep のように await 可能な非同期関数を使えば,待っている間に制御がイベントループに戻り,他のリクエストを処理できます.

import asyncio

@app.get("/good_async")
async def good_handler():
    await asyncio.sleep(5)
    return {"msg": "これはOK"}

⭕️ 正解2:同期処理なら def で定義する

def で定義された関数は,FastAPIが自動的にスレッドプールで実行してくれます.これにより,同期的なブロッキング処理(標準の sleeprequests など)を行ってもイベントループは止まりません.

@app.get("/good_sync")
def sync_handler():
    time.sleep(5)
    return {"msg": "これもOK"}

⭕️ 正解3:async 内でどうしても同期処理をしたい場合

計算処理など,どうしても async 関数内で重い処理を呼び出す必要がある場合は,run_in_threadpool を使って明示的にスレッドプールへ処理を逃がします.

from fastapi.concurrency import run_in_threadpool

@app.get("/manual")
async def manual_handler():
    result = await run_in_threadpool(heavy_sync_function)
    return {"result": result}

ちなみにdef 内で非同期処理をするとエラーになります.

まとめ

FastAPIにおける非同期処理のポイントは以下の3点です.

  1. 同期 vs 非同期: 「待ち時間をどう使うか」の違い.I/OバウンドなWebサーバーでは非同期が有利
  2. Workerの構造: 各Workerは「1つのEvent Loop」と「ThreadPool」を持っている
  3. 使い分け:
    • 非同期対応ライブラリを使うなら async def
    • 同期ライブラリやCPUバウンドな処理なら def (FastAPIがスレッドプールでよしなにやってくれる)

この仕組みを理解していれば,「なぜかリクエストが詰まる」「CPU使用率が上がらない」といったトラブルに遭遇した際も,原因の切り分けがスムーズになるはずです.つよつよエンジニア目指して頑張りましょう!

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?