পাইথন প্রক্রিয়া দ্বারা ব্যবহৃত মোট স্মৃতি?


265

পাইথন প্রোগ্রামের জন্য বর্তমানে এটি কতটা স্মৃতি ব্যবহার করছে তা নির্ধারণের কোনও উপায় আছে? আমি একটি একক অবজেক্টের জন্য মেমরির ব্যবহার সম্পর্কে আলোচনা দেখেছি, তবে আমার যা দরকার তা হল প্রক্রিয়াটির মোট স্মৃতিশক্তি ব্যবহার, যাতে ক্যাশেড ডেটা ফেলে দেওয়া শুরু করা কখন প্রয়োজন তা আমি নির্ধারণ করতে পারি।

উত্তর:


301

এখানে একটি দরকারী সমাধান যা লিনাক্স, উইন্ডোজ 7 ইত্যাদি সহ বিভিন্ন অপারেটিং সিস্টেমের জন্য কাজ করে .:

import os
import psutil
process = psutil.Process(os.getpid())
print(process.memory_info().rss)  # in bytes 

আমার বর্তমান পাইথন ২.7 এ সিউসিল 5.6.3 দিয়ে ইনস্টল করুন, শেষ লাইনটি হওয়া উচিত

print(process.memory_info()[0])

পরিবর্তে (এপিআইতে একটি পরিবর্তন ছিল)।

দ্রষ্টব্য: pip install psutilএটি ইনস্টল না হয়ে থাকলে করুন।


3
psutilক্রস প্ল্যাটফর্ম এবং psকমান্ড লাইন সরঞ্জামের মতো একই মানগুলি ফিরিয়ে আনতে পারে : পাইথোনহস্টেড.আর.পি.সুটিল /#psutil.Process.memory_info
amos

1
"( psutil) বর্তমানে সমর্থন লিনাক্স, উইন্ডোস, ওএসএক্স, ফ্রিবিএসডি এবং সূর্যের সোলারিস, উভয় 32 বিট এবং 64-বিট আর্কিটেকচারের, 2.6 থেকে 3.4 থেকে পাইথন সংস্করণের সাথে" থেকে নথিপত্র
সিসিলিয়া

2
প্রক্রিয়া এক্সপ্লোরারটির সাথে এই সংখ্যাটি কেন মেলে না? সোসুটিলের সংখ্যাটি সর্বদা প্রায় 10% দ্বারা বড় বলে মনে হয়।
শব্দগুলি

39
নোট করুন যে psutil স্ট্যান্ডার্ড লাইব্রেরিতে নেই
গ্রিসাইটিস

12
এর সাম্প্রতিক সংস্করণের জন্য psutil, psutil.Process()সমান psutil.Process(os.getpid())। এটি টাইপ করার জন্য আপনার মনে রাখা দরকার less
rnorris

208

ইউনিক্স ভিত্তিক সিস্টেমগুলির জন্য (লিনাক্স, ম্যাক ওএস এক্স, সোলারিস), আপনি getrusage()স্ট্যান্ডার্ড লাইব্রেরি মডিউল থেকে ফাংশনটি ব্যবহার করতে পারেন resource। ফলস্বরূপ অবজেক্টটির বৈশিষ্ট্য রয়েছে ru_maxrss, যা কলিং প্রক্রিয়াটির জন্য শীর্ষ মেমরির ব্যবহার করে:

>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
2656  # peak memory usage (kilobytes on Linux, bytes on OS X)

পাইথন ডক্স ইউনিট নোট না। man getrusage.2মানটির জন্য ইউনিটটি পরীক্ষা করতে আপনার নির্দিষ্ট সিস্টেমের পৃষ্ঠাটি দেখুন। উবুন্টু 18.04-এ, ইউনিটটি কিলোবাইট হিসাবে চিহ্নিত করা হয়। ম্যাক ওএস এক্সে এটি বাইটস।

