2012-03-24 45 views
22

関数の呼び出し中に(Pythonで)割り当てられたRAMの最大量を調べたいと思います。Python関数による最大*メモリ使用量の追跡

Which Python memory profiler is recommended?

How do I profile memory usage in Python?

しかしそれらは、あなたがより多くの(グッピーの場合)時heap()方法をメモリ使用量を追跡することを可能にするように見える:そこRAMの使用状況を追跡するSO関連のその他の質問がありますが呼び出されます。しかし、私が追跡したいのは、外部ライブラリの関数であり、変更できず、多くのRAMを使用するようになりましたが、関数の実行が完了すると解放されます。関数呼び出し中に使用されたRAMの総容量を調べる方法はありますか?

答えて

18

この質問はかなり面白そうだったし、ガッピー/ヒーフィーを調べる理由がわかりました。

私は約2時間、Heapyに関数呼び出し/プロセスの監視を行わせ、そのソースをゼロで修正することを試みました。

私は、組み込みのPythonライブラリresourceを使用してタスクを達成する方法を見つけました。ドキュメントにはRU_MAXRSSの値が何を返すのかが示されていないことに注意してください。別のSOユーザnotedはkBであった。 Mac OSX 7.3を実行し、私のシステムリソースが下のテストコードの間に登るのを見て、返された値はバイト、、kBytesではないと信じています。

resourceライブラリを使用してライブラリ呼び出しを監視する方法については、別の(モニター可能な)スレッドで関数を起動し、メインスレッドのそのプロセスのシステムリソースを追跡することでした。私はそれをテストするために実行する必要がある2つのファイルがあります。

ライブラリリソースモニタからwhatever_you_want.py

import resource 
import time 

from stoppable_thread import StoppableThread 


class MyLibrarySniffingClass(StoppableThread): 
    def __init__(self, target_lib_call, arg1, arg2): 
     super(MyLibrarySniffingClass, self).__init__() 
     self.target_function = target_lib_call 
     self.arg1 = arg1 
     self.arg2 = arg2 
     self.results = None 

    def startup(self): 
     # Overload the startup function 
     print "Calling the Target Library Function..." 

    def cleanup(self): 
     # Overload the cleanup function 
     print "Library Call Complete" 

    def mainloop(self): 
     # Start the library Call 
     self.results = self.target_function(self.arg1, self.arg2) 

     # Kill the thread when complete 
     self.stop() 

def SomeLongRunningLibraryCall(arg1, arg2): 
    max_dict_entries = 2500 
    delay_per_entry = .005 

    some_large_dictionary = {} 
    dict_entry_count = 0 

    while(1): 
     time.sleep(delay_per_entry) 
     dict_entry_count += 1 
     some_large_dictionary[dict_entry_count]=range(10000) 

     if len(some_large_dictionary) > max_dict_entries: 
      break 

    print arg1 + " " + arg2 
    return "Good Bye World" 

if __name__ == "__main__": 
    # Lib Testing Code 
    mythread = MyLibrarySniffingClass(SomeLongRunningLibraryCall, "Hello", "World") 
    mythread.start() 

    start_mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 
    delta_mem = 0 
    max_memory = 0 
    memory_usage_refresh = .005 # Seconds 

    while(1): 
     time.sleep(memory_usage_refresh) 
     delta_mem = (resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) - start_mem 
     if delta_mem > max_memory: 
      max_memory = delta_mem 

     # Uncomment this line to see the memory usuage during run-time 
     # print "Memory Usage During Call: %d MB" % (delta_mem/1000000.0) 

     # Check to see if the library call is complete 
     if mythread.isShutdown(): 
      print mythread.results 
      break; 

    print "\nMAX Memory Usage in MB: " + str(round(max_memory/1000.0, 3)) 

停止可能スレッド - stoppable_thread.py

import threading 
import time 

