Total memori yang digunakan oleh proses Python?

266

Apakah ada cara untuk program Python untuk menentukan berapa banyak memori yang sedang digunakan? Saya telah melihat diskusi tentang penggunaan memori untuk satu objek, tetapi yang saya butuhkan adalah penggunaan memori total untuk proses tersebut, sehingga saya dapat menentukan kapan perlu untuk mulai membuang data yang di-cache.

rwallace
sumber

Jawaban:

303

Berikut ini adalah solusi yang berguna yang berfungsi untuk berbagai sistem operasi, termasuk Linux, Windows 7, dll .:

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

Pada instal Python 2.7 saya saat ini dengan psutil 5.6.3, baris terakhir seharusnya

print(process.memory_info()[0])

sebagai gantinya (ada perubahan pada API).

Catatan: lakukan pip install psutiljika belum diinstal.

Basj
sumber
3
psutiladalah lintas platform dan dapat mengembalikan nilai yang sama dengan psalat baris perintah: pythonhosted.org/psutil/#psutil.Process.memory_info
amos
1
"( psutil) saat ini mendukung Linux, Windows, OSX, FreeBSD dan Sun Solaris, keduanya arsitektur 32-bit dan 64-bit, dengan versi Python dari 2,6 hingga 3,4" dari Dokumentasi
Cecilia
2
Mengapa nomor ini tidak cocok dengan yang ada di proses explorer? Jumlah dari psutil tampaknya selalu lebih besar sekitar 10%.
kata
39
Perhatikan bahwa psutil tidak ada di perpustakaan standar
grisaitis
12
Untuk versi terbaru psutil, psutil.Process()setara dengan psutil.Process(os.getpid()). Itu satu hal lagi yang perlu Anda ingat untuk mengetik.
rnorris
208

Untuk sistem berbasis Unix (Linux, Mac OS X, Solaris), Anda dapat menggunakan getrusage()fungsi dari modul perpustakaan standar resource. Objek yang dihasilkan memiliki atribut ru_maxrss, yang memberikan penggunaan memori puncak untuk proses panggilan:

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

Dokumen Python tidak mencatat unit. Lihat man getrusage.2halaman sistem spesifik Anda untuk memeriksa unit untuk nilainya. Pada Ubuntu 18.04, unit dicatat sebagai kilobyte. Di Mac OS X, ini byte.

The getrusage()fungsi juga dapat diberikan resource.RUSAGE_CHILDRENuntuk mendapatkan penggunaan untuk proses anak, dan (pada beberapa sistem)resource.RUSAGE_BOTH total (diri dan anak) penggunaan proses.

Jika Anda hanya peduli dengan Linux, Anda dapat membaca file /proc/self/statusatau /proc/self/statmsebagai alternatif yang dijelaskan dalam jawaban lain untuk pertanyaan ini dan yang ini juga.

Nathan Craike
sumber
2
Oke, akan lakukan. Saya tidak yakin apakah SO memiliki proses untuk menggabungkan pertanyaan atau apa. Posting duplikat sebagian untuk menunjukkan kepada orang-orang ada solusi perpustakaan standar pada kedua pertanyaan ... dan sebagian untuk perwakilan. ;) Haruskah saya menghapus jawaban ini?
Nathan Craike
6
Mac OS pasti mengembalikan RSS dalam byte, Linux mengembalikannya dalam kilobyte.
Neil
13
Unit TIDAK dalam kilobyte. Ini tergantung platform, jadi Anda harus menggunakan resource.getpagesize () untuk mengetahuinya. Python docs yang diberikan ( docs.python.org/2/library/resource.html#resource-usage ) sebenarnya sangat jelas tentang hal itu. Ada 4096 di kotak saya.
Ben Lin
5
@ BenLin Dokumen Python itu jelas salah, atau ada bug pada versi Mac. Unit yang digunakan oleh getrusage dan nilai yang dikembalikan oleh getpagesize jelas berbeda.
Andrew
6
Pertanyaan yang diajukan untuk penggunaan saat ini . Perhatikan bahwa ini adalah penggunaan maksimum . (Masih jawaban yang berguna, hanya memperingatkan orang-orang yang keliru menyalin-tempelkannya.)
Luc
65

Di Windows, Anda dapat menggunakan WMI ( beranda , cheeseshop ):


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)