শিশু প্রক্রিয়াগুলির জন্য এবং (কিছু সিস্টেমে) ব্যবহারের জন্য এই getrusage()ফাংশনটি দেওয়া resource.RUSAGE_CHILDRENযেতে পারেresource.RUSAGE_BOTH মোট (স্ব ও শিশু) প্রক্রিয়া ব্যবহারের জন্য।

আপনি শুধুমাত্র লিনাক্স যত্নশীল থাকে, তাহলে আপনি অন্যথায় পড়তে পারেন /proc/self/statusবা /proc/self/statmফাইলটি এই প্রশ্ন ও এর জন্য অন্যান্য উত্তর বর্ণনা অনুযায়ী এই খুব অন্যতম।


2
ঠিক আছে, করবে। আমি নিশ্চিত ছিলাম না যে এসওর মধ্যে প্রশ্নগুলি মার্জ করার প্রক্রিয়া ছিল বা কী। সদৃশ পোস্টটি আংশিকভাবে লোকদের উভয় প্রশ্নের জন্য একটি আদর্শ গ্রন্থাগার সমাধান ছিল তা দেখানোর জন্য ছিল ... এবং আংশিকভাবে এই প্রতিবেদনের জন্য। ;) আমার এই উত্তরটি মুছে ফেলা উচিত?
নাথান ক্রেইক

6
ম্যাক ওএস স্পষ্টতই আরএসএসকে বাইটে ফিরিয়ে দেয়, লিনাক্স এটিকে কিলোবাইটে ফেরত দেয়।
নীল

13
ইউনিটগুলি কিলোবাইটে নেই। এটি প্ল্যাটফর্ম নির্ভর, সুতরাং এটির জন্য আপনাকে রিসোর্স.টেটপেজাইজ () ব্যবহার করতে হবে। প্রদত্ত পাইথন ডকস ( docs.python.org/2/library/resource.html#resource-usage ) এ সম্পর্কে আসলে খুব স্পষ্ট। এটি আমার বাক্সে 4096।
বেন লিন

5
@ বেনলিন সেই পাইথন ডকস স্পষ্টতই ভুল, বা ম্যাক সংস্করণে একটি বাগ রয়েছে g গেট্রাসেজ দ্বারা ব্যবহৃত ইউনিট এবং গেটপেজাইজ দ্বারা ফেরত মান অবশ্যই পৃথক definitely
অ্যান্ড্রু

6
প্রশ্নটি বর্তমান ব্যবহারের জন্য জিজ্ঞাসা করেছিল । মনে রাখবেন এটি সর্বোচ্চ ব্যবহার। (এখনও একটি দরকারী উত্তর, ভুলরূপে এটি অনুলিপি করে এমন লোকদের সতর্ক করে))
লু

65

উইন্ডোজে, আপনি ডাব্লুএমআই ( হোম পেজ , পনিরশপ ) ব্যবহার করতে পারেন :


def memory():
    import os
    from wmi import WMI
    w = WMI('.')
    result = w.query("SELECT WorkingSet FROM Win32_PerfRawData_PerfProc_Process WHERE IDProcess=%d" % os.getpid())
    return int(result[0].WorkingSet)

