2019年のStackoverflowの調査によると、Pythonプログラミング言語は開発者の間で73.1%の承認を得ました。 データサイエンスと機械学習(ML)では、Rustに次いで2位にランクされています。
Pythonは開発者のお気に入りです。 複雑さよりもシンプルさ-それは、その堅牢性とそのコア哲学のために知られている高レベルの言語です。 しかし、Pythonアプリケーションのパフォーマンスは別の話です。 他のアプリケーションと同様に、パフォーマンスの問題のシェアを持っています。
ほとんどの場合、RetraceなどのAPMツールは、アプリケーションのパフォーマンスの問題を解決するのに役立ちます。 しかし、あなたのPythonアプリケーションが4時間実行されていて、サーバーがメモリ不足の場合はどうなりますか? これは、メモリリソースに関連する特定の問題です。 これはメモリリークと呼ばれます。
開発者は犯人を見つける必要があります。 これがPythonメモリプロファイラの出番です。
さらに調べてみましょう。 Pythonメモリプロファイラとは何ですか?
プロファイリングアプリケーションには、CPU、メモリなどの問題が常に発生します。 しかし、Pythonアプリケーションはメモリ管理の問題を起こしやすいです。 これは主に、PythonがデータサイエンスとMLアプリケーションに適用され、膨大な量のデータで動作するためです。 また、Pythonはユーザーに任せるのではなく、デフォルトでメモリ管理システムに依存しています。
Pythonコードは分散処理フレームワークを介してコンテナ内で動作するため、各コンテナには一定量のメモリが含まれています。 コードの実行がメモリ制限を超えると、コンテナは終了します。 これは、開発でメモリエラーが発生する場合です。 しかし、それは必ずしもそうではありません。
しかし、それは必ずしもそうではありません。 開発者が何が起こっているのかわからない場合があります。 たぶん、オブジェクトは、それが想定されていないときに参照にぶら下がっていて、時間の経過とともに蓄積されているかもしれません。 ピークに達すると、メモリの問題が発生します。
クイックフィックスの解決策は、メモリ割り当てを増やすことです。 しかし、これは資源の無駄になる可能性があるため、実用的ではありません。 また、予測不可能なメモリスパイクのためにアプリケーションの安定性を危険にさらす可能性があります。
したがって、Pythonメモリプロファイラの助けが必要です。 Pythonメモリプロファイラの目的は、メモリリークを見つけてPythonアプリケーションのメモリ使用量を最適化することです。 これらのタイプのPythonメモリプロファイラは、使用されるコードとパッケージのスペース効率を理解しています。
Top Python Memory Profilers
Pythonは自動的にメモリを管理しますが、長時間実行されるPythonジョブは多くのメモリを消費するため、ツールが必要です。 ほとんどの場合、これらのジョブは、ガベージコレクションを適切に実行しても、プロセスが終了するまでオペレーティングシステムにメモリを返 以下は、既知のPythonメモリプロファイラのリストです。
:Pympler
Pympler
Jean Brouwers、Ludwig Haehne、Robert Schuppeniesは2008年にPymplerを建てました。 彼らはpymplerがPythonオブジェクトのサイズと寿命の詳細を取得するpymplingのプロセスを導入しました。PymplerのPythonメモリプロファイラは、実行中のアプリケーション内のPythonオブジェクトのメモリ動作を分析します。 これは、完全でスタンドアロンのPythonメモリプロファイリングソリューションを提供します。 また、メモリの肥大化やその他の”pymples”のような実行時の動作にエラーが発生する可能性があります。”
Pymplerの中には三つの別々のモジュールがあります。 asizeofモジュールはPythonオブジェクトのサイズ情報を提供します。
>>> from pympler import asizeof
>>> obj =
>>> asizeof.asizeof(obj)
>>> print (asizeof.asized(obj, detail=1)./p>
‘i’size=32flat=32
3size=16flat=16
2size=16flat=16
1size=16flat=16
第二に、muppyモジュールを実装しましょう:
iv id pymplerからインポートmuppy
>>>>>>>>>>>>allobjects=muppyです。p>
>>>>>>>>>>>>>ymplerインポートの概要から
>>>>i=summary。要約(allObjects)
>>>>要約。print_(sum)
types | | # objects | | total size |
========================== | | =========== | | ============ |
str | | 13262 | | 1.01 MB |
dict | | 2120 | | 659.99 KB |
code | | 3362 | | 343.73 KB |
list | | 2587 | | 247.46 KB |
type | | 639 | | 242.61 KB |
tuple | | 2069 | | 58.83 KB |
set | | 86 | | 44.57 KB |
wrapper_descriptor | | 1247 | | 43.84 KB |
builtin_function_or_method | | 1014 | | 35.65 KB |
method_descriptor | | 937 | | 32.94 KB |
abc.ABCMeta | | 66 | | 32.38 KB |
weakref | | 818 | | 28.76 KB |
int | | 1612 | | 24. |
ここでは、muppyモジュールを使用してヒープ内のすべてのpythonオブジェクトを表示できます。 別の要約を呼び出して比較して、いくつかの配列にメモリリークがあるかどうかを確認できます。 Muppyモジュールの詳細はこちらをご覧ください。 Pymplerプロファイラの第三のモジュールは、クラスTrackerです。 これは、特定のクラスのオブジェクトの有効期間を追跡します。 Thus, it provides insight into instantiation patterns and helps developers understand how specific objects contribute to the memory footprint in the long run.
>>> tr = classtracker.ClassTracker()
>>> tr.track_class(Document)
>>> tr.create_snapshot(description=’Snapshot 1′)
>>> doc = create_document()
>>> tr.create_snapshot(description=’Snapshot 2′)
>>> tr.stats.print_summary()
–概要———————-
スナップショット1アクティブ0B平均pct
スナップショット2アクティブ0B平均pct
—————————
クラストラッカーの詳細については、ここをクリックしてください。
Guppy3
Guppy3(Heapyとも呼ばれます)は、Pythonプログラミング環境であり、ヒープ解析ツールセットです。 これは、次のサブパッケージを含むパッケージです。
- etc-これはGlueプロトコルモジュールを持つサポートモジュールです。
- gsl–Guppy仕様言語の実装を含むサブパッケージ。 これは、共通のソースから文書やテストを作成します。
- heapy–ヒープ解析ツールセットは、ヒープに関するオブジェクト情報を提供し、情報を表示します。
- sets–これにはビットセットとノードセットが含まれます。 Guppy3はGuppy-PEのフォークであり、Sverker NilssonによってPython2用に構築されました。注:このPythonメモリプロファイラを使用するには、Python3.5、3.6、3.7、または3.8が必要です。 このパッケージはCPythonでのみ動作します。 したがって、PyPyやその他のPythonコンパイラの実装はサポートされていません。 また、グラフィカルブラウザを使用するには、Tkinterが必要です。 さらに、リモートモニターを使用する場合は、スレッドを使用できる必要があります。 このPythonメモリプロファイラを利用する方法は次のとおりです。 重要なプロセスの前後にヒープのスナップショットを取ることができます。 次に、合計メモリを比較し、共通オブジェクト内で発生する可能性のあるメモリスパイクを特定します。
>>> from guppy import hpy
>>> h=hpy()
>>> h.heap()
Partition of a set of 34090 objects. Total size = 2366226 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class) 0 10279 30 666873 28 666873 28 str 1 4697 14 259576 11 926449 39 bytes 2 2413 7 251684 11 1178133 50 types.CodeType 3 6825 20 238084 10 1416217 60 tuple 4 448 1 174868 7 1591085 67 type 5 2208 6 150144 6 1741229 74 function 6 448 1 130964 6 1872193 79 dict of type 7 94 0 83532 4 1955725 83 dict of module 8 242 1 56524 2 2012249 85 dict (no owner) 9 1133 3 40788 2 2053037 87 types.WrapperDescriptorType <118 more rows. Type e.g. ‘_.more’ to view.>
Memory Profiler
Memory Profiler is a pure Python module that uses the psutil module. Pythonジョブプロセスのメモリ消費量を監視します。 また、アプリケーションのメモリ消費量の行ごとの分析を実行します。 行単位のメモリ使用モードは、line_profilerと同じように動作します。
行単位のメモリ使用モードは、line_profilerと同じように動作します。 @profile関数を使用してプロファイルしたい関数を装飾します。
- 特殊なスクリプトを使用してスクリプトを実行できます。 たとえば、Pythonインタプリタに特定の引数を使用します。
- 解放されていないメモリ内のラージオブジェクト
- 参照サイクル
- メモリリークを引き起こすC拡張で無効な参照カウント
- 突然のメモリスパイク
次の例では、my_funcという単純な関数を作成してみましょう。 この関数は、指定された範囲のリストを作成します。
@profile
def my_func():
a=
for i in range(1000):
a.append(i)
my_func()
This outputs:
Line # | Mem Usage | Increment | Line Contents |
1 | 13.859 MiB | 13.859 MiB | @profile |
2 | def my_func(): | ||
3 | 13.859 MiB | 0.000 MiB | a= |
4 | 13.859 MiB | 0.0.000MiB | 範囲(1000)内のiの場合: |
5 | 13.859MiB | 0.000MiB | a.append(i) |
最初の列は、プロファイルされたコードの行番号です。 Mem usageは、すべてのコード実行後のPythonインタプリタのメモリ使用量です。 3番目の列(増分)は、現在の行と最後の行のメモリの差を表します。 最後の列(行の内容)には、プロファイルされたコードが表示されます。
To see how this Python memory profiler works, let’s change the range value to 1000000 in the function above and execute it. Here is the output:
Line # | Mem usage | Increment | Line Contents |
1 | 13.844 MiB | 13.844 MiB | @profile |
2 | def my_func(): | ||
3 | 13.844 MiB | 0.000 MiB | a= |
4 | 33.387 MiB | 0.0.293MiB | a.append(i) |
4行目と5行目は、メモリ使用量の増加を示しており、このプロファイラーがメモリ消費量の行ごとの分析を実行していることを証
Fil
FilプロファイラはオープンソースのPythonメモリプロファイラです。 それはデータ処理および科学的な計算の適用のために適している。 現在、それはまだ開発段階にあり、LinuxとmacOSでのみ動作します。
ほとんどのデータ科学者とPython開発者は、Pythonデータパイプラインでメモリの問題に直面しています。 それはあまりにも多くのメモリを使用すると、正確にすべてのメモリが起こっている場所を特定することは困難です。
たとえば、次の2つのシナリオを挙げてみましょう。
サーバー
サーバーがノンストップで実行されているため、メモリリークがパフォーマンス障害の原因となることがよくあります。 ほとんどのサーバーが一度に少量のデータを処理するため、開発者は少量のメモリリークを無視します。 ただし、これらは最大数万の呼び出しを追加できます。 その結果、これは時間の経過とともに深刻な生産上の問題を作成する可能性があります。
データパイプライン
大きなデータチャンクを処理すると、メモリ使用量の急増がデータパイプラインに大きな脅威をもたらします。 たとえば、アプリケーションがかなりの時間1GBのRAMを使用していて、突然16GBのRAMが必要な場合。 突然のメモリスパイクの原因を特定するための大きな必要性があります。これがFilの主な目標であり、処理されるデータの量に関係なく、メモリ使用量の急増を診断することです。 これは、ピークメモリ使用量が正確にどこにあるのか、そのスパイクの原因となるコードを特定します。
メモリ使用量を測定する既存のPythonメモリプロファイラーがありますが、制限があります。 そのうちの一つは、膨大な量のデータバッチ処理を扱っています。 Pythonアプリケーションは、主にバッチ処理アプリケーションであり、常にデータを読み取り、処理し、結果を出力します。
その問題は、次のプロファイラーによって答えられます。
Blackfire
Pythonのような非常に動的な言語では、ほとんどの開発者は展開中にメモリの問題を経験します。 これは、メモリ使用量に何が起こるかについていくつかの混乱につながります。 開発者は最適化を実行する傾向がありますが、使用する適切なツールがありません。
Blackfireは独自のPythonメモリプロファイラです(おそらく最初のものです。 Pythonのメモリマネージャを使用して、C拡張を含むPythonによって割り当てられたすべてのメモリブロックを追跡します。 Blackfireはこの分野では初めてであり、次のようなメモリリークの問題を解決することを目指しています:
これらのユースケースでは、Blackfireは非常に限られたオーバーヘッドを持ち、関数呼び出しレベルでPythonアプリケーションのメモリ消費量を測定するため、エンドユーザーに影響を与えないことをユーザーに保証します。
Blackfire Pythonメモリプロファイラは、tracemallocのようなメモリ割り当てをトレースするためにPymem_Setallocator APIを使用しています。 現在、BlackfireはPythonバージョン3.5以降をサポートしています。 あなたはより多くを学ぶためにそのサイトを訪問することができます。
Retraceを使用したプロファイリング
Pythonを使用している場合は、すぐにメモリをオペレーティングシステムに解放しないことがあります。 したがって、別のプロセスで実行して、コードの実行後にメモリが解放されるようにします。 これは、”小さなテストケース”と呼ばれる便利なアプローチによって行われます。”このプロセスでは、問題のメモリリーケージコードのみを実行できます。
大量のデータを扱う場合は、ランダムにサンプリングされたデータのサブセットを使用します。 また、メモリを大量に消費するタスクを別々のプロセスで実行し、デバッガを使用してオブジェクトへの参照を追加します。 ただし、pdbなどのブレークポイントデバッガーを使用すると、デバッガーから手動で作成および参照されるオブジェクトはすべてメモリプロファイルに残 これは、オブジェクトが時間通りに解放されないため、誤ったメモリリークの感覚になります。 さらに、漏れやすいパッケージを調べることを検討してください。 潜在的にメモリリークが発生する可能性のあるPythonライブラリがあります。 これまでに、Pythonメモリプロファイラの動作とPythonの一般的なメモリの問題をすでに知っています。 しかし、一元化されたログ記録、エラー追跡、コードプロファイリングによるRetraceのようなツールは、Pythonの問題をより大規模に診断するのに役立ちます。 StackifyからのRetraceは、あらゆる種類のパフォーマンスの落とし穴に対処し、コードをうまく実行し続けるのに役立ちます。
今日あなたの14日間の無料リトレーストライアルを開始!