找回密码
 注册
查看: 4042|回复: 2

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2018-4-23 10:01:33 | 显示全部楼层 |阅读模式
购买主题 本主题需向作者支付 3 金钱 才能浏览

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2018-4-23 10:07:41 | 显示全部楼层
1. 首先,弄清楚dentry_cache的概念及作用:目录项高速缓存,是Linux为了提高目录项对象的处理效率而设计的;它记录了目录项到inode的映射关系。因此,当应用程序发起stat系统调用时,就会创建对应的dentry_cache项(更进一步,如果每次stat的文件都是不存在的文件,那么总是会有大量新的dentry_cache项被创建)。! g. l- v) J$ z1 N# J* X* k" a. _! F
2 R1 {2 j1 E) L# a, Y0 ^
2. 当前服务器是storm集群的节点,首先想到了storm相关的工作进程,strace一下storm的worker进程发现其中有非常频繁的stat系统调用发生,而且stat的文件总是新的文件名:: o; V7 N/ B2 C( I" U- W% a# x

$ c; P4 M8 M: `. ssudo strace -fp <pid> -e trace=stat
% j+ ^3 }3 `7 ?3. 进一步观察到storm的worker进程会在本地目录下频繁的创建、打开、关闭、删除心跳文件,每秒钟一个新的文件名:$ ]4 O( F. M, a9 B$ M$ @

; g+ r+ J' M  J$ _" Fsudo strace -fp <pid> -e trace=open,stat,close,unlink
0 M6 c+ }/ q; @' O8 T以上就是系统中为何有如此多的dentry_cache的原因所在。
+ C2 I$ A8 \. e2 a
- A! f# b( F; Y/ Y& s3 E# [: g一个奇怪的现象
( h1 q5 t$ ^- y1 P" Y% J2 O通过观察/proc/meminfo发现,slab内存分为两部分:4 P/ y" G, m$ v; y0 Z& t
8 \$ f* s  x2 h( Z* X; h6 ]7 j
SReclaimable // 可回收的slab
6 D/ T* E& a3 q. V% G# X) xSUnreclaim // 不可回收的slab
# n+ U4 L/ _* j7 h5 d! U当时服务器的现状是:slab部分占用的内存,大部分显示的都是SReclaimable,也就是说可以被回收的。8 z# Y+ }# p; O* i' l  z
3 K3 v2 @7 E1 ]  B' e
但是通过slabtop观察到slab内存中最主要的部分(dentry_cache)的OBJS几乎都是ACTIVE的,显示100%处于被使用状态。( `2 j- q4 \: _: U) G
/ ]  V3 ^* n" ^% w1 c
  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                  
8 w  M5 Q. \: ^13926348 13926348 100%    0.21K 773686       18   3494744K dentry_cache
' \) `- w/ u; s1 ~! ]334040 262056  78%    0.09K   8351       40     33404K buffer_head" ?. j2 ]$ N$ d- ?0 o
151040 150537  99%    0.74K  30208        5    120832K ext3_inode_cache
' t8 l& n" B5 y3 E# k3 B为什么显示可回收的,但是又处于ACTIVE状态呢?求Linux内核达人看到后热心解释下:(7 O) f, @6 L- X! b& |

