タダです.
業務で API で使用する言語を置き換える検討をしていたりするんですが, FastAPI と Falcon を比較した際Docker イメージにした時の軽量さとベンチマークしてみてどれくらいレスポンスが速いかを計測した機会があったので,この記事に検証した内容をまとめておきます.
FastAPI と Falcon の特徴
2つの Web フレームワークがどのような特徴を持っているかをさらっておきます.FastAPI は Python 3.6 以上の速い Web フレームワークであると謳ってます.また,ASGI を使います.
FastAPI
fastapi.tiangolo.com
特徴としては次のようなものがあります.
・ 速い。非常に高性能で、NodeJSやGoと同等のパフォーマンスを発揮します(StarletteとPydanticのおかげです)。利用可能なPythonフレームワークの中で最も高速なものの一つです。
・コード化が速い。機能開発のスピードを約200%~300%向上させます。
・バグが少ない。人間(開発者)によるエラーを約40%削減。
・ 直感的。素晴らしいエディタサポート。デバッグ時間を短縮。
・ 簡単。使いやすく、学習しやすいように設計されています。ドキュメントを読む時間を短縮。
・ 短い。コードの重複を最小限に抑えます。各パラメータ宣言から複数の機能を利用できるようになっています。
・ 堅牢。すぐに使えるコードを取得できます。自動でインタラクティブなドキュメントを提供します。
・ 標準ベース。APIのオープンスタンダードに基づいています(完全に互換性があります)。OpenAPI(以前はSwaggerとして知られていた)とJSON Schema。
Falcon も速く,軽量な Web フレームワークです. WSGI を使います.
Falcon
falcon.readthedocs.io
特徴としては次のようなものがあります.
・URIテンプレートRFCに基づくルート
・リソースへのURIのRESTに触発されたマッピング
・グローバル、リソース、およびメソッドのフック
・慣用的なHTTPエラー応答
・Unicodeの完全サポート
・直感的なリクエストオブジェクトとレスポンスオブジェクト
・geventのような非同期ライブラリでうまく機能します
・安全なAPIを作成するための最小限の攻撃対象領域
・包括的なテストスイートで100%のコードカバレッジ
・他のPythonパッケージへの依存関係はありません
・Python 2.7、3.5以降をサポート
・PyPyと互換性があります
Docker イメージ化した時のサイズ
Alphine Linux ベースの Docker イメージでビルドした場合のサイズですが,2つとも同じくらいのサイズ感でした.
$ docker images | grep falcon
falcon latest c74c32855823 About a minute ago 49.2MB
$ docker images | grep fastapi
fastapi latest 88fd7ac8fa13 3 hours ago 50.1MB
どれくらい早くレスポンスがされるかのベンチマーク
wrk2 を使って以下の条件でベンチマークしてみました.
10のコネクションを維持して、秒間 100 リクエスト投げた時の計測
FastAPI,Falcon ともに大きな差異はない.
wrk2 -t2 -c10 -d30s -R100 http://localhost:8000/
Running 30s test @ http://localhost:8000/
2 threads and 10 connections
Thread calibration: mean lat.: 7.524ms, rate sampling interval: 25ms
Thread calibration: mean lat.: 7.752ms, rate sampling interval: 26ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.06ms 3.00ms 22.78ms 79.35%
Req/Sec 53.01 71.93 208.00 80.30%
3002 requests in 30.01s, 416.29KB read
Requests/sec: 100.02
Transfer/sec: 13.87KB
wrk2 -t2 -c10 -d30s -R100 http://localhost:8080/
Running 30s test @ http://localhost:8080/
2 threads and 10 connections
Thread calibration: mean lat.: 32.647ms, rate sampling interval: 209ms
Thread calibration: mean lat.: 20.032ms, rate sampling interval: 185ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.24ms 4.06ms 29.98ms 82.81%
Req/Sec 49.44 5.69 62.00 84.00%
3002 requests in 30.01s, 483.72KB read
Requests/sec: 100.03
Transfer/sec: 16.12KB
50のコネクションを維持して、秒間 500 リクエスト投げた時の計測
Latency で FastAPI と Falcon の間に差がでてきた.
wrk2 -t2 -c50 -d30s -R500 http://localhost:8000/
Running 30s test @ http://localhost:8000/
2 threads and 50 connections
Thread calibration: mean lat.: 7.982ms, rate sampling interval: 28ms
Thread calibration: mean lat.: 7.915ms, rate sampling interval: 27ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.11ms 2.25ms 19.73ms 81.05%
Req/Sec 254.29 63.28 423.00 61.43%
14991 requests in 30.00s, 2.03MB read
Requests/sec: 499.66
Transfer/sec: 69.29KB
wrk2 -t2 -c50 -d30s -R500 http://localhost:8080/
Running 30s test @ http://localhost:8080/
2 threads and 50 connections
Thread calibration: mean lat.: 46.716ms, rate sampling interval: 204ms
Thread calibration: mean lat.: 45.854ms, rate sampling interval: 200ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 14.29ms 20.81ms 135.04ms 88.48%
Req/Sec 250.44 6.95 280.00 80.10%
14991 requests in 30.00s, 2.36MB read
Requests/sec: 499.63
Transfer/sec: 80.51KB
100のコネクションを維持して、秒間 1000 リクエスト投げた時の計測
1000リクエストになったら Requests を捌く量も Latency と同じくひらいてきた.
wrk2 -t2 -c100 -d30s -R1000 http://localhost:8000/
Running 30s test @ http://localhost:8000/
2 threads and 100 connections
Thread calibration: mean lat.: 241.727ms, rate sampling interval: 819ms
Thread calibration: mean lat.: 240.797ms, rate sampling interval: 815ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 241.60ms 260.77ms 777.22ms 75.42%
Req/Sec 481.31 47.68 583.00 79.17%
29201 requests in 30.01s, 3.96MB read
Requests/sec: 973.16
Transfer/sec: 135.12KB
wrk2 -t2 -c100 -d30s -R1000 http://localhost:8080/
Running 30s test @ http://localhost:8080/
2 threads and 100 connections
Thread calibration: mean lat.: 124.110ms, rate sampling interval: 383ms
Thread calibration: mean lat.: 124.684ms, rate sampling interval: 393ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 527.57ms 528.20ms 1.86s 73.48%
Req/Sec 161.29 255.12 0.99k 71.57%
16458 requests in 30.27s, 2.59MB read
Socket errors: connect 0, read 0, write 0, timeout 600
Requests/sec: 543.71
Transfer/sec: 87.61KB
500のコネクションを維持して、秒間 5000 リクエスト投げた時の計測
wrk2 -t2 -c500 -d30s -R5000 http://localhost:8000/
Running 30s test @ http://localhost:8000/
2 threads and 500 connections
Thread calibration: mean lat.: 3006.903ms, rate sampling interval: 11796ms
Thread calibration: mean lat.: 3028.214ms, rate sampling interval: 11796ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 12.31s 3.42s 18.87s 58.52%
Req/Sec 456.00 68.00 524.00 100.00%
26269 requests in 30.01s, 3.56MB read
Socket errors: connect 251, read 64, write 0, timeout 3514
Requests/sec: 875.44
Transfer/sec: 121.59KB
wrk2 -t2 -c500 -d30s -R5000 http://localhost:8080/
Running 30s test @ http://localhost:8080/
2 threads and 500 connections
Thread calibration: mean lat.: 2613.849ms, rate sampling interval: 10739ms
Thread calibration: mean lat.: 2724.868ms, rate sampling interval: 10936ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 8.13s 2.36s 15.61s 65.29%
Req/Sec 275.50 29.50 305.00 100.00%
16381 requests in 31.28s, 2.58MB read
Socket errors: connect 251, read 153, write 0, timeout 5439
Requests/sec: 523.76
Transfer/sec: 84.39KB
1000のコネクションを維持して、秒間 10000 リクエスト投げた時の計測
wrk2 -t2 -c1000 -d30s -R10000 http://localhost:8000/
Running 30s test @ http://localhost:8000/
2 threads and 1000 connections
Thread calibration: mean lat.: 3875.593ms, rate sampling interval: 13352ms
Thread calibration: mean lat.: 3795.580ms, rate sampling interval: 13303ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 12.20s 3.03s 18.14s 57.44%
Req/Sec 514.50 39.50 554.00 100.00%
27956 requests in 30.00s, 3.79MB read
Socket errors: connect 751, read 0, write 0, timeout 9763
Requests/sec: 931.79
Transfer/sec: 129.26KB
wrk2 -t2 -c1000 -d30s -R10000 http://localhost:8080/
Running 30s test @ http://localhost:8080/
2 threads and 1000 connections
Thread calibration: mean lat.: 3676.434ms, rate sampling interval: 14540ms
Thread calibration: mean lat.: 3547.812ms, rate sampling interval: 14319ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 7.69s 2.42s 17.81s 67.25%
Req/Sec 155.50 5.50 161.00 100.00%
16445 requests in 30.53s, 2.59MB read
Socket errors: connect 751, read 45, write 0, timeout 12373
Requests/sec: 538.65
Docker イメージにした時のサイズとベンチマークを踏まえての所感
検証の結果を踏まえて次の感想を持ちました.
- Docker イメージにした時の軽量さは2つに大差はない
- リクエスト数が増えていった時も FastAPI のほうが処理スピードが速くリクエストを捌く量も多い
また, FastAPI のドキュメントをみていると,FastAPI を作る時に既存のフレームワークを参考に開発したと解説されており, Falcon も参考にして開発されているようなので改良されたのが FastAPI って位置付けなのだと感じました.
fastapi.tiangolo.com
まとめ
FastAPI と Falcon の比較をするための検証で行ったことを整理してみました.ベンチマークしてみて FastAPI が速くてパフォーマンスも優れているという所以を感じることができました.FastAPI を業務で使う機会が出てきたら習熟していけるようになっていきたいです.