লিনাক্সে (পাইথন কুকবুক থেকে http://code.activestate.com/recips/286222/ :

import os
_proc_status = '/proc/%d/status' % os.getpid()

_scale = {'kB': 1024.0, 'mB': 1024.0*1024.0,
          'KB': 1024.0, 'MB': 1024.0*1024.0}

def _VmB(VmKey):
    '''Private.
    '''
    global _proc_status, _scale
     # get pseudo file  /proc/<pid>/status
    try:
        t = open(_proc_status)
        v = t.read()
        t.close()
    except:
        return 0.0  # non-Linux?
     # get VmKey line e.g. 'VmRSS:  9999  kB\n ...'
    i = v.index(VmKey)
    v = v[i:].split(None, 3)  # whitespace
    if len(v) < 3:
        return 0.0  # invalid format?
     # convert Vm value to bytes
    return float(v[1]) * _scale[v[2]]


def memory(since=0.0):
    '''Return memory usage in bytes.
    '''
    return _VmB('VmSize:') - since


def resident(since=0.0):
    '''Return resident memory usage in bytes.
    '''
    return _VmB('VmRSS:') - since


def stacksize(since=0.0):
    '''Return stack size in bytes.
    '''
    return _VmB('VmStk:') - since

14
উইন্ডোজ কোডটি আমার পক্ষে কাজ করে না। এই পরিবর্তনটি করে:return int(result[0].WorkingSet)
জন ফুহি

1
জন ফোহির মন্তব্য সংশোধন করার পরেও এই উইন্ডোজ কোডটি উইন্ডোজ 7 x64 এ আমার জন্য কাজ করে না।
বসজ

আমার এই ত্রুটিটি রয়েছে: স্ব-আপত্তির জন্য [ ডাব্লুএমআই_বজেক্ট (,জেক্ট, উদাহরণ_ও, ক্ষেত্রগুলি) ফিরে দিন _ পরবর্তী রিটার্নে _get_good_object_ (স্ব ._জিটার। পূর্ববর্তী (), ফলাফল CLSID = self.resultCLSID) পাইউইনটাইপস.কম_অরর: (-2147217385, 'OLE ত্রুটি 0x80041017', কিছুই নেই, কেউ নয়) যদি কেউ আমাকে সাহায্য করতে পারে? আমি 8 x64 কিন্তু x32-তে পাইথন জিতেছি
রাদু ভ্লাদ

দ্রষ্টব্য: আমি ডাব্লুএমআই মডিউলটির (সর্বশেষ) উত্স পরিদর্শন করার পরে জন ফুহির পরামর্শ অনুসরণ করে উইন্ডোজ উদাহরণটি আপডেট করেছি। আরও দেখুন (1) , (2)
jedwards

33

ইউনিক্সে, আপনি psএটি পর্যবেক্ষণ করতে সরঞ্জামটি ব্যবহার করতে পারেন :

$ ps u -p 1347 | awk '{sum=sum+$6}; END {print sum/1024}'

যেখানে ১৩4747 হ'ল কিছু প্রক্রিয়া আইডি। এছাড়াও, ফলাফল এমবি হয়।


7

লিনাক্সে পাইথন 2, পাইথন 3 এবং পাইপির জন্য বর্তমান প্রক্রিয়াটির বর্তমান মেমরির ব্যবহার, কোনও আমদানি ছাড়াই:

def getCurrentMemoryUsage():
    ''' Memory usage in kB '''

    with open('/proc/self/status') as f:
        memusage = f.read().split('VmRSS:')[1].split('\n')[0][:-3]

    return int(memusage.strip())

লিনাক্স ৪.৪ এবং ৪.৯ এ পরীক্ষিত, তবে লিনাক্সের প্রাথমিক সংস্করণটিও কাজ করা উচিত।

তাকিয়ে man procএবং উপর তথ্য অনুসন্ধানের জন্য /proc/$PID/statusফাইল, এটা ( "VmPTE" জন্য লিনাক্স 2.6.10 মত) কিছু ক্ষেত্রের জন্য ন্যূনতম সংস্করণ উল্লেখ কিন্তু "VmRSS" ক্ষেত্র (যা আমি এখানে ব্যবহার করুন) যেমন কোনো উল্লেখ নেই। অতএব আমি ধরে নিচ্ছি এটি প্রাথমিক সংস্করণ থেকেই রয়েছে।


5

আমি এটি পছন্দ করি , @ বায়ারের জন্য আপনাকে ধন্যবাদ আমি এখন একটি নির্দিষ্ট প্রক্রিয়া গণনা সরঞ্জাম পাই।

# Megabyte.
$ ps aux | grep python | awk '{sum=sum+$6}; END {print sum/1024 " MB"}'
87.9492 MB

# Byte.
$ ps aux | grep python | awk '{sum=sum+$6}; END {print sum " KB"}'
90064 KB

আমার প্রক্রিয়া তালিকা সংযুক্ত করুন।

$ ps aux  | grep python
root       943  0.0  0.1  53252  9524 ?        Ss   Aug19  52:01 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid
root       950  0.6  0.4 299680 34220 ?        Sl   Aug19 568:52 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid
root      3803  0.2  0.4 315692 36576 ?        S    12:43   0:54 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid
jonny    23325  0.0  0.1  47460  9076 pts/0    S+   17:40   0:00 python
jonny    24651  0.0  0.0  13076   924 pts/4    S+   18:06   0:00 grep python

উল্লেখ


মাল্টি পাইপ এড়াতে কোডের কেবলমাত্র একটি অপ্টিমাইজেশনps aux | awk '/python/{sum+=$6}; END {print sum/1024 " MB"}'
নেরনলেভেলু

4

পাইথন ৩.6 এবং সিউচিল ৫.৪.৫ এর জন্য এখানেmemory_percent() তালিকাভুক্ত ফাংশনটি ব্যবহার করা সহজ ।

import os
import psutil
process = psutil.Process(os.getpid())
print(process.memory_percent())

1
এটির জন্য lib psutil
কনফিফিক

4

আরও সহজ ছাড়া ব্যবহার করা /proc/self/status: /proc/self/statm। এটি বেশ কয়েকটি পরিসংখ্যানের একটি স্থান সীমানা তালিকা । উভয় ফাইল সর্বদা উপস্থিত থাকে কিনা তা আমি বলতে সক্ষম হয়েছি না।

জন্য / proc / [PID] / statm

পৃষ্ঠাগুলিতে মাপা মেমরির ব্যবহার সম্পর্কে তথ্য সরবরাহ করে। কলামগুলি হ'ল:

  • আকার (1) মোট প্রোগ্রামের আকার (ভিএমসিজে ইন / প্রোক / [পিআইডি] / স্ট্যাটাসের সমান)
  • বাসিন্দা (২) আবাসিক সেট আকার (/ প্রোকে / [পিআইডি] / স্থিতিতে ভিএমআরএসএসের সমান)
  • ভাগ করা (3) আবাসিক ভাগ করা পৃষ্ঠাগুলির সংখ্যা (অর্থাত্ কোনও ফাইলের সাহায্যে)
  • পাঠ্য (4) পাঠ্য (কোড)
  • lib (5) গ্রন্থাগার (লিনাক্স 2.6 থেকে অব্যবহৃত; সর্বদা 0)
  • ডেটা (6) ডেটা + স্ট্যাক
  • ডিটি ()) নোংরা পৃষ্ঠাগুলি (লিনাক্স ২.6 থেকে অব্যবহৃত; সর্বদা 0)

এখানে একটি সাধারণ উদাহরণ:

from pathlib import Path
from resource import getpagesize

PAGESIZE = getpagesize()
PATH = Path('/proc/self/statm')


def get_resident_set_size() -> int:
    """Return the current resident set size in bytes."""
    # statm columns are: size resident shared text lib data dt
    statm = PATH.read_text()
    fields = statm.split()
    return int(fields[1]) * PAGESIZE


data = []
start_memory = get_resident_set_size()
for _ in range(10):
    data.append('X' * 100000)
    print(get_resident_set_size() - start_memory)

এটি এমন একটি তালিকা তৈরি করে যা দেখে মনে হয়:

0
0
368640
368640
368640
638976
638976
909312
909312
909312

আপনি দেখতে পাচ্ছেন যে এটি 100,000 বাইটের প্রায় 3 বরাদ্দের পরে প্রায় 300,000 বাইটে লাফিয়ে যায়।


4

নীচে আমার ফাংশন ডেকরেটার যা ফাংশন কল করার আগে এই প্রক্রিয়াটি কতটা মেমরি গ্রাস করেছে, ফাংশন কল করার পরে এটি কত স্মৃতি ব্যবহার করে এবং কতক্ষণ ফাংশনটি কার্যকর হয় তা ট্র্যাক করতে সহায়তা করে।

import time
import os
import psutil


def elapsed_since(start):
    return time.strftime("%H:%M:%S", time.gmtime(time.time() - start))


def get_process_memory():
    process = psutil.Process(os.getpid())
    return process.memory_info().rss


def track(func):
    def wrapper(*args, **kwargs):
        mem_before = get_process_memory()
        start = time.time()
        result = func(*args, **kwargs)
        elapsed_time = elapsed_since(start)
        mem_after = get_process_memory()
        print("{}: memory before: {:,}, after: {:,}, consumed: {:,}; exec time: {}".format(
            func.__name__,
            mem_before, mem_after, mem_after - mem_before,
            elapsed_time))
        return result
    return wrapper

সুতরাং, যখন আপনি এটি দিয়ে সজ্জিত কিছু ফাংশন করবেন

from utils import track

@track
def list_create(n):
    print("inside list create")
    return [1] * n

আপনি এই আউটপুটটি দেখতে সক্ষম হবেন:

inside list create
list_create: memory before: 45,928,448, after: 46,211,072, consumed: 282,624; exec time: 00:00:00

3
import os, win32api, win32con, win32process
han = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION|win32con.PROCESS_VM_READ, 0, os.getpid())
process_memory = int(win32process.GetProcessMemoryInfo(han)['WorkingSetSize'])

