Linux x86_64 内存
Debugging Memory on Linux | Linux Journal
Kernel memory and User memory
内核内存
由以下组成:
-
Text — 存储程序的只读部分,通常是程序的实际指令代码。同一程序的多个实例可以共享此内存
-
Static Data — 分配已知内存的区域,通常是全局变量和静态C++类。操作系统为程序的每个实例分配此内存区域的副本。
-
Memory Arena (also known as break space) — 动态运行时内存区域。memory arena由heap 和unused memory组成。heap是用户分配内存。heap从低位的内存地址增长到高位内存地址。The heap is where all user-allocated memory is located.
-
Stack — 每当程序进行函数调用时,当前函数的状态需要保存到stack内。Stack从高位内存向地位内存增长。程序的每个实例都有唯一的memory arena和stack。
用户内存
它驻留在memory heap中,供内存例程(memory routines)调用,如malloc(), realloc, free(), callo()。
因此,内存对系统性能很重要,是性能调优最关键之一。
我们有很多工具可以用来测量系统性能,但有时会失败。
比如某生产环境,60G内存、多核CPU、应用压力大,进而产生了数百万个连接,从而造成性能瓶颈。
在这种情况下,运行top
命令肯定不会反映实际内存使用情况。所以,我们不能依赖ps
或top
命令,因为它们报告进程的内存使用情况,因为这是操作系统中运行的唯一进程,但实际上Linux还有一些shared libs的概念,因此当我们在进程上执行ps
或top
来获得使用情况时,它会忽略其他与内存相关的内容,如显示实际内存使用情况的shared/private部分。
提示:
如上,Linux内存的使用是一个复杂问题;使用ps
不能获知准确信息。特别是创建很多相同子进程的程序,比如Java。Ps
命令可能会报告每个Java进程使用100M内存,而实际情况可能是每个Java进程的边际成本是10M内存。
通过
pmap -x $pid
,writeable/private显示内存使用情况。
Linux Philosophy
Linux的理念是,未使用的资源是浪费的资源。因此,内核将使用尽可能多的RAM来缓存本地/远程文件,并随着时间增长。该缓存被系统设定为buffers and pagecache的和。缓存可回收,不是在进程退出时,而是在需要时。即,当启动一个需要大量内存才能运行的进程时,Linux内核将回收存储缓存数据的内存,并将其提供给新进程。
这些缓存不能直接被内核所用:
-
anonymous mmaps, which are not backed by a file but by the swap area.
-
shared memory regions, both System V IPC and POSIX /dev/shm ones.
-
Some application servers and databases (e.g. SAP and Oracle DB) make usage of those shared memory facilities as a very convenient way of sharing data between multiple processes.
虽然 anonymous mmaps 和 shared memory regions 都可以被交换到磁盘,因此,理论上程序可以使用该内存。这种情况会导致性能问题。
因此,如上情况,并非所有报告为“cached”的内存都被统计为available内存。
这与普通缓存不同。普通缓存不是任何正在运行的进程的地址空间的一部分,只是一个内核映射。
比如:
# free -m
total used free shared buffers cached
Mem: 1000 900 100 0 350 350
-/+ buffers/cache: 200 800
本例中,系统仅使用200MB的内存,并有800MB的空闲空间,可在需要时使用(只要没有anonymous memory maps或shared memory regions)。
计算:
Total Physical Memory = 1000 M
Physically Used Memory = 900 M
Actual used memory = 200 M
buffers = 350 M
cached = 350 M
Physically Free Memory = 100 M
Memory free for Applications = 800 M
<Physically Used Memory> = <Actual used memory> + <buffers> + <cache> = 200 + 350 + 350 = 900 M
<Physically Free Memory> = <Total Physical Memory> - <Actual used memory> - <buffers> - <cache> = 1000 - 200 - 350 - 350 = 100 M
<Memory free for Applications> = <Total Physical Memory> - <Actual used memory> = 1000 - 200 = 800 M
<Memory used by Applications> = <Physically Used Memory> - <buffers> - <cache> = 900 - 350 - 350 = 200 M