2009-02-16 21 views
126

Gần đây tôi đã trở nên quan tâm đến các thuật toán và đã bắt đầu khám phá chúng bằng cách viết một triển khai ngây thơ và sau đó tối ưu hóa nó theo nhiều cách khác nhau.Tôi làm cách nào để sử dụng bộ nhớ trong Python?

Tôi đã quen với mô-đun Python chuẩn cho thời gian chạy hồ sơ (đối với hầu hết mọi thứ tôi đã tìm thấy hàm ma thuật thời gian trong IPython là đủ), nhưng tôi cũng quan tâm đến việc sử dụng bộ nhớ để tôi có thể khám phá sự cân bằng cũng như (ví dụ: chi phí lưu bộ nhớ đệm một bảng các giá trị được tính toán trước đó so với việc tính toán lại chúng khi cần). Có một mô-đun sẽ hồ sơ việc sử dụng bộ nhớ của một chức năng nhất định cho tôi?

Trả lời

87

một này đã được trả lời đã ở đây: Python memory profiler

Về cơ bản bạn làm điều gì đó như thế (trích dẫn từ Guppy-PE):

>>> from guppy import hpy; h=hpy() 
>>> h.heap() 
Partition of a set of 48477 objects. Total size = 3265516 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 25773 53 1612820 49 1612820 49 str 
    1 11699 24 483960 15 2096780 64 tuple 
    2 174 0 241584 7 2338364 72 dict of module 
    3 3478 7 222592 7 2560956 78 types.CodeType 
    4 3296 7 184576 6 2745532 84 function 
    5 401 1 175112 5 2920644 89 dict of class 
    6 108 0 81888 3 3002532 92 dict (no owner) 
    7 114 0 79632 2 3082164 94 dict of type 
    8 117 0 51336 2 3133500 96 type 
    9 667 1 24012 1 3157512 97 __builtin__.wrapper_descriptor 
<76 more rows. Type e.g. '_.more' to view.> 
>>> h.iso(1,[],{}) 
Partition of a set of 3 objects. Total size = 176 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0  1 33  136 77  136 77 dict (no owner) 
    1  1 33  28 16  164 93 list 
    2  1 33  12 7  176 100 int 
>>> x=[] 
>>> h.iso(x).sp 
0: h.Root.i0_modules['__main__'].__dict__['x'] 
>>> 
+3

