Yanıtlar:
RSS Yerleşik Ayar Boyutudur ve bu işleme ne kadar bellek tahsis edildiğini ve RAM'de olduğunu göstermek için kullanılır. Değiştirilen belleği içermez. Bu kitaplıklardan gelen sayfalar gerçekte bellekte olduğu sürece, paylaşılan kitaplıklardan bellek içerir. Tüm yığın ve yığın belleği içerir.
VSZ, Sanal Bellek Boyutudur. Değiştirilen bellek, ayrılan ancak kullanılmayan bellek ve paylaşılan kitaplıklardan alınan bellek de dahil olmak üzere, işlemin erişebileceği tüm belleği içerir.
Yani A süreci 500K'lık bir ikili dosyaya sahipse ve 2500K paylaşılan kütüphaneye bağlıysa, 100K'sı gerçekte bellekte olan (geri kalanı değiştirilir veya kullanılmaz) 200K yığın / yığın tahsisine sahipse ve sadece 1000K paylaşılan kütüphaneleri yükledi ve kendi ikilisinin 400K'sı:
RSS: 400K + 1000K + 100K = 1500K
VSZ: 500K + 2500K + 200K = 3200K
Belleğin bir kısmı paylaşıldığından, birçok işlem bunu kullanabilir, bu nedenle tüm RSS değerlerini toplarsanız, sisteminizde olduğundan daha fazla alan elde edebilirsiniz.
Ayrılan bellek, aslında program tarafından kullanılıncaya kadar RSS'de olmayabilir. Dolayısıyla, programınız bir sürü bellek ayırdıysa, zamanla kullanırsa, RSS'nin yükseldiğini ve VSZ'nin aynı kaldığını görebilirsiniz.
Ayrıca PSS (orantılı set boyutu) vardır. Bu, paylaşılan belleği geçerli işlem tarafından kullanılan bir oran olarak izleyen daha yeni bir ölçüdür. Dolayısıyla, önceden aynı paylaşılan kitaplığı kullanan iki işlem varsa:
PSS: 400K + (1000K/2) + 100K = 400K + 500K + 100K = 1000K
İş parçacıklarının tümü aynı adres alanını paylaşır, böylece her iş parçacığı için RSS, VSZ ve PSS, işlemdeki diğer iş parçacıklarının tümü ile aynıdır. Bu bilgiyi linux / unix biçiminde görüntülemek için ps veya top komutunu kullanın.
Bundan daha fazla yol var, daha fazla bilgi edinmek için aşağıdaki referansları kontrol edin:
Ayrıca bakınız:
libxml2.so
, paylaşılan kütüphane RSS'lerinin her birinde sayılır, bu nedenle RSS'lerinin toplamı kullanılan gerçek bellekten daha fazla olacaktır.
top
. Bu sistemin herhangi bir takası yoktur, swapon --show
hiçbir şey döndürmez. Bunu nasıl açıklıyorsunuz? Vsz takas + paylaşılan kütüphaneler ise, bu durumda, paylaşılan kütüphaneler 3.3G? Mümkün mü? Gerçekten şaşkın ...
RSS Yerleşik Set Boyutu (fiziksel olarak yerleşik bellek - şu anda makinenin fiziksel belleğinde yer kaplıyor) ve VSZ Sanal Bellek Boyutu (ayrılmış adres alanı - bu işlemin bellek haritasında ayrılmış adresler var, ancak mutlaka gerçek bellek şimdi arkasında).
Günümüzde sıradan sanal makinelerde, makinenin bakış açısından fiziksel belleğin gerçek fiziksel bellek olmayabileceğini unutmayın.
Minimal çalıştırılabilir örnek
Bunun mantıklı olması için, sayfalamanın temellerini anlamalısınız: x86 sayfalama nasıl çalışır? ve özellikle işletim sisteminin sanal belleği, RAM veya disk üzerinde bir yedek depolama alanına (RSS yerleşik belleği) sahip olmadan önce sayfa tabloları / dahili bellek defteri tutma (VSZ sanal bellek) aracılığıyla ayırabilir.
Şimdi bunu gözlemlemek için, aşağıdakileri yapan bir program oluşturalım:
mmap
main.c
#define _GNU_SOURCE
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
typedef struct {
unsigned long size,resident,share,text,lib,data,dt;
} ProcStatm;
/* /programming/1558402/memory-usage-of-current-process-in-c/7212248#7212248 */
void ProcStat_init(ProcStatm *result) {
const char* statm_path = "/proc/self/statm";
FILE *f = fopen(statm_path, "r");
if(!f) {
perror(statm_path);
abort();
}
if(7 != fscanf(
f,
"%lu %lu %lu %lu %lu %lu %lu",
&(result->size),
&(result->resident),
&(result->share),
&(result->text),
&(result->lib),
&(result->data),
&(result->dt)
)) {
perror(statm_path);
abort();
}
fclose(f);
}
int main(int argc, char **argv) {
ProcStatm proc_statm;
char *base, *p;
char system_cmd[1024];
long page_size;
size_t i, nbytes, print_interval, bytes_since_last_print;
int snprintf_return;
/* Decide how many ints to allocate. */
if (argc < 2) {
nbytes = 0x10000;
} else {
nbytes = strtoull(argv[1], NULL, 0);
}
if (argc < 3) {
print_interval = 0x1000;
} else {
print_interval = strtoull(argv[2], NULL, 0);
}
page_size = sysconf(_SC_PAGESIZE);
/* Allocate the memory. */
base = mmap(
NULL,
nbytes,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
-1,
0
);
if (base == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* Write to all the allocated pages. */
i = 0;
p = base;
bytes_since_last_print = 0;
/* Produce the ps command that lists only our VSZ and RSS. */
snprintf_return = snprintf(
system_cmd,
sizeof(system_cmd),
"ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == \"%ju\") print}'",
(uintmax_t)getpid()
);
assert(snprintf_return >= 0);
assert((size_t)snprintf_return < sizeof(system_cmd));
bytes_since_last_print = print_interval;
do {
/* Modify a byte in the page. */
*p = i;
p += page_size;
bytes_since_last_print += page_size;
/* Print process memory usage every print_interval bytes.
* We count memory using a few techniques from:
* /programming/1558402/memory-usage-of-current-process-in-c */
if (bytes_since_last_print > print_interval) {
bytes_since_last_print -= print_interval;
printf("extra_memory_committed %lu KiB\n", (i * page_size) / 1024);
ProcStat_init(&proc_statm);
/* Check /proc/self/statm */
printf(
"/proc/self/statm size resident %lu %lu KiB\n",
(proc_statm.size * page_size) / 1024,
(proc_statm.resident * page_size) / 1024
);
/* Check ps. */
puts(system_cmd);
system(system_cmd);
puts("");
}
i++;
} while (p < base + nbytes);
/* Cleanup. */
munmap(base, nbytes);
return EXIT_SUCCESS;
}
Derleyin ve çalıştırın:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
sudo dmesg -c
./main.out 0x1000000000 0x200000000
echo $?
sudo dmesg
nerede:
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
: Linux'un fiziksel RAM'den daha büyük bir mmap çağrısı yapmamıza izin vermesi için gereklidir: malloc'un ayırabileceği maksimum bellekProgram çıktısı:
extra_memory_committed 0 KiB
/proc/self/statm size resident 67111332 768 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 1648
extra_memory_committed 8388608 KiB
/proc/self/statm size resident 67111332 8390244 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 8390256
extra_memory_committed 16777216 KiB
/proc/self/statm size resident 67111332 16778852 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 16778864
extra_memory_committed 25165824 KiB
/proc/self/statm size resident 67111332 25167460 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 25167472
Killed
Çıkış durumu:
137
tarafından hangi 128 + sinyal numarası kuralı vasıtasıyla biz sinyal numarası var 9
, man 7 signal
diyor sigkill Linux tarafından gönderilen, dışı belleğe katil .
Çıktı yorumu:
printf '0x%X\n' 0x40009A4 KiB ~= 64GiB
( ps
değerler KiB cinsindendir).extra_memory_committed 0
yani henüz hiçbir sayfaya dokunmadık. RSS, 1648 KiB
metin alanı, globaller vb. Gibi normal program başlangıcı için ayrılmış küçük bir dosyadır.8388608 KiB == 8GiB
değerli sayfalara yazdık. Sonuç olarak, RSS tam olarak 8GIB'ye yükseltildi.8390256 KiB == 8388608 KiB + 1648 KiB
Ayrıca bakınız: /unix/35129/need-explanation-on-resident-set-size-virtual-size
OOM katil günlükleri
Bizim dmesg
komutları OOM katil günlükleri göstermiştir.
Bunların tam bir yorumu şu şekilde sorulmuştur:
Günlüğün ilk satırı şuydu:
[ 7283.479087] mongod invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
İlginç bir şekilde, dizüstü bilgisayarımda her zaman arka planda OOM katilini tetikleyen MongoDB arka plan programı olduğunu görüyoruz, muhtemelen zavallı şey biraz bellek ayırmaya çalışırken.
Ancak, OOM katili mutlaka uyandıranı öldürmez.
Çağrının ardından, çekirdek aşağıdakileri içeren bir tablo veya işlemler yazdırır oom_score
:
[ 7283.479292] [ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name
[ 7283.479303] [ 496] 0 496 16126 6 172032 484 0 systemd-journal
[ 7283.479306] [ 505] 0 505 1309 0 45056 52 0 blkmapd
[ 7283.479309] [ 513] 0 513 19757 0 57344 55 0 lvmetad
[ 7283.479312] [ 516] 0 516 4681 1 61440 444 -1000 systemd-udevd
ve ileride görüyoruz ki main.out
, önceki çağrımızda kendi küçüklerimiz gerçekten öldürüldü:
[ 7283.479871] Out of memory: Kill process 15665 (main.out) score 865 or sacrifice child
[ 7283.479879] Killed process 15665 (main.out) total-vm:67111332kB, anon-rss:92kB, file-rss:4kB, shmem-rss:30080832kB
[ 7283.479951] oom_reaper: reaped process 15665 (main.out), now anon-rss:0kB, file-rss:0kB, shmem-rss:30080832kB
Bu günlükte, söz score 865
konusu işlemin, muhtemelen şu adreste belirtildiği gibi en yüksek (en kötü) OOM katil skoruna sahip olduğu belirtilmektedir: /unix/153585/how-does-the-oom-killer-decide-which- süreç-to-kill ilk
Ayrıca ilginç bir şekilde, her şey o kadar hızlı oldu ki, serbest hafıza hesaplanmadan önce oom
, DeadlineMonitor
süreç tarafından tekrar uyandı :
[ 7283.481043] DeadlineMonitor invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
ve bu sefer genellikle bilgisayarlarımın normal bellek domuzu olan bazı Chromium işlemini öldürdü:
[ 7283.481773] Out of memory: Kill process 11786 (chromium-browse) score 306 or sacrifice child
[ 7283.481833] Killed process 11786 (chromium-browse) total-vm:1813576kB, anon-rss:208804kB, file-rss:0kB, shmem-rss:8380kB
[ 7283.497847] oom_reaper: reaped process 11786 (chromium-browse), now anon-rss:0kB, file-rss:0kB, shmem-rss:8044kB
Ubuntu 19.04, Linux çekirdeği 5.0.0'da test edilmiştir.
Sanırım RSS vs VSZ hakkında çok şey söylendi. Bir yönetici / programcı / kullanıcı bakış açısından, uygulamaları tasarladığımda / kodladığımda RSZ, (Yerleşik bellek) hakkında daha fazla endişe duyuyorum ve daha fazla değişken çektiğinizde (yığılı) bu değerin yükseldiğini göreceksiniz. Döngüde malloc tabanlı alan tahsisi oluşturmak için basit bir program deneyin ve bu hatalı alana veri doldurduğunuzdan emin olun. RSS sürekli yükseliyor. VSZ söz konusu olduğunda, linux'un yaptığı daha çok sanal bellek haritalaması ve temel özelliklerinden biri geleneksel işletim sistemi konseptlerinden türetilmiş. VSZ yönetimi, çekirdeğin Sanal bellek yönetimi tarafından yapılır, VSZ hakkında daha fazla bilgi için, Robert Love'ın çekirdekte temel görev_yapısı veri yapısının bir parçası olan mm_struct ve vm_struct açıklamasına bakın.
Yönetilmezler, ölçülürler ve muhtemelen sınırlıdırlar (bkz getrlimit
. Getrlimit için sistem çağrısı ) (2 ).
RSS, yerleşik set boyutu (sanal adres alanınızın RAM'de oturan kısmı) anlamına gelir .
Proc (5) kullanarak ve durumunu (bellek tüketimi dahil ) kullanarak 1234 işleminin sanal adres alanını sorgulayabilirsiniz.cat /proc/1234/maps
cat /proc/1234/status