7
এটি কী করে এবং এটি কীভাবে কাজ করে তার কিছু ব্যাখ্যা দিয়ে এটি উন্নত হতে পারে।
আর্টঅফ ওয়ারফেয়ার

2
ফিরে আসা বিশাল সংখ্যার (8 ডিজিট) এবং কীভাবে আমি খুব বেশি কিছু করছি না তার ভিত্তিতে, আমি অনুমান করছি এটি বাইট হতে হবে? বরং এটি প্রায় অলস ইন্টারেক্টিভ উদাহরণগুলির জন্য প্রায় 28.5 এমবি। (বাহ ... আমি এমনকি বুঝতে পারছি না উপরে মন্তব্য 4 বছর আগে থেকে খনি ছিল ... যে অদ্ভুত।)
ArtOfWarfare

3

ইউনিক্স সিস্টেম কমান্ডের জন্য time(/ usr / bin / সময়) আপনাকে সেই তথ্য দেয় যদি আপনি পাস করেন -v। Maximum resident set sizeনীচে দেখুন , যা সর্বোচ্চ (শিখর) বাস্তব (ভার্চুয়াল নয়) যা মেমোরি প্রোগ্রাম প্রয়োগের সময় ব্যবহৃত হয়েছিল :

$ /usr/bin/time -v ls /

    Command being timed: "ls /"
    User time (seconds): 0.00
    System time (seconds): 0.01
    Percent of CPU this job got: 250%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
    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): 0
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 315
    Voluntary context switches: 2
    Involuntary context switches: 0
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

1
মনে রাখবেন যে আপনি যদি এর timeপরিবর্তে কেবল ব্যবহার করার চেষ্টা করেন তবে এটি ব্যর্থ হতে পারে /usr/bin/time। দেখুন: askubuntu.com/questions/434289/...
abought

1

অজগর বেয়ারের উত্তর পেতে শ এবং ওএস ব্যবহার করে।

float(sh.awk(sh.ps('u','-p',os.getpid()),'{sum=sum+$6}; END {print sum/1024}'))

উত্তরটি মেগাবাইটে রয়েছে।


4
লক্ষ করা উচিত যে `sh 'একটি stdlib মডিউল নয়। যদিও এটি পাইপের সাথে ইনস্টলযোগ্য।
জার্গেন এ। এয়ারহার্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.