tài liệu cá bảy màu chính thức là một chút minimial; để xem các tài nguyên khác, hãy xem [ví dụ này] (http://smira.ru/wp-content/uploads/2011/08/heapy.html) và [bài viết heapy] (http://guppy-pe.sourceforge.net/ heapy-thesis.pdf). – tutuDajuju

16

Đối với một cách tiếp cận thử thực sự đơn giản:

import resource 
def using(point=""): 
    usage=resource.getrusage(resource.RUSAGE_SELF) 
    return '''%s: usertime=%s systime=%s mem=%s mb 
      '''%(point,usage[0],usage[1], 
       (usage[2]*resource.getpagesize())/1000000.0) 

Chỉ cần chèn using("Label") nơi bạn muốn xem điều gì đang xảy ra.

+5

"sử dụng bộ nhớ của một hàm nhất định" để cách tiếp cận của bạn không giúp ích gì. – Glaslos

+0

Bằng cách nhìn vào 'usage [2]', bạn đang nhìn vào 'ru_maxrss', mà chỉ là phần của quá trình đó là * resident *. Điều này sẽ không giúp ích gì nhiều nếu quá trình này đã được đổi sang đĩa, thậm chí một phần. – Louis

+3

'tài nguyên' là một mô-đun cụ thể của Unix không hoạt động trong Windows. – Martin

13

tôi bạn chỉ muốn xem xét việc sử dụng bộ nhớ của một đối tượng, (answer to other question)

Có một module gọi là Pympler chứa các module asizeof .

Sử dụng như sau:

from pympler import asizeof 
asizeof.asizeof(my_object) 

Không giống như sys.getsizeof, nó làm việc cho các đối tượng tự tạo của bạn.

>>> asizeof.asizeof(tuple('bcd')) 
200 
>>> asizeof.asizeof({'foo': 'bar', 'baz': 'bar'}) 
400 
>>> asizeof.asizeof({}) 
280 
>>> asizeof.asizeof({'foo':'bar'}) 
360 
>>> asizeof.asizeof('foo') 
40 
>>> asizeof.asizeof(Bar()) 
352 
>>> asizeof.asizeof(Bar().__dict__) 
280 
>>> help(asizeof.asizeof) 
Help on function asizeof in module pympler.asizeof: 

asizeof(*objs, **opts) 
    Return the combined size in bytes of all objects passed as positional arguments. 
+0

Đây có phải là asizeof liên quan đến RSS không? – mousecoder

+0

Kích thước này có tính bằng byte không? – mousecoder

+1

@mousecoder: có, tính bằng byte. Xem sửa đổi –

7

Python 3.4 bao gồm một module mới: tracemalloc. Nó cung cấp số liệu thống kê chi tiết về mã nào được cấp phát bộ nhớ nhiều nhất. Dưới đây là một ví dụ hiển thị ba dòng đầu phân bổ bộ nhớ.

from collections import Counter 
import linecache 
import os 
import tracemalloc 

def display_top(snapshot, key_type='lineno', limit=3): 
    snapshot = snapshot.filter_traces((
     tracemalloc.Filter(False, "<frozen importlib._bootstrap>"), 
     tracemalloc.Filter(False, "<unknown>"), 
    )) 
    top_stats = snapshot.statistics(key_type) 

    print("Top %s lines" % limit) 
    for index, stat in enumerate(top_stats[:limit], 1): 
     frame = stat.traceback[0] 
     # replace "/path/to/module/file.py" with "module/file.py" 
     filename = os.sep.join(frame.filename.split(os.sep)[-2:]) 
     print("#%s: %s:%s: %.1f KiB" 
       % (index, filename, frame.lineno, stat.size/1024)) 
     line = linecache.getline(frame.filename, frame.lineno).strip() 
     if line: 
      print(' %s' % line) 

    other = top_stats[limit:] 
    if other: 
     size = sum(stat.size for stat in other) 
     print("%s other: %.1f KiB" % (len(other), size/1024)) 
    total = sum(stat.size for stat in top_stats) 
    print("Total allocated size: %.1f KiB" % (total/1024)) 


tracemalloc.start() 

counts = Counter() 
fname = '/usr/share/dict/american-english' 
with open(fname) as words: 
    words = list(words) 
    for word in words: 
     prefix = word[:3] 
     counts[prefix] += 1 
print('Top prefixes:', counts.most_common(3)) 

snapshot = tracemalloc.take_snapshot() 
display_top(snapshot) 

Và đây là kết quả:

Top prefixes: [('con', 1220), ('dis', 1002), ('pro', 809)] 
Top 3 lines 
#1: scratches/memory_test.py:37: 6527.1 KiB 
    words = list(words) 
#2: scratches/memory_test.py:39: 247.7 KiB 
    prefix = word[:3] 
#3: scratches/memory_test.py:40: 193.0 KiB 
    counts[prefix] += 1 
4 other: 4.3 KiB 
Total allocated size: 6972.1 KiB 
2

có thể nó giúp đỡ:
< see additional>

pip install gprof2dot 
sudo apt-get install graphviz 

gprof2dot -f pstats profile_for_func1_001 | dot -Tpng -o profile.png 

def profileit(name): 
    """ 
    @profileit("profile_for_func1_001") 
    """ 
    def inner(func): 
     def wrapper(*args, **kwargs): 
      prof = cProfile.Profile() 
      retval = prof.runcall(func, *args, **kwargs) 
      # Note use of name from outer scope 
      prof.dump_stats(name) 
      return retval 
     return wrapper 
    return inner 

@profileit("profile_for_func1_001") 
def func1(...) 
Các vấn đề liên quan