Như những người khác đã chỉ ra một cách chính xác, thật khó để xử lý bộ nhớ thực được sử dụng bởi một quy trình, những gì với các khu vực được chia sẻ, và các tập tin mmap và không có gì.
Nếu bạn là người thử nghiệm, bạn có thể chạy valgrind và massif . Điều này có thể hơi nặng nề đối với người dùng thông thường nhưng bạn sẽ có ý tưởng về hành vi bộ nhớ của ứng dụng theo thời gian. Nếu một malloc () chính xác là những gì nó cần thì điều này sẽ cung cấp cho bạn một đại diện tốt về việc sử dụng bộ nhớ động thực sự của một quá trình. Nhưng thí nghiệm này có thể bị "đầu độc".
Để làm phức tạp vấn đề, Linux cho phép bạn vượt quá bộ nhớ của bạn. Khi bạn malloc () bộ nhớ, bạn nói rõ ý định tiêu thụ bộ nhớ. Nhưng phân bổ không thực sự xảy ra cho đến khi bạn viết một byte vào một trang mới của "RAM" được phân bổ của bạn. Bạn có thể tự chứng minh điều này bằng cách viết và chạy một chương trình C nhỏ như vậy:
// 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 $!
Chạy cái này trên một máy có ít hơn 16GB RAM và, thì đấy, bạn vừa ghi được 16GB bộ nhớ! (không thật sự lắm).
Lưu ý trong top
bạn thấy "VIRT" là 16,004G nhưng% MEM là 0,0
Chạy lại cái này với valgrind:
# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30
Và massif nói "tổng của tất cả allocs () = 16GB". Vì vậy, điều đó không thú vị lắm.
NHƯNG, nếu bạn chạy nó trên một quy trình lành mạnh :
# 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
Và ở đây chúng ta thấy (rất thực nghiệm và với độ tin cậy rất cao) rằng trình biên dịch đã phân bổ 77KB của heap.
Tại sao phải cố gắng rất nhiều để có được chỉ sử dụng heap? Bởi vì tất cả các đối tượng và phần văn bản được chia sẻ mà một quá trình sử dụng (trong ví dụ này, trình biên dịch) không thú vị lắm. Chúng là chi phí liên tục cho một quá trình. Trong thực tế, các yêu cầu tiếp theo của quá trình gần như là "miễn phí".
Ngoài ra, so sánh và đối chiếu như sau:
MMAP () tệp 1GB. VMSize của bạn sẽ là 1 + GB. Nhưng Kích thước cài đặt thường trú của bạn sẽ chỉ là các phần của tệp mà bạn gây ra được phân trang (bằng cách hủy bỏ một con trỏ tới vùng đó). Và nếu bạn "đọc" toàn bộ tệp thì đến khi bạn kết thúc, hạt nhân có thể đã loại bỏ phần bắt đầu (điều này rất dễ thực hiện vì kernel biết chính xác cách thức / nơi để thay thế các trang đó nếu bị hủy bỏ một lần nữa ). Trong cả hai trường hợp, cả VMSize và RSS đều không phải là một chỉ số tốt về "mức sử dụng" bộ nhớ của bạn. Bạn chưa thực sự malloc () 'ed bất cứ điều gì.
Ngược lại, Malloc () và chạm vào NHIỀU bộ nhớ - cho đến khi bộ nhớ của bạn được hoán đổi vào đĩa. Vì vậy, bộ nhớ được phân bổ của bạn bây giờ vượt quá RSS của bạn. Tại đây, VMSize của bạn có thể bắt đầu cho bạn biết điều gì đó (quy trình của bạn sở hữu nhiều bộ nhớ hơn so với những gì thực sự nằm trong RAM của bạn). Nhưng vẫn khó phân biệt giữa VM là các trang được chia sẻ và VM được hoán đổi dữ liệu.
Đây là nơi valgrind / massif trở nên thú vị. Nó cho bạn thấy những gì bạn đã cố ý phân bổ (bất kể trạng thái của các trang của bạn).
htop
tác giả cho một câu hỏi tương tự tôi đã có vào ngày khác ... Cách tính mức sử dụng bộ nhớ từ / Proc / meminfo (như htop)