2012-03-24 25 views
22

Tôi muốn tìm hiểu số lượng RAM tối đa được cấp phát trong khi gọi hàm là (bằng Python). Có những câu hỏi khác về SO liên quan đến theo dõi việc sử dụng RAM:Theo dõi * tối đa * sử dụng bộ nhớ bằng chức năng Python

Which Python memory profiler is recommended?

How do I profile memory usage in Python?

nhưng những người dường như để cho phép bạn hơn để theo dõi việc sử dụng bộ nhớ vào thời điểm đó phương pháp heap() (trong trường hợp của cá bảy màu) được gọi là. Tuy nhiên, những gì tôi muốn theo dõi là một chức năng trong một thư viện bên ngoài mà tôi không thể sửa đổi, và phát triển để sử dụng rất nhiều RAM nhưng sau đó giải phóng nó sau khi thực hiện chức năng hoàn tất. Có cách nào để tìm ra tổng số RAM được sử dụng trong suốt cuộc gọi chức năng?

Trả lời

18

Câu hỏi này có vẻ khá thú vị và nó đã cho tôi một lý do để nhìn vào Guppy/Heapy, vì điều đó tôi cảm ơn bạn.

Tôi đã thử khoảng 2 giờ để có được Heapy để theo dõi một cuộc gọi/quy trình hàm mà không sửa đổi nguồn của nó bằng số không may mắn.

Tôi đã tìm cách hoàn thành nhiệm vụ của bạn bằng cách sử dụng thư viện Python được xây dựng resource. Lưu ý rằng tài liệu không chỉ ra giá trị trả về của giá trị RU_MAXRSS. Một người dùng SO khác là noted rằng nó nằm trong kB. Chạy Mac OSX 7.3 và xem tài nguyên hệ thống của tôi tăng lên trong mã thử nghiệm bên dưới, tôi tin rằng các giá trị trả lại nằm trong Byte, không phải kByte.

Chế độ xem 10000ft về cách tôi sử dụng thư viện resource để giám sát cuộc gọi thư viện là khởi chạy chức năng trong một chuỗi riêng biệt (theo dõi) và theo dõi tài nguyên hệ thống cho quy trình đó trong chuỗi chính. Dưới đây tôi có hai tệp mà bạn cần chạy để thử nghiệm.

Library Resource Monitor - 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)) 

stop Chủ đề - 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

Cảm ơn bạn đã trả lời chi tiết! – astrofrog

+0

@astrofrog Rất vui được giúp đỡ. Đó là điều mà tôi cũng có thể hưởng lợi trong tương lai. –

+0

Tôi đặt mã này như một ý chính để dễ dàng tải xuống các tệp: https://gist.github.com/b54fafd87634f017d50d – Tom

11

Có thể làm điều này với memory_profiler. Hàm memory_usage trả về một danh sách các giá trị, các giá trị này đại diện cho việc sử dụng bộ nhớ theo thời gian (theo mặc định trong các phần của .1 giây). Nếu bạn cần tối đa, chỉ cần lấy tối đa của danh sách đó. Ví dụ nhỏ:

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)) 

Trong trường hợp của tôi (memory_profiler 0,25) nếu bản in đầu ra sau đây:

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

giải pháp tuyệt vời cho các cửa sổ. https://pypi.python.org/pypi/memory_profiler nhưng cũng cần phải unstall psutil – mrgloom

+0

Nó chỉ stucks tại giao diện điều khiển khi tôi thử nó .... – Wajahat

+0

Bạn đang sử dụng hệ thống nào @Wajahat? –

5

Điều này dường như làm việc trong môi trường Windows. Không biết về các hệ điều hành khác.

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

Tôi tin rằng điều này sẽ là 'memory_info_ex.peak_set' – gbronner

+0

Xem tài liệu. https://pythonhosted.org/psutil/#psutil.Process.memory_info Nên là 'process.memory_info(). rss' để có dạng chéo –

-2

Bạn cũng đang phải vật lộn với tác vụ này. Sau khi thử nghiệm với psutil và các phương thức từ Adam, tôi đã viết một hàm (các khoản tín dụng cho Adam Lewis) để đo bộ nhớ được sử dụng bởi một hàm cụ thể. Mọi người có thể thấy dễ lấy và sử dụng hơn.

1) measure_memory_usage

2) test measure_memory_usage

tôi thấy rằng tài liệu về luồng và lớp cha trọng là thực sự hữu ích trong việc tìm hiểu những gì Adam đang làm trong các kịch bản của mình. Rất tiếc, tôi không thể đăng các liên kết do giới hạn tối đa "2 liên kết" của tôi.

0

Bạn có thể sử dụng tài nguyên thư viện python để sử dụng bộ nhớ.

nhập khẩu tài nguyên resource.getrusage (resource.RUSAGE_SELF) .ru_maxrss

Nó sẽ cho sử dụng bộ nhớ trong kilobyte, để chuyển đổi trong MB chia cho 1000.

Các vấn đề liên quan