易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 4038|回复: 2
收起左侧

Linux内存中的Cache真的能被回收么?

[复制链接]
发表于 2018-4-23 10:01:33 | 显示全部楼层 |阅读模式
购买主题 本主题需向作者支付 3 金钱 才能浏览
 楼主| 发表于 2018-4-23 10:07:41 | 显示全部楼层
1. 首先,弄清楚dentry_cache的概念及作用:目录项高速缓存,是Linux为了提高目录项对象的处理效率而设计的;它记录了目录项到inode的映射关系。因此,当应用程序发起stat系统调用时,就会创建对应的dentry_cache项(更进一步,如果每次stat的文件都是不存在的文件,那么总是会有大量新的dentry_cache项被创建)。" H7 o+ \& ~, w

  b4 L7 A; q8 c' o0 x; [  {, y2. 当前服务器是storm集群的节点,首先想到了storm相关的工作进程,strace一下storm的worker进程发现其中有非常频繁的stat系统调用发生,而且stat的文件总是新的文件名:) K8 c: }. d$ Y( ]& z: o- g

% ~+ Z% }- }* h) @0 s& a  ~sudo strace -fp <pid> -e trace=stat
! Z1 t/ h# z& x3. 进一步观察到storm的worker进程会在本地目录下频繁的创建、打开、关闭、删除心跳文件,每秒钟一个新的文件名:* n- n. t3 v; m& C
# W! r, N! a$ S2 A
sudo strace -fp <pid> -e trace=open,stat,close,unlink
* N* F6 n1 N6 N% U& o以上就是系统中为何有如此多的dentry_cache的原因所在。
7 S0 {. y! R9 A! G: b! n  |& N( R$ D
一个奇怪的现象
( q( O% ]1 n% ?6 x5 Z$ V# N. |) d. [通过观察/proc/meminfo发现,slab内存分为两部分:, m% d( I- h- ]4 K/ ?5 j7 j
2 P/ t7 \" E/ w- m
SReclaimable // 可回收的slab& y4 B9 b( k, ]
SUnreclaim // 不可回收的slab; G6 i5 V) T$ |9 H* O
当时服务器的现状是:slab部分占用的内存,大部分显示的都是SReclaimable,也就是说可以被回收的。
2 ]* m* z* J, r2 U# F! m% j+ }2 i7 A
但是通过slabtop观察到slab内存中最主要的部分(dentry_cache)的OBJS几乎都是ACTIVE的,显示100%处于被使用状态。5 J0 ~8 X7 x8 o9 Y% x. J% r5 G! d8 |
4 E8 ?& @: J: G; M/ y* g& T& i
  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   / P- ~7 \0 M& k4 ^/ V- P
13926348 13926348 100%    0.21K 773686       18   3494744K dentry_cache
. P8 V% u& d" q) g) p9 \334040 262056  78%    0.09K   8351       40     33404K buffer_head
" a( P8 h& k& V8 P151040 150537  99%    0.74K  30208        5    120832K ext3_inode_cache+ Y) ]( L% S. J! }
为什么显示可回收的,但是又处于ACTIVE状态呢?求Linux内核达人看到后热心解释下:(
: n9 z- m& W1 T6 O0 P! y3 }3 }, _2 |1 f1 r" ^% ]9 c; ^
会不会由于是ACTIVE状态,导致dcache没有被自动回收释放掉呢?' d0 u5 u4 }" c7 m- w$ U- D
2 B, z) d, `% @0 f( K" i
让系统自动回收dcache7 F- P) X9 S% E# ?. l! u# }7 E
上一小节,我们已经提到,服务器上大部分的slab内存是SReclaimable可回收状态的,那么,我们能不能交给操作系统让他在某个时机自动触发回收操作呢?答案是肯定的。
) }& {  I5 x, B* o$ U: ?
9 A4 X$ r* i+ l查了一些关于Linux dcache的相关资料,发现操作系统会在到了内存临界阈值后,触发kswapd内核进程工作才进行释放,这个阈值的计算方法如下:) Z0 I7 ?9 l. a3 A3 m# G

8 N  }; e  M" h1. 首先,grep low /proc/zoneinfo,得到如下结果:
: r( |. x- q; C0 p2 n2 G& M& h  W; ^
        low      1
; c( f2 S9 {- N$ H% f7 p4 Q        low      380
1 H/ ~! r" k6 V) p        low      12067
5 |1 h! q: |# ?1 [/ H2. 将以上3列加起来,乘以4KB,就是这个阈值,通过这个方法计算后发现当前服务器的回收阈值只有48MB,因此很难看到这一现象,实际中可能等不到回收,操作系统就会hang住没响应了。
0 C, w" _; n) x2 N3 O# @7 ~# G7 w6 Z6 x7 e8 N7 H8 h
3. 可以通过以下方法调大这个阈值:将vm.extra_free_kbytes设置为vm.min_free_kbytes和一样大,则/proc/zoneinfo中对应的low阈值就会增大一倍,同时high阈值也会随之增长,以此类推。# A, S% k3 ]! ]" W) K
9 k5 E. Q, C& x; D
$ sudo sysctl -a | grep free_kbytes       ' H4 Q1 b7 G, i# U
vm.min_free_kbytes = 39847
8 k8 }& c( m9 `! q$ j3 Cvm.extra_free_kbytes = 08 e2 k9 p7 u2 o$ H9 q7 `
$ sudo sysctl -w vm.extra_free_kbytes=836787  ######1GB
1 c  P$ X# f* h 4. 举个例子,当low阈值被设置为1GB的时候,当系统free的内存小于1GB时,观察到kswapd进程开始工作(进程状态从Sleeping变为Running),同时dcache开始被系统回收,直到系统free的内存介于low阈值和high阈值之间,停止回收。
 楼主| 发表于 2018-4-23 10:15:54 | 显示全部楼层
如何运行 free6 b0 `" p5 ?7 l
想要运行,只需在控制台输入free 即可。不带选项运行会显示一个以KB为单位的默认输出。
* N2 R& [  x6 F2 ^) ?6 W4 m- Z$ D9 N) T0 l3 r4 `0 M# k
$ free! S6 X' h$ n( ^
free默认视图
! p8 O1 O1 ~5 N) |/ C9 O$ M
" G8 P3 S; [" K; ?3 A从上面的截图我们看到:
! [3 y, b  [! @% a9 o; x; `5 Q  Z+ l$ x  c* U- G2 `: A' ~5 ~# K
内存 (以KB计)
0 h( C, @, W3 K, Y, ATotal(全部) : 1026740; W" y. ^& b6 }+ H) }9 n, w
Used(已用) : 843396+ z7 F! Q! F: p. I
Free(可用) : 183344
7 t/ B1 a- J" DShared(共享) : 0+ M6 X4 E9 B7 @& L$ s
Buffers(块设备缓存区) : 52704
* D% N' q7 N1 f5 G* TCached(文件缓存) : 376384: `% [9 a" F! }6 i
译注:关于Buffers和Cached的区别,来自 http://www.taobaotesting.com/blogs/qa?bid=2265 的一段解释如下:
3 g' J3 k/ s* l: l
$ c0 H' T4 a6 h' g) d: \6 cbuffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.
& h' O  F; k; u; J
6 C! \- x, S5 _# ]) D2 S8 u1 ~cached是用来给文件做缓冲。; \8 j9 L) }; |& ?! ]+ }