Di Linux (dari python cookbook 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
kode kode
sumber
14
Kode Windows tidak berfungsi untuk saya. Perubahan ini tidak:return int(result[0].WorkingSet)
John Fouhy
1
Kode Windows ini tidak berfungsi untuk saya di Windows 7 x64, bahkan setelah modifikasi komentar John Fouhy.
Basj
Saya memiliki kesalahan ini: return [ wmi_object (obj, instance_of, bidang) untuk obj di self._raw_query (wql)] File "C: \ Python27 \ lib \ situs-paket \ win32com \ client \ util.py", baris 84, di return berikutnya _get_good_object_ (self._iter .next (), resultCLSID = self.resultCLSID) pywintypes.com_error: (-2147217385, 'OLE error 0x80041017', Tidak Ada, Tidak Ada) jika ada yang bisa membantu saya? Saya telah menang 8 x 64 tetapi python di x32
Radu Vlad
Catatan: Saya memperbarui contoh windows mengikuti saran John Fouhy setelah memeriksa sumber (terbaru) dari modul wmi. Lihat juga (1) , (2) .
jedwards
33

Pada unix, Anda dapat menggunakan psalat untuk memonitornya:

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

di mana 1347 adalah beberapa id proses. Juga, hasilnya adalah dalam MB.

bayer
sumber
8

Penggunaan memori saat ini dari proses saat ini di Linux , untuk Python 2 , Python 3 , dan pypy , tanpa impor apa pun:

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

Itu membaca file status dari proses saat ini, mengambil semuanya setelah itu VmRSS:, kemudian mengambil segalanya sebelum baris baru pertama (mengisolasi nilai VmRSS), dan akhirnya memotong 3 byte terakhir yang merupakan ruang dan unit (kB).
Untuk kembali, ia menghapus spasi dan mengembalikannya sebagai angka.

Diuji pada Linux 4.4 dan 4.9, tetapi bahkan versi Linux awal harus berfungsi: mencari man procdan mencari info pada /proc/$PID/statusfile, ia menyebutkan versi minimum untuk beberapa bidang (seperti Linux 2.6.10 untuk "VmPTE"), tetapi "VmRSS "bidang (yang saya gunakan di sini) tidak disebutkan. Karena itu saya menganggap sudah ada di sana sejak versi awal.

Luc
sumber
5

Saya suka itu , terima kasih untuk @bayer. Saya mendapatkan alat hitung proses tertentu, sekarang.

# 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

Lampirkan daftar proses saya.

$ 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

Referensi

Chu-Siang Lai
sumber
hanya optimasi kode untuk menghindari multi-pipaps aux | awk '/python/{sum+=$6}; END {print sum/1024 " MB"}'
NeronLeVelu
4

Untuk Python 3.6 dan psutil 5.4.5 lebih mudah untuk menggunakan memory_percent()fungsi yang tercantum di sini .

import os
import psutil
process = psutil.Process(os.getpid())
print(process.memory_percent())
A.Ametov
sumber
1
ini membutuhkan lib psutil
confiq
4

Bahkan lebih mudah digunakan daripada /proc/self/status: /proc/self/statm. Ini hanya daftar terbatas beberapa ruang statistik . Saya belum bisa memastikan apakah kedua file selalu ada.

/ proc / [pid] / statm

Memberikan informasi tentang penggunaan memori, diukur dalam halaman. Kolomnya adalah:

  • size (1) total ukuran program (sama dengan VmSize di / proc / [pid] / status)
  • resident (2) resident set size (sama dengan VmRSS di / proc / [pid] / status)
  • shared (3) jumlah resident shared pages (yaitu, didukung oleh file) (sama seperti RssFile + RssShmem di / proc / [pid] / status)
  • teks (4) teks (kode)
  • lib (5) library (tidak digunakan sejak Linux 2.6; selalu 0)
  • data (6) data + stack
  • dt (7) halaman kotor (tidak digunakan sejak Linux 2.6; selalu 0)

Berikut ini contoh sederhana:

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)

Itu menghasilkan daftar yang terlihat seperti ini:

0
0
368640
368640
368640
638976
638976
909312
909312
909312

Anda dapat melihat bahwa itu melonjak sekitar 300.000 byte setelah sekitar 3 alokasi 100.000 byte.

Don Kirkby
sumber
4

Di bawah ini adalah dekorator fungsi saya yang memungkinkan untuk melacak berapa banyak memori yang digunakan proses ini sebelum panggilan fungsi, berapa banyak memori yang digunakan setelah panggilan fungsi, dan berapa lama fungsi ini dijalankan.

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

Jadi, ketika Anda memiliki beberapa fungsi yang dihiasi dengannya

from utils import track

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

Anda akan dapat melihat output ini:

inside list create
list_create: memory before: 45,928,448, after: 46,211,072, consumed: 282,624; exec time: 00:00:00
Ihor B.
sumber
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'])
Pedro Reis
sumber
7
Ini dapat ditingkatkan dengan beberapa penjelasan tentang apa yang dilakukannya dan bagaimana cara kerjanya.
ArtOfWarfare
2
Berdasarkan jumlah besar yang dikembalikan (8 digit) dan bagaimana saya tidak melakukan banyak hal, saya menduga ini harus byte? Jadi sekitar 28,5 MB untuk contoh interaktif yang agak menganggur. (Wow ... Saya bahkan tidak menyadari komentar di atas adalah milik saya sejak 4 tahun lalu ... itu aneh.)
ArtOfWarfare
3

Untuk perintah sistem Unix time(/ usr / bin / time) memberi Anda info itu jika Anda lulus -v. Lihat di Maximum resident set sizebawah ini, yang merupakan memori maksimum (puncak) nyata (bukan virtual) yang digunakan selama eksekusi program :

$ /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
Charly Empereur-mot
sumber
1
Catatan bahwa ini mungkin gagal jika Anda hanya mencoba untuk menggunakan timebukan /usr/bin/time. Lihat: askubuntu.com/questions/434289/...
abaikan
1

Menggunakan sh dan os untuk masuk ke jawaban python bayer.

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

Jawabannya dalam megabita.

Newmu
sumber
4
Perlu dicatat bahwa `sh 'bukan modul stdlib. Ini bisa diinstal dengan pip.
Jürgen A. Erhard