पायथन प्रक्रिया द्वारा उपयोग की जाने वाली कुल मेमोरी?


266

क्या पायथन कार्यक्रम के लिए एक तरीका है जिससे यह निर्धारित किया जा सके कि वर्तमान में कितनी मेमोरी है? मैंने किसी एकल ऑब्जेक्ट के लिए मेमोरी उपयोग के बारे में चर्चा की है, लेकिन मुझे प्रक्रिया के लिए कुल मेमोरी उपयोग की आवश्यकता है, ताकि मैं यह निर्धारित कर सकूं कि कैश्ड डेटा को छोड़ना शुरू करना कब आवश्यक है।

जवाबों:


302

यहाँ एक उपयोगी समाधान है जो लिनक्स, विंडोज 7, आदि सहित विभिन्न ऑपरेटिंग सिस्टम के लिए काम करता है।

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

मेरे वर्तमान पायथन 2.7 पर Psutil 5.6.3 के साथ स्थापित, अंतिम पंक्ति होनी चाहिए

print(process.memory_info()[0])

इसके बजाय (एपीआई में बदलाव हुआ था)।

नोट: pip install psutilयदि यह अभी तक स्थापित नहीं है, तो करें।


3
psutilक्रॉस प्लेटफॉर्म है और psकमांड लाइन टूल के समान मानों को वापस कर सकता है : pythonhosted.org/psutil/#psutil.Process.memory_info
amos

1
"( psutil) वर्तमान में लिनक्स, विंडोज, ओएसएक्स, फ्रीबीएसडी और सन सोलारिस, दोनों 32-बिट और 64-बिट आर्किटेक्चर दोनों का समर्थन करता है, जो कि पायथन संस्करणों के साथ 2.6 से 3.4 तक है" प्रलेखन से
सेसिलिया

2
यह संख्या प्रक्रिया एक्सप्लोरर में एक से मेल क्यों नहीं खाती है? Psutil से संख्या हमेशा लगभग 10% से बड़ी लगती है।
wordsforthewise

39
ध्यान दें कि psutil मानक पुस्तकालय में नहीं है
ग्रैजाइटिस

12
के हाल के संस्करणों के लिए psutil, psutil.Process()के बराबर है psutil.Process(os.getpid())। टाइप करने के लिए आपको याद रखने की आवश्यकता कम है।
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
इकाइयां किलोबाइट में नहीं हैं। यह प्लेटफॉर्म पर निर्भर है, इसलिए आपको इसका पता लगाने के लिए resource.getpagesize () का उपयोग करना होगा। दिए गए पायथन डॉक्स ( docs.python.org/2/library/resource.html#resource-usage ) वास्तव में इसके बारे में बहुत स्पष्ट हैं। यह मेरे डिब्बे में 4096 है।
बेन लिन

5
@BenLin उन पायथन डॉक्स स्पष्ट रूप से गलत हैं, या मैक संस्करण पर एक बग है। गेटट्रेज द्वारा उपयोग की जाने वाली इकाई और गेटपेजाइज़ द्वारा लौटाए गए मूल्य निश्चित रूप से अलग हैं।
एंड्रयू

6
वर्तमान उपयोग के लिए पूछा गया प्रश्न । ध्यान दें कि यह अधिकतम उपयोग है। (फिर भी एक उपयोगी उत्तर, जो लोग इसे गलती से कॉपी-पेस्ट करते हैं, उन्हें चेतावनी देते हैं।)
ल्यूक

65

विंडोज पर, आप WMI ( होम पेज , चीज़शॉप ) का उपयोग कर सकते हैं :


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/recipes/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)
जॉन Fouhy

1
यह विंडोज कोड मेरे लिए विंडोज 7 x64 पर काम नहीं करता है, यहां तक ​​कि जॉन फूह के टिप्पणी संशोधन के बाद भी।
बसज

