パフォーマンスと最適化—Djangoドキュメント

提供:Dev Guides
< DjangoDjango/docs/3.2.x/topics/performance
移動先:案内検索

パフォーマンスと最適化

このドキュメントでは、Djangoコードをより効率的に、より速く、より少ないシステムリソースで実行するのに役立つテクニックとツールの概要を説明します。

序章

一般に、最初の懸念は、が機能するコードを作成することです。このコードのロジックは、期待される出力を生成するために必要に応じて機能します。 ただし、コードを効率的にとして機能させるには、これだけでは不十分な場合があります。

この場合、必要なのは、コードの動作に影響を与えることなく、または最小限にとどめて、コードのパフォーマンスを向上させるための何か(実際には、多くの場合、それらのコレクション)です。


一般的なアプローチ

をに最適化するものは何ですか?

「パフォーマンス」とはどういう意味かを明確に理解することが重要です。 それの1つのメトリックだけではありません。

速度の向上はプログラムの最も明白な目的かもしれませんが、メモリ消費量の削減やデータベースまたはネットワークへの要求の削減など、他のパフォーマンスの改善が求められる場合もあります。

ある領域での改善により、別の領域でのパフォーマンスが向上することがよくありますが、常にそうとは限りません。 時には、ある人が別の人を犠牲にすることさえあります。 たとえば、プログラムの速度が向上すると、より多くのメモリを使用する可能性があります。 さらに悪いことに、それは自滅的である可能性があります-速度の向上がメモリを大量に消費し、システムがメモリを使い果たし始めた場合、あなたは善よりも害を及ぼしたことになります。

覚えておくべき他のトレードオフがあります。 あなた自身の時間は貴重なリソースであり、CPU時間よりも貴重です。 一部の改善は、実装する価値がないほど難しい場合や、コードの移植性や保守性に影響を与える場合があります。 すべてのパフォーマンスの改善が努力に値するわけではありません。

したがって、どのようなパフォーマンスの向上を目指しているかを知る必要があります。また、その方向を目指す正当な理由があることも知っておく必要があります。そのためには、次のことが必要です。


パフォーマンスベンチマーク

コードのどこに非効率性があるのかを推測したり推測したりするのはよくありません。

Djangoツール

django-debug-toolbar は、コードが実行していることと、コードの実行に費やした時間についての洞察を提供する非常に便利なツールです。 特に、ページが生成しているすべてのSQLクエリと、各クエリにかかった時間を表示できます。

ツールバーにはサードパーティのパネルも用意されており、たとえば、キャッシュのパフォーマンスやテンプレートのレンダリング時間についてレポートできます。


サードパーティのサービス

リモートHTTPクライアントの観点からサイトのページのパフォーマンスを分析およびレポートし、実際に実際のユーザーのエクスペリエンスをシミュレートする無料のサービスがいくつかあります。

これらはコードの内部についてレポートすることはできませんが、Django環境内から適切に測定できない側面を含め、サイトの全体的なパフォーマンスに関する有用な洞察を提供することができます。 例は次のとおりです。

同様の分析を実行する有料サービスもいくつかあります。その中には、Django対応であり、コードベースと統合してパフォーマンスをはるかに包括的にプロファイルできるものもあります。


最初から物事を正しくする

最適化の作業の中には、パフォーマンスの欠点に取り組むことを伴うものもありますが、パフォーマンスの向上について考える前に採用する必要があるグッドプラクティスの一部として、とにかく行う作業に組み込むことができる作業もあります。

この点で、Pythonは使用するのに優れた言語です。これは、エレガントに見え、適切に感じられるソリューションが通常、最高のパフォーマンスを発揮するためです。 ほとんどのスキルと同様に、「正しく見える」ものを学ぶには練習が必要ですが、最も役立つガイドラインの1つは次のとおりです。

適切なレベルで作業する

Djangoにはさまざまなアプローチ方法がありますが、特定の方法で何かを行うことができるからといって、それが最も適切な方法であるとは限りません。 たとえば、QuerySet、Python、またはテンプレートで、同じこと(コレクション内のアイテムの数など)を計算できる場合があります。