% [! J, K5 T5 V会不会由于是ACTIVE状态,导致dcache没有被自动回收释放掉呢?7 x1 b0 e* T2 [2 t4 k
/ r' y; c: n4 X/ c5 M- J/ |/ U
让系统自动回收dcache
% s2 `) X) ^) b上一小节,我们已经提到,服务器上大部分的slab内存是SReclaimable可回收状态的,那么,我们能不能交给操作系统让他在某个时机自动触发回收操作呢?答案是肯定的。6 R- ~6 X0 _1 F/ D7 C

5 A7 o! X  A5 q4 t( J查了一些关于Linux dcache的相关资料,发现操作系统会在到了内存临界阈值后,触发kswapd内核进程工作才进行释放,这个阈值的计算方法如下:  s+ a$ n$ \( i( V  ]3 V. u/ l

+ n: G& }8 j! w4 E( U! ]% J1. 首先,grep low /proc/zoneinfo,得到如下结果:
; `6 x- M% E6 K/ g3 _* B; K; L- j5 i2 E
        low      1; Y3 [: o1 |0 \2 A
        low      380
/ q& \* L6 s* S4 O0 l, u        low      12067# U% d* K+ Z0 f- c# Z! v" w/ U5 `$ q
2. 将以上3列加起来,乘以4KB,就是这个阈值,通过这个方法计算后发现当前服务器的回收阈值只有48MB,因此很难看到这一现象,实际中可能等不到回收,操作系统就会hang住没响应了。
& v6 R  |/ ^9 _1 l% [8 A/ d* s; @, ^. I0 \
3. 可以通过以下方法调大这个阈值:将vm.extra_free_kbytes设置为vm.min_free_kbytes和一样大,则/proc/zoneinfo中对应的low阈值就会增大一倍,同时high阈值也会随之增长,以此类推。
1 Y( C7 F# p+ c  e9 w; [* N2 _6 [& p9 f  ]: ?
$ sudo sysctl -a | grep free_kbytes      
8 @: k2 D6 }/ M) ^vm.min_free_kbytes = 398472 \) d3 k0 M2 _* j, ^7 U" A; `
vm.extra_free_kbytes = 0
# k. E$ e- ]+ G; X$ sudo sysctl -w vm.extra_free_kbytes=836787  ######1GB
9 i1 P. a/ X8 W6 e# ^ 4. 举个例子,当low阈值被设置为1GB的时候,当系统free的内存小于1GB时,观察到kswapd进程开始工作(进程状态从Sleeping变为Running),同时dcache开始被系统回收,直到系统free的内存介于low阈值和high阈值之间,停止回收。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2018-4-23 10:15:54 | 显示全部楼层
如何运行 free
( e6 e/ G: P! X1 U想要运行,只需在控制台输入free 即可。不带选项运行会显示一个以KB为单位的默认输出。, U- D* C: F. e
! `  w) B1 d5 W& t7 n  R+ k7 s
$ free( E5 C6 ?' e/ |4 B7 t# o# b
free默认视图
1 Y7 u5 a- p% ?1 _# s
" g+ @( `4 X( M- e6 D( T5 T4 y从上面的截图我们看到:
9 a2 X' X) v3 j" x+ L" Q8 R
( S0 z4 R$ V( I9 C内存 (以KB计)
) I: _, W. M) |1 [* M% ZTotal(全部) : 1026740
8 q/ n0 R$ U  ?Used(已用) : 8433966 q! Q% b; X$ A% b, G2 U
Free(可用) : 183344
6 w  n, y# S4 A$ V% \0 ~  oShared(共享) : 0* r5 Z2 ?( x. `. P  U8 h* Z
Buffers(块设备缓存区) : 527042 }1 t+ R4 G6 }9 ?; V) j
Cached(文件缓存) : 376384
3 ~+ Q. N* g( R5 P1 H译注:关于Buffers和Cached的区别,来自 http://www.taobaotesting.com/blogs/qa?bid=2265 的一段解释如下:# o. l4 p. U# _4 c" M7 A1 M
% M9 U$ {4 Q. z0 n* }; G
buffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.
# P8 E: q* H7 Q0 T) e
2 X  f* N) L+ L: m9 f( [cached是用来给文件做缓冲。) g% f/ g7 _+ G

: ^) S9 f( n8 V$ H0 \+ p那就是说:buffers是用来存储,目录里面有什么内容,权限等等。而cached直接用来记忆我们打开的文件
* E* }4 B4 k# b8 X0 T1 Y) S; B  z: I  X3 @* E) k
Swap (以KB计)
- [) q' Y" ?# c6 H1 H  d* uTotal(全部) : 1045500
) G( \+ W6 s0 I8 _, w& N8 s2 E( B) W2 DUsed(已用) : 3376+ U9 {' X0 `! m9 k
Free(可用) : 1042124
6 u% O& ?9 ?9 ]6 G当你看见 buffer/cache 的空闲空间低或者 swap 的空闲空间低,说明内存需要升级了。这意味这内存利用率很高。请注意 shared(共享)内存列应该被忽略 ,因为它已经被废弃了。0 ]/ n2 u% }- L" g4 c- Z, n) F

0 s: l6 t" G2 d  y以其它单元显示内存信息7 u% [$ m( W) h: `0 r
如我们先前提到的,默认 free 会以 KB 为单位显示信息。free 同样提供给我们 b (B), -k (KB), -m (MB), -g (GB) and –tera (TB)这些单位。要显示我们想要的单位,只要选择一个并在 free 后面跟上。下面一个是以 MB 为单位的输出样例。7 m0 [. ~- y4 g3 V: d
) d" ~* Y6 S3 T
$ free -m  q/ i  w# ?  Z! n2 i1 C! ~7 s+ z
free命令以MB为单位! h$ m2 z: v& E6 m

$ s4 q  y# }2 N' ]) y' |5 l这个技巧同样适用于-b, -k, -g 以及 –tera 选项。6 Z+ X# M5 t, w& _1 Y6 C6 D

  D9 }* W2 T/ D0 f9 f0 N- f以适于人类可读方式显示内存信息& T! w9 b+ L4 W. N8 z( m! Q* L& ^
free 同样提供了-h选项,这意味着适于人类可读(译注:系统上可能并不存在-h选项,已被-m取代)。那么这与其它的选项有什么不同呢,如-m(MB)选项? 可见的最大不同是-h选项会在数字后面加上适于人类可读的单位。让我们看一个例子。0 f1 u9 r; f+ F/ ~& h+ N

% w" j% b$ w; v$ n$ free -h3 @9 b# t# L( f  G5 l1 l/ b- t
人类可读的free" i! \8 ^8 T; V, w2 o
2 E2 U* r6 ], H8 |/ u
如我们一起看到的,在1,0数字后这里是G(GB)字母。当数字并没有达到GB时,free足够聪明来知道并在每个数字后面跟上合适的单位。后面的M - 数字929告诉我们它有929MB(译注: 原文为929 number tell us its 969 Megabytes,这里应该为输入错误)。8 z" G* p, h4 A( b% C
3 _/ i3 p9 a( ?4 P. B
间隔显示 free- W% H% l: D3 P
作为一个状态检查工具,最好的统计内存利用率的方法是使用延迟间隔。这么做的话,我们可以使用-s选项后面跟上我们想要间隔的N秒数。我们可以在后面合并几个选项来使输出满足我们的需求。假如我们想要每3秒统计一次内存利用率并且适于人类可读,那么就像这样做:$ U4 B9 t. s4 _3 K/ q
8 j- n' u" t* A4 e' ?
$ free -hs 3. ]6 N4 c- U. i& K. y
间隔3s显示free
0 h* Z; C+ K4 q" Z
6 H. e: }" h+ f- t显示高低内存利用率
' }" g( O' u9 j* ~! k6 d如果我们想要知道高低内存统计,我们可以使用-l选项。下面是一个例子。% ^; x0 R; w) F8 U& F2 s