मेरे पास यह त्रुटि है: स्व में obj के लिए [ wmi_object (obj, Inst_of, फ़ील्ड्स) वापस करें ।_raw_query (wql)] फ़ाइल "C: \ Python27 \ lib \ साइट-संकुल \ win \com \ ग्राहक \ उपयोग", पंक्ति 84। अगली वापसी में _get_good_object_ (self._iter .next) (, resultCLSID = self.resultCLSID) pywintypes.com_error: (-2147217385, 'OLE त्रुटि 0x80041017', कोई नहीं, कोई नहीं) अगर कोई मेरी मदद कर सकता है? मैंने x32 पर 8 x64 लेकिन अजगर पर जीत हासिल की है
रादु व्लाद

नोट: मैंने विमी मॉड्यूल के (नवीनतम) स्रोत का निरीक्षण करने के बाद जॉन फूही के सुझाव के बाद विंडोज़ उदाहरण को अपडेट किया। यह भी देखें (1) , (2)
जेड्वर्ड

33

यूनिक्स पर, आप psइसे मॉनिटर करने के लिए उपकरण का उपयोग कर सकते हैं :

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

जहां 1347 कुछ प्रक्रिया आईडी है। इसके अलावा, परिणाम एमबी में है।


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

लिनक्स 4.4 और 4.9 पर परीक्षण किया गया, लेकिन यहां तक ​​कि एक शुरुआती लिनक्स संस्करण को भी काम करना चाहिए।

में देख रहे हैं man procऔर के बारे में जानकारी के लिए खोज /proc/$PID/statusफ़ाइल, यह ( "VmPTE" के लिए लिनक्स 2.6.10) की तरह कुछ क्षेत्रों के लिए न्यूनतम संस्करणों का उल्लेख है, लेकिन "VmRSS" क्षेत्र (जो मैं यहाँ का उपयोग करें) इस तरह के कोई जिक्र नहीं है। इसलिए मुझे लगता है कि यह एक प्रारंभिक संस्करण के बाद से वहाँ है।


5

मुझे यह पसंद है , @bayer के लिए धन्यवाद। मुझे अब एक विशिष्ट प्रक्रिया गिनती उपकरण मिलता है।

# 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"}'
NeronLeVelu

4

पायथन 3.6 और psutil 5.4.5 के लिए यहांmemory_percent() सूचीबद्ध फ़ंक्शन का उपयोग करना आसान है

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

1
इस आवश्यकता lib psutil
confiq

4

और भी आसान से उपयोग करने के लिए /proc/self/status: /proc/self/statm। यह कई आंकड़ों की सिर्फ एक सीमांकित सूची है । मैं यह बताने में सक्षम नहीं हूं कि क्या दोनों फाइलें हमेशा मौजूद हैं।

/ Proc / [pid] / statm

पृष्ठों में मापा गया, मेमोरी उपयोग के बारे में जानकारी प्रदान करता है। स्तंभ हैं:

  • आकार (1) कुल कार्यक्रम का आकार (VmSize / proc / [pid] / स्थिति के समान)
  • निवासी (2) निवासी सेट आकार (VmRSS के रूप में / proc / [pid] / स्थिति)
  • साझा (3) निवासी साझा किए गए पृष्ठों की संख्या (अर्थात, फ़ाइल द्वारा समर्थित) (रुपये के रूप में + RssSemem in / proc / [pid] / स्थिति)
  • पाठ (4) पाठ (कोड)
  • lib (5) लाइब्रेरी (लिनक्स 2.6 के बाद से अप्रयुक्त; हमेशा 0)
  • data (6) data + stack
  • dt (7) गंदे पृष्ठ (लिनक्स 2.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 साल पहले की थी ... यह अजीब है।)
आर्टऑफवर्फ

3

यूनिक्स सिस्टम कमांड के लिए time(/ usr / bin / time) आपको वह जानकारी देता है यदि आप -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/…
लड़ा गया

1

अजगर बायर के जवाब में प्राप्त करने के लिए श और ओएस का उपयोग करना।

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

उत्तर मेगाबाइट में है।


4
यह ध्यान दिया जाना चाहिए कि `श’ एक stdlib मॉड्यूल नहीं है। यह पाइप के साथ इंस्टॉल करने योग्य है, हालांकि।
जुरगेन ए। इरहार्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.