পাইথন 3.4 একটি নতুন মডিউল রয়েছে: tracemalloc
। এটি কোন কোড সর্বাধিক মেমরি বরাদ্দ করছে সে সম্পর্কে বিশদ পরিসংখ্যান সরবরাহ করে। এখানে একটি উদাহরণ যা মেমরির বরাদ্দ শীর্ষ তিনটি লাইন প্রদর্শন করে।
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)
এবং ফলাফল এখানে:
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
মেমরি ফুটো কখন হয় না?
সেই উদাহরণটি দুর্দান্ত যখন মেমরিটি এখনও গণনার শেষে রাখা হয় তবে কখনও কখনও আপনার কাছে এমন কোড থাকে যা প্রচুর মেমরি বরাদ্দ করে এবং তারপরে এটি সমস্ত প্রকাশ করে। এটি প্রযুক্তিগতভাবে কোনও মেমরি ফাঁস নয়, তবে এটি আপনার মনে করা উচিত তার চেয়ে বেশি মেমরি ব্যবহার করছে। মেমরির ব্যবহার প্রকাশিত হয়ে গেলে আপনি কীভাবে এটি ট্র্যাক করতে পারেন? এটি যদি আপনার কোড হয় তবে চলমান অবস্থায় স্ন্যাপশট নিতে আপনি সম্ভবত কিছু ডিবাগিং কোড যুক্ত করতে পারেন। যদি তা না হয় তবে মূল থ্রেড চলাকালীন আপনি মেমরির ব্যবহার নিরীক্ষণ করতে একটি পটভূমি থ্রেড শুরু করতে পারেন।
এখানে আগের উদাহরণটি এখানে কোডটি সমস্ত count_prefixes()
ফাংশনে সরানো হয়েছে । যখন ফাংশনটি ফিরে আসে, সমস্ত মেমরি প্রকাশিত হয়। sleep()
দীর্ঘমেয়াদী গণনা অনুকরণের জন্য আমি কয়েকটি কলও যুক্ত করেছি ।
from collections import Counter
import linecache
import os
import tracemalloc
from time import sleep
def count_prefixes():
sleep(2) # Start up time.
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
sleep(0.0001)
most_common = counts.most_common(3)
sleep(3) # Shut down time.
return most_common
def main():
tracemalloc.start()
most_common = count_prefixes()
print('Top prefixes:', most_common)
snapshot = tracemalloc.take_snapshot()
display_top(snapshot)
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))
main()
আমি যখন এই সংস্করণটি চালনা করি তখন মেমরির ব্যবহার 6MB থেকে 4KB তে চলে যায় কারণ ফাংশনটি সমস্ত স্মৃতি প্রকাশের পরে এটি শেষ করে।
Top prefixes: [('con', 1220), ('dis', 1002), ('pro', 809)]
Top 3 lines
#1: collections/__init__.py:537: 0.7 KiB
self.update(*args, **kwds)
#2: collections/__init__.py:555: 0.6 KiB
return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
#3: python3.6/heapq.py:569: 0.5 KiB
result = [(key(elem), i, elem) for i, elem in zip(range(0, -n, -1), it)]
10 other: 2.2 KiB
Total allocated size: 4.0 KiB
এখন এখানে অন্য উত্তরের দ্বারা অনুপ্রাণিত একটি সংস্করণ যা মেমরির ব্যবহার নিরীক্ষণ করতে দ্বিতীয় থ্রেড শুরু করে।
from collections import Counter
import linecache
import os
import tracemalloc
from datetime import datetime
from queue import Queue, Empty
from resource import getrusage, RUSAGE_SELF
from threading import Thread
from time import sleep
def memory_monitor(command_queue: Queue, poll_interval=1):
tracemalloc.start()
old_max = 0
snapshot = None
while True:
try:
command_queue.get(timeout=poll_interval)
if snapshot is not None:
print(datetime.now())
display_top(snapshot)
return
except Empty:
max_rss = getrusage(RUSAGE_SELF).ru_maxrss
if max_rss > old_max:
old_max = max_rss
snapshot = tracemalloc.take_snapshot()
print(datetime.now(), 'max RSS', max_rss)
def count_prefixes():
sleep(2) # Start up time.
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
sleep(0.0001)
most_common = counts.most_common(3)
sleep(3) # Shut down time.
return most_common
def main():
queue = Queue()
poll_interval = 0.1
monitor_thread = Thread(target=memory_monitor, args=(queue, poll_interval))
monitor_thread.start()
try:
most_common = count_prefixes()
print('Top prefixes:', most_common)
finally:
queue.put('stop')
monitor_thread.join()
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))
main()
resource
মডিউল আপনি বর্তমান মেমোরি ব্যবহার চেক করুন এবং শিখর মেমোরি ব্যবহার থেকে স্ন্যাপশট সংরক্ষণ করতে দেয়। সারিটি মূল থ্রেডটি মেমরি মনিটরের থ্রেডকে কখন তার রিপোর্টটি প্রিন্ট করতে হবে এবং বন্ধ করতে দেয় তা বলতে দেয়। এটি চলতে থাকলে, list()
কলটি ব্যবহার করে মেমরিটি দেখায় :
2018-05-29 10:34:34.441334 max RSS 10188
2018-05-29 10:34:36.475707 max RSS 23588
2018-05-29 10:34:36.616524 max RSS 38104
2018-05-29 10:34:36.772978 max RSS 45924
2018-05-29 10:34:36.929688 max RSS 46824
2018-05-29 10:34:37.087554 max RSS 46852
Top prefixes: [('con', 1220), ('dis', 1002), ('pro', 809)]
2018-05-29 10:34:56.281262
Top 3 lines
#1: scratches/scratch.py:36: 6527.0 KiB
words = list(words)
#2: scratches/scratch.py:38: 16.4 KiB
prefix = word[:3]
#3: scratches/scratch.py:39: 10.1 KiB
counts[prefix] += 1
19 other: 10.8 KiB
Total allocated size: 6564.3 KiB
আপনি যদি লিনাক্সে থাকেন /proc/self/statm
তবে resource
মডিউলটির চেয়ে আপনি আরও দরকারী ।