ただし、ほとんどの場合、この作業を高いレベルではなく低いレベルで実行する方が高速です。 より高いレベルでは、システムは複数レベルの抽象化と機械の層を介してオブジェクトを処理する必要があります。

つまり、データベースは通常、Pythonよりも高速に処理を実行でき、テンプレート言語よりも高速に処理を実行できます。

# QuerySet operation on the database
# fast, because that's what databases are good at
my_bicycles.count()

# counting Python objects
# slower, because it requires a database query anyway, and processing
# of the Python objects
len(my_bicycles)

# Django template filter
# slower still, because it will have to count them in Python anyway,
# and because of template language overheads
{{ my_bicycles|length }}

一般的に言って、ジョブに最も適切なレベルは、コーディングしやすい最低レベルのレベルです。

ノート

上記の例は単なる例示です。

まず、実際のケースでは、カウントの前後に何が起こっているかを考慮して、その特定のコンテキストでそれを行うための最適な方法を見つける必要があります。 データベース最適化ドキュメントでは、テンプレートでのカウントが優れている場合について説明しています。

次に、考慮すべき他のオプションがあります。実際のケースでは、テンプレートから直接QuerySet count()メソッドを呼び出すテンプレート:My bicycles.countが最も適切な選択である可能性があります。 。


キャッシング

多くの場合、値の計算にはコストがかかる(つまり、リソースを大量に消費し、時間がかかる)ため、次に必要になったときに備えて、すばやくアクセスできるキャッシュに値を保存することには大きなメリットがあります。

これは十分に重要で強力な手法であるため、Djangoには包括的なキャッシュフレームワークやその他の小さなキャッシュ機能が含まれています。

キャッシングフレームワーク

Djangoのキャッシングフレームワークは、動的コンテンツを保存してリクエストごとに計算する必要がないようにすることで、パフォーマンスを向上させる非常に重要な機会を提供します。

便宜上、Djangoはさまざまなレベルのキャッシュ粒度を提供します。特定のビューの出力をキャッシュすることも、作成が難しい部分のみをキャッシュすることも、サイト全体をキャッシュすることもできます。

キャッシュの実装は、記述が不十分なためにパフォーマンスが低下しているコードを改善するための代替手段と見なされるべきではありません。 これは、ショートカットではなく、パフォーマンスの高いコードを作成するための最終ステップの1つです。


cached_property

クラスインスタンスのメソッドを複数回呼び出さなければならないのはよくあることです。 その機能が高価な場合、そうすることは無駄になる可能性があります。

cached_property デコレータを使用すると、プロパティによって返される値が保存されます。 次回そのインスタンスで関数が呼び出されると、関数は再計算するのではなく、保存された値を返します。 これは、selfを唯一の引数として取るメソッドでのみ機能し、メソッドをプロパティに変更することに注意してください。

特定のDjangoコンポーネントには、独自のキャッシュ機能もあります。 これらについては、以下のこれらのコンポーネントに関連するセクションで説明します。


怠惰を理解する

怠惰は、キャッシングを補完する戦略です。 キャッシングは、結果を保存することで再計算を回避します。 怠惰は、実際に必要になるまで計算を遅らせます。

怠惰は、インスタンス化される前、またはインスタンス化が可能になる前でさえ、物事を参照することを可能にします。 これには多くの用途があります。

たとえば、 lazy translation は、レンダリングされたテンプレートなど、翻訳された文字列が実際に必要になるまで実行されないため、ターゲット言語がわかる前に使用できます。

怠惰は、そもそも仕事を避けようとすることで労力を節約する方法でもあります。 つまり、怠惰の1つの側面は、結局必要であることが判明しない可能性があるため、実行する必要があるまで何も実行しないことです。 したがって、怠惰はパフォーマンスに影響を与える可能性があり、関係する作業の費用が高ければ高いほど、怠惰によって得られるものは多くなります。

