関数の呼び出し中に割り当てられるRAMの最大量は(Pythonの場合)であるかを調べたいと思います。SOに関連する他の質問があります追跡RAM使用:
Pythonでメモリ使用量をプロファイルするにはどうすればよいですか?
しかし、これらはheap()
メソッド(グッピーの場合)が呼び出されたときのメモリ使用量をさらに追跡できるようです。ただし、追跡したいのは、変更できない外部ライブラリの関数であり、多くのRAMを使用するようになりますが、関数の実行が完了すると解放されます関数呼び出し中に使用されたRAMの合計量が何であったかを知る方法はありますか?
この質問はかなりおもしろそうで、Guppy/Heapyを調べる理由になりました。ありがとうございます。
Heapyにソースをzero運で変更せずに関数呼び出し/プロセスを監視させるために、約2時間試してみました。
組み込みのPythonライブラリ resource
を使用してタスクを実行する方法を見つけました。ドキュメントにはRU_MAXRSS
値が返されます。別のSO user noted それがkBであったこと。MacOSX 7.3を実行し、以下のテストコード中にシステムリソースが上昇するのを観察すると、戻り値はBytesで、kBytesではありません。
resource
ライブラリを使用してライブラリの呼び出しを監視する方法に関する10000ftのビューは、別の(監視可能な)スレッドで関数を起動し、メインスレッドでそのプロセスのシステムリソースを追跡することでした。以下に、テストするために実行する必要がある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
memory_profiler でこれを行うことができます。関数 memory_usage
は値のリストを返します。これらは時間の経過に伴うメモリ使用量を表します(デフォルトでは.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))
私の場合(memory_profiler 0.25)ifは次の出力を出力します:
Memory usage (in chunks of .1 seconds): [45.65625, 45.734375, 46.41015625, 53.734375]
Maximum memory usage: 53.734375
これは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
pythonライブラリリソースを使用して、メモリ使用量を取得できます。
import resource
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
1000で除算したMBで変換するために、キロバイト単位のメモリ使用量を提供します。
@Vader Bの回答の改善(そのままでは機能しませんでした):
$ /usr/bin/time --verbose ./myscript.py
Command being timed: "./myscript.py"
User time (seconds): 16.78
System time (seconds): 2.74
Percent of CPU this job got: 117%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:16.58
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 616092 # WE NEED THIS!!!
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 432750
Voluntary context switches: 1075
Involuntary context switches: 118503
Swaps: 0
File system inputs: 0
File system outputs: 800
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
標準のUnixユーティリティtime
は、プロセスの最大メモリ使用量と、プログラムの他の有用な統計を追跡します。
出力例(maxresident
はキロバイト単位の最大メモリ使用量です。):
> time python ./scalabilty_test.py
45.31user 1.86system 0:47.23elapsed 99%CPU (0avgtext+0avgdata 369824maxresident)k
0inputs+100208outputs (0major+99494minor)pagefaults 0swaps