class StoppableThread(threading.Thread): 
    def __init__(self): 
     super(StoppableThread, self).__init__() 
     self.daemon = True 
     self.__monitor = threading.Event() 
     self.__monitor.set() 
     self.__has_shutdown = False 

    def run(self): 
     '''Overloads the threading.Thread.run''' 
     # Call the User's Startup functions 
     self.startup() 

     # Loop until the thread is stopped 
     while self.isRunning(): 
      self.mainloop() 

     # Clean up 
     self.cleanup() 

     # Flag to the outside world that the thread has exited 
     # AND that the cleanup is complete 
     self.__has_shutdown = True 

    def stop(self): 
     self.__monitor.clear() 

    def isRunning(self): 
     return self.__monitor.isSet() 

    def isShutdown(self): 
     return self.__has_shutdown 


    ############################### 
    ### User Defined Functions #### 
    ############################### 

    def mainloop(self): 
     ''' 
     Expected to be overwritten in a subclass!! 
     Note that Stoppable while(1) is handled in the built in "run". 
     ''' 
     pass 

    def startup(self): 
     '''Expected to be overwritten in a subclass!!''' 
     pass 

    def cleanup(self): 
     '''Expected to be overwritten in a subclass!!''' 
     pass 
+0

おかげでMB除算に変換するには、キロバイト単位でメモリ使用量を与える

を.ru_maxrss! – astrofrog

+0

@astrofrog喜んで助けてください。これは私が将来も恩恵を受けることができるものです。 –

+0

ファイルをダウンロードするのは簡単ですので、このコードを参考にしてください:https://gist.github.com/b54fafd87634f017d50d – Tom

11

memory_profilerでこれを行うことが可能です。関数memory_usageは値のリストを返します。これらは時間の経過と共にメモリ使用量を表します(デフォルトでは0.1秒のチャンクよりも大きい)。最大値が必要な場合は、そのリストの最大値を取るだけです。リトル例:私の場合は

from memory_profiler import memory_usage 
from time import sleep 

def f(): 
    # a function that with growing 
    # memory consumption 
    a = [0] * 1000 
    sleep(.1) 
    b = a * 100 
    sleep(.1) 
    c = b * 100 
    return a 

mem_usage = memory_usage(f) 
print('Memory usage (in chunks of .1 seconds): %s' % mem_usage) 
print('Maximum memory usage: %s' % max(mem_usage)) 

(0.25 memory_profiler)の場合は、次のような出力を出力します。

Memory usage (in chunks of .1 seconds): [45.65625, 45.734375, 46.41015625, 53.734375] 
Maximum memory usage: 53.734375 
+1

窓用の素晴らしいソリューション。 https://pypi.python.org/pypi/memory_profilerでもpsutilをアンストールする必要があります – mrgloom

+0

試してみるとコンソールにちょうど立ち往生します.... – Wajahat

+0

@Wajahatを使っているシステムは何ですか? –

5

これは、Windowsで動作するように表示されます。他のオペレーティングシステムについては知らない

In [50]: import os 

In [51]: import psutil 

In [52]: process = psutil.Process(os.getpid()) 

In [53]: process.get_ext_memory_info().peak_wset 
Out[53]: 41934848 
+1

これは 'memory_info_ex.peak_set'となるはずです。 – gbronner

+0

docsをご覧ください。 https://pythonhosted.org/psutil/#psutil.Process.memory_infoクロスメッシュフォームである 'process.memory_info()。rss'でなければなりません。 –

-2

この作業にも苦労しています。 psutilとAdamのメソッドを試した後、私は特定の関数が使用するメモリを測定する関数(Adam Lewisにクレジット)を書きました。人々はそれをつかむと使いやすくなるかもしれません。

1)measure_memory_usage

2)test measure_memory_usage

私はスーパークラスをスレッドとオーバーライドに関する資料は、アダムが彼のスクリプトの中でやっていることを理解するのに本当に便利であることを発見。申し訳ありませんが、私は "2リンク"の最大限の制限のためにリンクを投稿できません。

0

pythonライブラリリソースを使用してメモリ使用量を取得できます。

輸入資源 resource.getrusage(resource.RUSAGE_SELFは)それは、詳細な回答のために1000

関連する問題