Pythonは、特にジェネレーターおよびジェネレーター式コンストラクトを介して、遅延評価のための多数のツールを提供します。 Pythonの怠惰について読んで、コードで怠惰なパターンを利用する機会を見つけることは価値があります。

Djangoの怠惰

Django自体はかなり怠惰です。 この良い例は、QuerySetsの評価にあります。 QuerySetsは怠惰です。 したがって、QuerySetを作成し、渡し、他のQuerySetsと組み合わせることができます。実際にデータベースにアクセスして、記述されているアイテムをフェッチする必要はありません。 渡されるのはQuerySetオブジェクトであり、データベースから最終的に必要となるアイテムのコレクションではありません。

一方、特定の操作では、QuerySet の評価が強制されます。 QuerySetの時期尚早な評価を回避することで、データベースへの高額で不必要な移動を省くことができます。

Djangoは、 keep_lazy()デコレータも提供しています。 これにより、遅延引数を使用して呼び出された関数は、必要な場合にのみ評価され、それ自体が遅延動作することができます。 したがって、怠惰な議論(高価なものになる可能性があります)は、厳密に要求されるまで評価を求められません。


データベース

データベースの最適化

Djangoのデータベースレイヤーは、開発者がデータベースから最高のパフォーマンスを得るのに役立つさまざまな方法を提供します。 データベース最適化ドキュメントは、関連するドキュメントへのリンクをまとめ、データベースの使用を最適化しようとするときに実行する手順の概要を示すさまざまなヒントを追加します。


HTTPパフォーマンス

ミドルウェア

Djangoには、サイトのパフォーマンスを最適化するのに役立つミドルウェアがいくつか付属しています。 それらが含まれます:

ConditionalGetMiddleware

ETagおよびLast-Modifiedヘッダーに基づいて条件付きでGET応答する最新のブラウザーのサポートを追加します。 また、必要に応じてETagを計算して設定します。


GZipMiddleware

最新のすべてのブラウザの応答を圧縮し、帯域幅と転送時間を節約します。 GZipMiddlewareは現在セキュリティリスクと見なされており、TLS / SSLによって提供される保護を無効にする攻撃に対して脆弱であることに注意してください。 詳細については、 GZipMiddleware の警告を参照してください。


セッション

キャッシュされたセッションの使用

キャッシュされたセッションの使用は、データベースなどの低速のストレージソースからセッションデータをロードする必要をなくし、代わりに頻繁に使用されるセッションデータをメモリに保存することで、パフォーマンスを向上させる方法です。


静的ファイル

定義上動的ではない静的ファイルは、最適化の向上の優れたターゲットになります。

ManifestStaticFilesStorage

Webブラウザーのキャッシュ機能を利用することにより、最初のダウンロード後に特定のファイルのネットワークヒットを完全に排除できます。

ManifestStaticFilesStorage は、静的ファイルのファイル名にコンテンツ依存のタグを追加して、ブラウザーが将来の変更を見逃すことなくそれらを長期間キャッシュできるようにします。ファイルが変更された場合も同様です。タグを付けると、ブラウザはアセットを自動的にリロードします。


「縮小」

いくつかのサードパーティのDjangoツールとパッケージは、HTML、CSS、およびJavaScriptを「縮小」する機能を提供します。 不要な空白、改行、コメントを削除し、変数名を短くして、サイトが公開するドキュメントのサイズを縮小します。


テンプレートのパフォーマンス

ご了承ください:

  • {% block %}を使用すると、{% include %}を使用するよりも高速になります
  • 多くの小さな断片から組み立てられた、非常に断片化されたテンプレートは、パフォーマンスに影響を与える可能性があります

キャッシュされたテンプレートローダー

キャッシュテンプレートローダーを有効にすると、レンダリングが必要になるたびに各テンプレートをコンパイルする必要がなくなるため、パフォーマンスが大幅に向上することがよくあります。


利用可能なソフトウェアの異なるバージョンを使用する

使用しているソフトウェアのさまざまなバージョンが利用可能かどうかを確認する価値がある場合があります。