" K% f, R1 M1 k- p5 x6 `$ free -l, v$ j  |6 f# u* b. B( e' O
Free 的 低-高 统计
- G0 o4 k5 s9 b5 r* m8 M' s$ a2 {* C* p  ]% k* s/ S
显示 Linux 全部内存, x) l/ W; e0 g9 \/ I! |1 z
如果我们需要每列的总计信息,我们可以在 free 命令后面跟上 -t 选项。这会在字底部额外加入一行显示。
" I/ [7 i" F5 b) E+ t7 A  q# L  E6 T* o. T
$ free -t
+ J! n; [  Y- S) W0 g' K( x/ sfree命令带总计内存
) x* F" |+ }1 f  I. ]. G5 D7 |  C
8 v( B; n! g% s, F3 |! q总结
6 E0 a& K& e! M$ d( h/ C# O6 O* g' a除了vmstat以外,free 命令也是一个用于统计内存利用率的简单统计工具。用这个你可以快速查看你的 Linux 内存信息。free 命令使用 /proc/meminfo 作为基准来显示内存利用率信息。如往常一样,你可以在控制台下输入 man free 来获取更多关于 free 的信息。
# r# a2 e5 }) o% A
; X5 K4 c* S2 B7 B4 ~& N0 G4 Q 6 r3 s% m: c0 F+ t4 J/ C, }" g
- a, k  l2 |$ V9 a% y" P7 j, t

/ s: n# E: C3 r) Z$ K; s3 m/ R1 L& `& u7 E6 T" L
5 y% C5 e: ^8 Q& x

6 V1 \* E& x$ H1 D- _0 \8 k前段时间有个项目的用C写的,性能测试时发现内存泄露问题。关于怎么观察内存使用问题,free是很好用的一个命令。$ k- c% X, E' B6 w
+ S1 V/ G5 ^4 E. `! u4 I' \
bash-3.00$ free
6 Y% G: S7 K" {) J, y+ U; q) ]$ ~6 R& s1 m3 c
total       used       free     shared    buffers     cached
2 r( |3 Y7 r* {' A0 r. R$ U9 S3 K, F6 i. I5 W0 w
Mem:       1572988    1509260      63728          0      62800     2778881 L: O" B. J% m

. @8 {' @: L  T6 T3 D# ^3 Y( W-/+ buffers/cache:    1168572     404416
/ D- ^3 u  w  V4 \
# o9 a8 l2 b# \* p4 g- {6 k$ ySwap:      2096472      16628    2079844, N1 A7 r2 v6 o5 D$ p. u+ t

9 O2 L: g6 B% G. O3 v6 r* X 4 ^1 p) I1 K, x% \! L

  i$ X$ q9 P7 G; o' Y' ^Mem:表示物理内存统计6 [1 v& r/ _2 ~1 T$ l3 k

0 ]9 [. k) R' q2 K# y7 o6 A3 Q/ q-/+ buffers/cached:表示物理内存的缓存统计, G+ }0 h+ D& D. F! [: Q# l7 g$ z( u
4 m( {# k" `2 z! x& @# ^
Swap:表示硬盘上交换分区的使用情况,这里我们不去关心。5 y- V7 y, J/ x" Q
! J7 N5 Y' D, T/ k9 X
系统的总物理内存:255268Kb(256M),但系统当前真正可用的内存b并不是第一行free 标记的 16936Kb,它仅代表未被分配的内存。
' ?$ O, k' Y$ V) f  G
  Q' E6 I2 Y& p! `/ {7 u第1行 Mem: total:表示物理内存总量。
