ในขณะที่คนอื่นชี้ให้เห็นอย่างถูกต้องมันเป็นเรื่องยากที่จะจัดการกับหน่วยความจำจริงที่ใช้โดยกระบวนการสิ่งที่มีพื้นที่ที่ใช้ร่วมกันและไฟล์ mmap'ed และอะไรก็ตาม
หากคุณเป็นผู้ทดลองคุณสามารถเรียกใช้valgrind และเทือกเขา สิ่งนี้อาจจะค่อนข้างหนักสำหรับผู้ใช้ทั่วไป แต่คุณจะได้รับแนวคิดเกี่ยวกับพฤติกรรมความจำของแอปพลิเคชันเมื่อเวลาผ่านไป หากแอปพลิเคชัน malloc () เป็นสิ่งที่ต้องการจริงๆสิ่งนี้จะช่วยให้คุณแสดงการใช้หน่วยความจำแบบไดนามิกที่แท้จริงของกระบวนการ แต่การทดลองนี้สามารถ "วางยาพิษ" ได้
ในการทำให้เรื่องซับซ้อนลีนุกซ์อนุญาตให้คุณเขียนทับหน่วยความจำของคุณมากเกินไป เมื่อคุณใช้หน่วยความจำ malloc () แสดงว่าคุณตั้งใจจะใช้ความจำ แต่การจัดสรรจะไม่เกิดขึ้นจนกว่าคุณจะเขียนไบต์ลงในหน้าใหม่ของ "RAM" ที่จัดสรรของคุณ คุณสามารถพิสูจน์ได้ด้วยตัวเองโดยการเขียนและรันโปรแกรม C ตัวเล็ก ๆ เช่น:
// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
void *p;
sleep(5)
p = malloc(16ULL*1024*1024*1024);
printf("p = %p\n", p);
sleep(30);
return 0;
}
# Shell:
cc test.c -o test && ./test &
top -p $!
รันสิ่งนี้บนเครื่องที่มี RAM น้อยกว่า 16GB และ voila! คุณเพิ่งได้คะแนนจากหน่วยความจำ 16GB! (ไม่ไม่ได้จริงๆ)
โปรดสังเกตtop
ว่าคุณเห็น "VIRT" เป็น 16.004G แต่% MEM คือ 0.0
เรียกใช้อีกครั้งด้วย valgrind:
# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30
และ massif บอกว่า "ผลรวมของ allocs () = 16GB" นั่นไม่น่าสนใจมาก
แต่ถ้าคุณใช้ในกระบวนการมีสติ :
# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30
--------------------------------------------------------------------------------
Command: cc test.c -o test
Massif arguments: (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------
KB
77.33^ :
| #:
| :@::@:#:
| :::::@@::@:#:
| @:: :::@@::@:#:
| ::::@:: :::@@::@:#:
| ::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
| :@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
0 +----------------------------------------------------------------------->Mi
0 1.140
และที่นี่เราเห็น (มากสังเกตุและมีความมั่นใจสูงมาก) ว่าคอมไพเลอร์จัดสรรฮีป 77KB
เหตุใดจึงต้องพยายามอย่างหนักเพื่อให้ได้รับการใช้งานฮีพเพียงอย่างเดียว เนื่องจากวัตถุที่ใช้ร่วมกันและส่วนข้อความทั้งหมดที่กระบวนการใช้ (ในตัวอย่างนี้คอมไพเลอร์) ไม่น่าสนใจอย่างมาก ค่าใช้จ่ายคงที่สำหรับกระบวนการ อันที่จริงการขอร้องกระบวนการต่อมาเกือบจะ "ฟรี"
เปรียบเทียบและคอนทราสต์ต่อไปนี้ด้วย:
MMAP () ไฟล์ 1GB VMSize ของคุณจะเป็น 1 + GB แต่คุณจะใช้ขนาดชุดที่อยู่อาศัยจะเป็นเพียงบางส่วนของไฟล์ที่คุณได้รับการทำเพจใน และถ้าคุณ "อ่าน" ไฟล์ทั้งหมดจากนั้นเมื่อถึงจุดสิ้นสุดเคอร์เนลอาจเริ่มต้นเพจแล้ว (ซึ่งเป็นเรื่องง่ายที่จะทำเพราะเคอร์เนลรู้วิธีการ / ตำแหน่งที่จะเปลี่ยนหน้าเหล่านั้นได้อย่างถูกต้อง ) ไม่ว่าในกรณีใด VMSize หรือ RSS จะเป็นตัวบ่งชี้ที่ดีสำหรับการใช้งาน "หน่วยความจำ" ของคุณ คุณยังไม่ได้ malloc () 'ed อะไรเลย
ในทางตรงกันข้าม Malloc () และแตะหน่วยความจำจำนวนมาก - จนกว่าหน่วยความจำของคุณจะถูกเปลี่ยนเป็นดิสก์ ดังนั้นหน่วยความจำที่จัดสรรของคุณจะเกิน RSS ของคุณแล้ว ที่นี่ VMSize ของคุณอาจเริ่มบอกบางสิ่งกับคุณ (กระบวนการของคุณเป็นเจ้าของหน่วยความจำมากกว่าสิ่งที่อยู่ใน RAM จริง) แต่ก็ยังคงยากที่จะแยกแยะความแตกต่างระหว่าง VM ซึ่งเป็นเพจที่ใช้ร่วมกันและ VM ที่เปลี่ยนข้อมูล
นี่คือจุดที่ valgrind / massif ได้รับความสนใจ มันแสดงให้คุณเห็นถึงสิ่งที่คุณจัดสรรไว้โดยไม่เจตนา
htop
ผู้เขียนกับคำถามที่คล้ายกันหนึ่งคำถามที่ฉันมีในวันอื่น ... วิธีการคำนวณการใช้หน่วยความจำจาก / proc / meminfo (เช่น htop)