3 l3 C% T9 Q/ ~6 A1 G! N那就是说:buffers是用来存储,目录里面有什么内容,权限等等。而cached直接用来记忆我们打开的文件
. [. L" C3 M* O( I% P4 r1 c
5 Z4 u0 u2 W; j  p0 `1 ]Swap (以KB计)& W5 j) ^0 O& K3 `: c
Total(全部) : 1045500  F7 i( C1 ?# y) V* c) J& K) E
Used(已用) : 33767 L5 L+ Z9 E% m) m) p; R
Free(可用) : 1042124
( [1 L: H1 V* i4 C$ u当你看见 buffer/cache 的空闲空间低或者 swap 的空闲空间低,说明内存需要升级了。这意味这内存利用率很高。请注意 shared(共享)内存列应该被忽略 ,因为它已经被废弃了。
! w0 f/ T1 B/ w/ M3 e1 J" k6 _" r' ~! K
以其它单元显示内存信息
) ~  b7 v% M/ E) G$ ^* i6 a# B如我们先前提到的,默认 free 会以 KB 为单位显示信息。free 同样提供给我们 b (B), -k (KB), -m (MB), -g (GB) and –tera (TB)这些单位。要显示我们想要的单位,只要选择一个并在 free 后面跟上。下面一个是以 MB 为单位的输出样例。- p: q- _/ c9 t& s! S6 T
: b6 ^( G% I7 I, U* W
$ free -m
4 j4 |& b" i3 S5 Bfree命令以MB为单位
& s" r/ f. M2 b3 m0 [- H
; c- w) N/ [  T这个技巧同样适用于-b, -k, -g 以及 –tera 选项。9 t# @: M7 w' K: t. L* H) [
6 z! ~7 K, u, f  c1 V
以适于人类可读方式显示内存信息
, N- S- Y: x. H1 r* ?% T6 f0 i; pfree 同样提供了-h选项,这意味着适于人类可读(译注:系统上可能并不存在-h选项,已被-m取代)。那么这与其它的选项有什么不同呢,如-m(MB)选项? 可见的最大不同是-h选项会在数字后面加上适于人类可读的单位。让我们看一个例子。- U/ o$ b$ g  d0 N2 c" F
/ X7 }8 \3 z) u$ p9 b) R# w
$ free -h& ^6 u: E* s* t: I
人类可读的free
6 ?, X6 D/ r6 i! |; h/ ]( s: P$ b) X1 e) d* @
如我们一起看到的,在1,0数字后这里是G(GB)字母。当数字并没有达到GB时,free足够聪明来知道并在每个数字后面跟上合适的单位。后面的M - 数字929告诉我们它有929MB(译注: 原文为929 number tell us its 969 Megabytes,这里应该为输入错误)。1 O  `5 @& @9 s* [' o

: U9 N2 t" n9 r7 f, ^3 ]间隔显示 free
4 J) ]1 R: l1 @6 V作为一个状态检查工具,最好的统计内存利用率的方法是使用延迟间隔。这么做的话,我们可以使用-s选项后面跟上我们想要间隔的N秒数。我们可以在后面合并几个选项来使输出满足我们的需求。假如我们想要每3秒统计一次内存利用率并且适于人类可读,那么就像这样做:% F) Z. \! a' Q# O

+ \" l5 k, X* M6 l3 H$ Y$ free -hs 3# w, R0 [9 ~0 o0 U
间隔3s显示free$ X+ W' T# y/ y( q

7 @& _: ]$ B6 Y" f3 s3 L& r( V" ^显示高低内存利用率; C& g: v4 D( _  |( d" r" X
如果我们想要知道高低内存统计,我们可以使用-l选项。下面是一个例子。, R7 l7 L. g0 c# r
4 y5 K& g8 `- i* `3 ]4 B& N4 j/ R
$ free -l
& @* {$ }6 k5 C! p: K; \' Z% sFree 的 低-高 统计4 N# h5 \6 i" G& s
2 z9 N& C  A2 c2 t( R
显示 Linux 全部内存
# _/ ~2 V- Z9 j0 Z8 U" j) Y6 C如果我们需要每列的总计信息,我们可以在 free 命令后面跟上 -t 选项。这会在字底部额外加入一行显示。" N7 D* t- G5 @0 y3 z$ w" u
5 G3 f) o1 B/ f" V# f4 S
$ free -t6 \& b: n" p; E7 B* |& B5 e/ n+ }
free命令带总计内存
: l: m1 u1 y9 {& S9 {5 D, ~3 E/ E# v& b
总结
6 C" }0 r/ |, V$ O除了vmstat以外,free 命令也是一个用于统计内存利用率的简单统计工具。用这个你可以快速查看你的 Linux 内存信息。free 命令使用 /proc/meminfo 作为基准来显示内存利用率信息。如往常一样,你可以在控制台下输入 man free 来获取更多关于 free 的信息。
) o  E( J( j6 S2 d# {$ }9 T* G* b" V; |/ y5 w

' R6 o0 s- s6 B8 B5 h6 e
# G. m+ T' A/ I  l5 j6 h* U5 G) [/ K + t9 j- O4 o1 J1 s

6 Y( z0 T2 T* C1 T. N, J3 j8 ? - b0 j4 g+ t1 ^0 M5 ?$ ^

1 i+ G( q* C; s0 E5 r% m1 n前段时间有个项目的用C写的,性能测试时发现内存泄露问题。关于怎么观察内存使用问题,free是很好用的一个命令。6 p0 r; X- c8 f$ ^
- Q; \/ N7 q  \1 Q3 M5 p0 \/ Q* p
bash-3.00$ free
: `! Y  f9 p! W. s0 [
$ @  V- V) x: W! E4 atotal       used       free     shared    buffers     cached: ]9 w3 Z% [7 C
* B# i  s) H8 n$ v) ]3 }$ u; H# S
Mem:       1572988    1509260      63728          0      62800     277888
; {. @4 a! O0 l6 o8 k9 a9 L% I" @2 y9 x5 `! A) S. o/ @8 Y: X
-/+ buffers/cache:    1168572     404416' U, ?9 l- t  U( t( x% n4 x6 p
% R7 D* i( e* F1 R+ z1 X; }
Swap:      2096472      16628    2079844
5 t8 U' U1 c) I$ J7 N
4 f; o+ Z5 n9 x' {+ P
& _% m  ~1 Q6 T8 i* D1 K! A
, J  ^4 C  X" T$ L! V- ~Mem:表示物理内存统计3 |7 U! f! J3 g* o

* i1 z' {- H: h-/+ buffers/cached:表示物理内存的缓存统计
# _6 ~  d! u% E; B5 M2 W& m/ r3 E
- |( i! ^$ Q0 y+ G) j% s+ [1 sSwap:表示硬盘上交换分区的使用情况,这里我们不去关心。
5 M! Y2 U# c7 D
; s/ V' F- t8 F" s系统的总物理内存:255268Kb(256M),但系统当前真正可用的内存b并不是第一行free 标记的 16936Kb,它仅代表未被分配的内存。
& `; }* s0 T% b/ J0 W3 D3 d% _4 m' f' X: h& {$ P
第1行 Mem: total:表示物理内存总量。2 [" q. _2 l% g3 a2 O) m; v

5 e. t# M7 I3 B) bused:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。
8 `* _' e4 o/ j) v+ E" s3 x5 l! ?1 K% B* r( H% L
free:未被分配的内存。+ t3 h) V- ^2 M7 n+ X. y

: `$ R& j+ h( w$ Mshared:共享内存,一般系统不会用到,这里也不讨论。
- C; u+ d" T* c& P8 Y9 H* H! c$ V4 }9 q; g* e5 a4 t3 s' B- w3 b
buffers:系统分配但未被使用的buffers 数量。
4 G, p2 ]! @+ t0 b/ j+ f6 Y
& P, K+ k: S, k0 Acached:系统分配但未被使用的cache 数量。buffer 与cache 的区别见后面。 total = used + free 第2行 -/+ buffers/cached: used:也就是第一行中的used - buffers-cached 也是实际使用的内存总量。 / Z3 }: G9 N2 l2 c9 L; A

$ Q' {. c( K; V! |6 @free:未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。 free 2= buffers1 + cached1 + free1 //free2为第二行、buffers1等为第一行
# n0 k% S0 L+ H/ P8 z9 U( n; E) V
$ ]& d( M" c. x/ t9 hbuffer 与cache 的区别
  R7 ^- g( y/ h8 A
: c! K, @& |! h1 ?A buffer is something that has yet to be “written” to disk. A cache is something that has been “read” from the disk and stored for later use 第3行: 第三行所指的是从应用程序角度来看,对于应用程序来说,buffers/cached 是等于可用的,因为buffer/cached是为了提高文件读取的性能,当应用程序需在用到内存的时候,buffer/cached会很快地被回收。& f7 J% o! B3 }% `& R4 \6 ~
: s6 q3 Y$ \0 @- Q$ M; }4 `
所以从应用程序的角度来说,可用内存=系统free memory+buffers+cached.' r/ @/ ~0 t4 K+ I, _. L* m
- g# a- B* G2 x1 `
接下来解释什么时候内存会被交换,以及按什么方交换。
: ^& i; @& @" ^+ H4 a# u1 i) n) }/ _1 A. w: E
当可用内存少于额定值的时候,就会开会进行交换.
( [# x8 o% u# r! ?9 m: q1 B0 W3 u' m- ]: @4 O+ V5 t/ V
如何看额定值(RHEL4.0):
9 s" ^( o1 ^" `. W0 Z6 e9 ~  h5 ~- |7 e: W
#cat /proc/meminfo
, q6 u* q, D9 t' T4 y
9 C/ X; w% {: h6 a0 g交换将通过三个途径来减少系统中使用的物理页面的个数:( F" ?; b) ], M
' `& ?& n/ Y2 Q, r3 f9 e
1.减少缓冲与页面cache的大小,
0 x/ M8 r& M' U. J3 T& p: {, E" c- N0 Y- X! v% W( Y
2.将系统V类型的内存页面交换出去,
) W( H# D: p; e% }& c# Q& P: o; K* b) x# s
3.换出或者丢弃页面。(Application 占用的内存页,也就是物理内存不足)。- M  [% h- v) c

* b9 i) q+ Y+ ?事实上,少量地使用swap是不是影响到系统性能的。
( r" P' d: B- k; d) p; ~; |: N) h( |. ~; {6 e
下面是buffers与cached的区别。
4 A* R- o8 o0 r4 _$ M" F5 s4 C9 U7 t1 o
buffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.
. H% A' K$ q4 Q4 C
, T6 g) d2 f" X. fcached是用来给文件做缓冲。# R" V. Z3 o1 [
# D+ S( Y$ o! n* Y1 k
那就是说:buffers是用来存储,目录里面有什么内容,权限等等。
3 l1 T. c. ^2 I2 r" f( G5 g% A6 g+ r( x0 ?
而cached直接用来记忆我们打开的文件,如果你想知道他是不是真的生效,你可以试一下,先后执行两次命令#man X ,你就可以明显的感觉到第二次的开打的速度快很多。
# p5 J$ g6 V/ G" `
2 a$ x% u, C+ l. H: e" G实验:在一台没有什么应用的机器上做会看得比较明显。记得实验只能做一次,如果想多做请换一个文件名。
7 \1 _3 r" M; F& N5 z* g
/ X: @( f6 Q' S; K- T; z#free
) b* }6 T0 S5 p. }: O1 U
( A( T( c5 Q  |% U( g8 P" l  O& g#man X) f0 i" `5 z9 ~  E
' n1 s8 q2 [) x: G3 L/ o4 L1 E
#free
0 x0 o- e% @) H1 c; `# ]
8 a1 m$ d0 {0 `) B# Y; @6 b+ \) e: F/ \#man X8 W; e! b7 L! P9 q" d: O  d
3 L4 j; X7 l2 W1 c+ e4 [
#free/ \7 p6 D  u. x/ p$ b- }- [
, U( n$ ~( X% C  b( e" L7 A
你可以先后比较一下free后显示buffers的大小。/ [' p) E9 t- }6 ?: ]' t5 z& e
0 |0 o, X7 E5 ^7 q
另一个实验:; ~- ^) H1 T6 T
- i5 V" H9 B  K
#free& [' }; S7 U" f
  [2 Z# t; X' }/ ~! V  D
#ls /dev
5 F- [% \% i3 m9 r& t
5 a" F2 @  {+ k4 k- r7 G#free
% a" K* m3 y$ l/ m  f9 ^3 F2 x2 I
/ q& G1 K; F/ v/ c你比较一下两个的大小,当然这个buffers随时都在增加,但你有ls过的话,增加的速度会变得快,这个就是buffers/chached的区别。
2 y8 k* j9 }, a3 W" y. J2 u% h& E$ q8 m1 Y
因为Linux将你暂时不使用的内存作为文件和数据缓存,以提高系统性能,当你需要这些内存时,系统会自动释放(不像windows那样,即使你有很多空闲内存,他也要访问一下磁盘中的pagefiles)
* \$ F; Z  g& @- [) X! V+ y/ r  l6 u5 v% W  a
使用free命令  ]; D0 ~0 t/ E4 D- c3 ~1 W
( J" y7 T2 @* U: A
将used的值减去   buffer和cache的值就是你当前真实内存使用 ————– 对操作系统来讲是Mem的参数.buffers/cached 都是属于被使用,所以它认为free只有16936.( }& K/ u' Q) k  E# q0 s+ g+ K
: f! q) N6 j9 O
对应用程序来讲是(-/+ buffers/cach).buffers/cached 是等同可用的,因为buffer/cached是为了提高 程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。 所以,以应用来看看,以(-/+ buffers/cache)的free和used为主.所以我们看这个就好了.另外告诉大家 一些常识.Linux为了提高磁盘和内存存取效率, Linux做了很多精心的设计, 除了对dentry进行缓存(用于 VFS,加速文件路径名到inode的转换), 还采取了两种主要Cache方式:Buffer Cache和Page Cache。 前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache能有效缩短了 I/O系统调用(比如read,write,getdents)的时间。 记住内存是拿来用的,不是拿来看的.不象windows,无论你的真实物理内存有多少,他都要拿硬盘交换 文件来读.这也就是windows为什么常常提示虚拟空间不足的原因.你们想想,多无聊,在内存还有大部分 的时候,拿出一部分硬盘空间来充当内存.硬盘怎么会快过内存.所以我们看linux,只要不用swap的交换 空间,就不用担心自己的内存太少.如果常常swap用很多,可能你就要考虑加物理内存了.这也是linux看 内存是否够用的标准哦.
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )点击这里给我发消息

GMT+8, 2026-4-8 23:57 , Processed in 0.066540 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

快速回复 返回顶部 返回列表