これらの手法は、すでに十分に最適化されたDjangoサイトのパフォーマンスの限界を押し上げたい上級ユーザーを対象としています。

ただし、これらはパフォーマンスの問題に対する魔法の解決策ではなく、より基本的なことを正しく行っていないサイトに、わずかな利益よりも優れた利益をもたらす可能性はほとんどありません。

ノート

繰り返す価値があります。すでに使用しているソフトウェアの代替品を探すことは、パフォーマンスの問題に対する最初の答えではありません。 このレベルの最適化に到達したら、正式なベンチマークソリューションが必要です。


多くの場合、常にではありませんが、新しい方が優れています

手入れの行き届いたソフトウェアの新しいリリースの効率が低下することはかなりまれですが、メンテナは考えられるすべてのユースケースを予測できるわけではありません。したがって、新しいバージョンの方がパフォーマンスが向上する可能性があることを認識しながら、常にパフォーマンスが向上するとは限りません。意思。

これはDjango自体にも当てはまります。 後続のリリースでは、システム全体で多くの改善が見られましたが、アプリケーションの実際のパフォーマンスを確認する必要があります。変更により、パフォーマンスが向上するのではなく、低下する場合があるためです。

新しいバージョンのPythonおよびPythonパッケージも、多くの場合、パフォーマンスが向上しますが、想定するのではなく、測定します。

ノート

特定のバージョンで異常なパフォーマンスの問題が発生した場合を除いて、新しいリリースでは通常、より優れた機能、信頼性、セキュリティが見つかり、これらの利点は、勝ち負けする可能性のあるパフォーマンスよりもはるかに重要です。


Djangoのテンプレート言語の代替

ほとんどすべての場合、Djangoの組み込みテンプレート言語で十分です。 ただし、Djangoプロジェクトのボトルネックがテンプレートシステムにあるようで、これを修正する他の機会を使い果たした場合は、サードパーティの代替手段が答えになる可能性があります。

Jinja2 は、特に速度に関しては、パフォーマンスを向上させることができます。

代替テンプレートシステムは、Djangoのテンプレート言語を共有する範囲が異なります。

ノート

' テンプレートでパフォーマンスの問題が発生した場合、最初に行うことは、その理由を正確に理解することです。 代替のテンプレートシステムを使用すると、より高速になる場合がありますが、同じメリットがその問題にならずに利用できる場合もあります。たとえば、テンプレートの高価な処理とロジックをビューでより効率的に実行できます。


代替ソフトウェアの実装

使用しているPythonソフトウェアが、同じコードをより高速に実行できる別の実装で提供されているかどうかを確認する価値があるかもしれません。

ただし、適切に記述されたDjangoサイトのパフォーマンスの問題のほとんどは、Pythonの実行レベルではなく、非効率的なデータベースクエリ、キャッシュ、およびテンプレートにあります。 不十分に記述されたPythonコードに依存している場合、パフォーマンスの問題は、実行速度を上げることで解決される可能性はほとんどありません。

別の実装を使用すると、互換性、展開、移植性、またはメンテナンスの問題が発生する可能性があります。 言うまでもなく、非標準の実装を採用する前に、アプリケーションが潜在的なリスクを上回るのに十分なパフォーマンスの向上を提供することを確認する必要があります。

これらの警告を念頭に置いて、次の点に注意する必要があります。

PyPy

PyPy は、Python自体でのPythonの実装です(「標準」のPython実装はCです)。 PyPyは、通常、重量級のアプリケーションで大幅なパフォーマンスの向上を実現できます。

PyPyプロジェクトの主な目的は、既存のPythonAPIおよびライブラリとの互換性です。 Djangoは互換性がありますが、依存している他のライブラリの互換性を確認する必要があります。


PythonライブラリのC実装

一部のPythonライブラリもCで実装されており、はるかに高速になります。 彼らは同じAPIを提供することを目指しています。 互換性の問題と動作の違いは不明ではないことに注意してください(そして常にすぐに明らかになるとは限りません)。