- r& R+ J" V8 g! }' E4 N2 n
) h# r! M* K5 Y. K2 aused:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。
- v- K" T7 B' }6 u/ Y* E  l6 _* X3 |: M+ p/ q8 }7 `. I
free:未被分配的内存。! L  T6 x9 x3 F  G0 B

. k; w1 P! q4 m( {- kshared:共享内存,一般系统不会用到,这里也不讨论。
  S8 t& ^* T% T' i" ~" O
) l3 p8 X: I; R$ L  T: Tbuffers:系统分配但未被使用的buffers 数量。( E5 l# [* W) Q# r! C$ `

( Q$ J9 [3 j, V+ d9 y+ Acached:系统分配但未被使用的cache 数量。buffer 与cache 的区别见后面。 total = used + free 第2行 -/+ buffers/cached: used:也就是第一行中的used - buffers-cached 也是实际使用的内存总量。 6 e+ F$ r2 o9 [5 ]+ k+ T5 ?( k

+ P0 @3 X  O. ^. l9 P* }+ E0 Z+ kfree:未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。 free 2= buffers1 + cached1 + free1 //free2为第二行、buffers1等为第一行
+ m; p- {; D) Z. I
- f/ u! Q5 \8 U6 F: S9 L$ U. tbuffer 与cache 的区别6 X$ ^9 t3 g( s

  P7 y2 P: L+ A# F: hA 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会很快地被回收。( I- o# t0 J% ~( I+ Q2 B, R4 T8 v
9 C" ~! K3 o9 Z& ~) h0 P
所以从应用程序的角度来说,可用内存=系统free memory+buffers+cached.
. |2 C# J0 @$ ^+ d/ ?7 Q. l3 e& F3 e. l- C) N2 `/ L- q# t
接下来解释什么时候内存会被交换,以及按什么方交换。
* q7 n+ O# A: x  G/ v% _2 z. |5 ~, k" n: y2 p3 W3 V
当可用内存少于额定值的时候,就会开会进行交换.
8 b4 _6 A2 f3 R( Y
+ o! x7 i  b' R$ G2 P* c3 M如何看额定值(RHEL4.0):
' [' m3 h7 n9 S8 g. r/ v
, W2 Y: J$ ?- E# Q#cat /proc/meminfo
% D1 x6 V% J5 Z7 j
- o  {  M+ B+ w0 X交换将通过三个途径来减少系统中使用的物理页面的个数:) M" |# @  Q* s6 i  f4 l" t

. O# b8 p& l$ W( @% g0 n1 G2 u1.减少缓冲与页面cache的大小,5 o* T- s- p8 I9 O; X2 h9 P. H

" T; E" |$ z+ ^2.将系统V类型的内存页面交换出去,) D! b; M$ K' }; q

7 {  A5 m$ g5 \* H3.换出或者丢弃页面。(Application 占用的内存页,也就是物理内存不足)。
! t2 ~& u) R3 T! C
& n6 R8 Q' ~/ @, P' \) f1 U事实上,少量地使用swap是不是影响到系统性能的。  P  N. o5 V7 U/ J$ j) J

; ~- C6 h) c7 M/ T0 h下面是buffers与cached的区别。
' R$ N: N& E/ d) @1 B* p* H, ?$ Q" @8 `. v$ r" ]$ s* S  _
buffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.
# x3 I1 N1 h# H9 ]& n$ P* k
! j' @# w  Y# O6 ~' W% X) Hcached是用来给文件做缓冲。: F/ o! `) H6 v8 l
; |3 p$ L$ M. ]# b: A
那就是说:buffers是用来存储,目录里面有什么内容,权限等等。% `9 i7 d% ~6 P6 T" C! e$ ^/ h
6 q% w3 w- u$ ?9 _, b% Y" _3 `
而cached直接用来记忆我们打开的文件,如果你想知道他是不是真的生效,你可以试一下,先后执行两次命令#man X ,你就可以明显的感觉到第二次的开打的速度快很多。
( {& `; q- m& x5 |, [! M
7 q2 |" k- {5 {5 V/ O$ C1 K# ?实验:在一台没有什么应用的机器上做会看得比较明显。记得实验只能做一次,如果想多做请换一个文件名。
8 J0 e( n" S- a; o: u; v  P* M/ r. ]& p8 g
#free3 x! F+ \8 W$ v( j

/ @0 z3 y) [- {0 q: y( y# R2 J# t#man X
( p  K/ S  }; t9 p. S* d, ~6 B; J& @6 o7 J1 i
#free0 X: \' h& ]/ I5 Z: h: f' A3 ]

+ F! V4 G5 e2 c8 j/ s) l! u#man X
1 J2 i$ Y. e2 z7 |
  z1 b8 z- ]( Q# p$ b#free
, Z7 r$ t7 T: f( b" G
- [; F' ?) O, w; Z; @% @你可以先后比较一下free后显示buffers的大小。$ U. e- z8 A; U) h1 N
4 ?6 s% g# K  Z0 m; n. S
另一个实验:
9 N9 p. j' Y* h3 z
8 [4 e8 q; j9 S( ]#free
* G, p- F- n! O' u# m3 y6 l% H. c; F; j7 N
#ls /dev. }) d! l% ^, \2 ^7 |7 s

8 [; U) j9 i+ Q5 q#free
7 S; K" ?% Y8 v8 X6 g9 w: d3 k% a  s/ i: v2 ~0 N8 T
你比较一下两个的大小,当然这个buffers随时都在增加,但你有ls过的话,增加的速度会变得快,这个就是buffers/chached的区别。
1 G( A6 ~/ m5 u  c4 W/ a! Q) m* Q) A
8 I; Q* A3 p! n% [2 E& [因为Linux将你暂时不使用的内存作为文件和数据缓存,以提高系统性能,当你需要这些内存时,系统会自动释放(不像windows那样,即使你有很多空闲内存,他也要访问一下磁盘中的pagefiles), r  i! u' {, ]4 u4 Y
, K% p) {% X* E9 N0 i/ d! U
使用free命令" m' S% }% z( f9 m! c) ]* Z
$ h4 l# I7 t# @
将used的值减去   buffer和cache的值就是你当前真实内存使用 ————– 对操作系统来讲是Mem的参数.buffers/cached 都是属于被使用,所以它认为free只有16936.
- e( }3 Y. p( {* V: v- _
* y; T+ m3 M2 L0 o; Y& x9 f* F对应用程序来讲是(-/+ 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看 内存是否够用的标准哦.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-12 03:03 , Processed in 0.020490 second(s), 25 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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