易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 4037|回复: 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项被创建)。
+ |8 }' {, b$ q( |( H4 \) }, y' R8 j# D* w7 u/ w1 E# F3 W' H
2. 当前服务器是storm集群的节点,首先想到了storm相关的工作进程,strace一下storm的worker进程发现其中有非常频繁的stat系统调用发生,而且stat的文件总是新的文件名:+ Y3 R& b# ~$ a% `

8 |3 T% J' Z% r+ c+ csudo strace -fp <pid> -e trace=stat
3 ^7 M0 {/ p) F3. 进一步观察到storm的worker进程会在本地目录下频繁的创建、打开、关闭、删除心跳文件,每秒钟一个新的文件名:
7 U) r, Q3 K1 M3 @, F" n
  i! O/ B/ b" O- Z, w6 o6 a4 ssudo strace -fp <pid> -e trace=open,stat,close,unlink) \8 M# P8 Q4 P7 I) M& m7 m
以上就是系统中为何有如此多的dentry_cache的原因所在。/ c& v7 p0 j8 ^. P% n
; r; M. q6 f+ u: A; l$ ]- r
一个奇怪的现象, ^; {) a! X( J' _" s" |  ]" f1 l! ^; x
通过观察/proc/meminfo发现,slab内存分为两部分:
$ W3 |7 ~' p$ Y0 j, n8 v/ ^! L
SReclaimable // 可回收的slab
" O3 k2 t! q0 j8 C$ v% v) q+ ]/ V' d: eSUnreclaim // 不可回收的slab
  K4 E+ M! R; _' t当时服务器的现状是:slab部分占用的内存,大部分显示的都是SReclaimable,也就是说可以被回收的。* i( w9 k4 Z/ O

  s6 u8 l9 k! F3 d/ m, P7 Q' g) [但是通过slabtop观察到slab内存中最主要的部分(dentry_cache)的OBJS几乎都是ACTIVE的,显示100%处于被使用状态。, y8 t1 ]& h" I1 J3 ]

5 I0 P& Z1 \3 O# P  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                  
4 |5 _9 f( v8 m) m- f) z, q13926348 13926348 100%    0.21K 773686       18   3494744K dentry_cache1 h, O  d  i  E1 M! N; |+ ]
334040 262056  78%    0.09K   8351       40     33404K buffer_head
% \( }2 o6 J/ S6 i/ u3 t, C7 R151040 150537  99%    0.74K  30208        5    120832K ext3_inode_cache# h: \$ ?1 N7 \  }( k9 }
为什么显示可回收的,但是又处于ACTIVE状态呢?求Linux内核达人看到后热心解释下:(
. F- v. e1 D: }/ J1 |2 o6 h$ Y7 p9 ^! P
会不会由于是ACTIVE状态,导致dcache没有被自动回收释放掉呢?
, n. E* r2 P" I" @5 ~) l$ _  G& D& R4 i  W8 V9 \( Z# a6 y1 V
让系统自动回收dcache+ v7 y: A0 Y; `8 G$ G" }2 O9 O! N
上一小节,我们已经提到,服务器上大部分的slab内存是SReclaimable可回收状态的,那么,我们能不能交给操作系统让他在某个时机自动触发回收操作呢?答案是肯定的。6 T* [8 u; }) S# |

" l$ C: j- h8 y  `) a8 C查了一些关于Linux dcache的相关资料,发现操作系统会在到了内存临界阈值后,触发kswapd内核进程工作才进行释放,这个阈值的计算方法如下:, g2 N4 R$ H2 @7 Q

/ ~3 Z. ^; s6 A+ t1. 首先,grep low /proc/zoneinfo,得到如下结果:1 |7 o3 y6 ]* ]( t( e* Q
( _; |# d) W+ G0 p
        low      1( ]: f$ p) r# {+ |" p, t1 n1 H
        low      380/ X2 ~) m/ O7 R% n% h
        low      12067
) R1 u& ~2 q$ |4 Y- M7 f6 V2. 将以上3列加起来,乘以4KB,就是这个阈值,通过这个方法计算后发现当前服务器的回收阈值只有48MB,因此很难看到这一现象,实际中可能等不到回收,操作系统就会hang住没响应了。  A- C( _. z$ x9 A, g
4 g$ Q( y6 P0 \/ {, o# l4 B
3. 可以通过以下方法调大这个阈值:将vm.extra_free_kbytes设置为vm.min_free_kbytes和一样大,则/proc/zoneinfo中对应的low阈值就会增大一倍,同时high阈值也会随之增长,以此类推。
# M+ d5 _' {+ T; q
. j, F2 u2 m; d) q2 T$ sudo sysctl -a | grep free_kbytes       ( b# T# D$ ?/ f0 k
vm.min_free_kbytes = 398470 V5 {5 K+ [4 N4 Y' b+ Y' b* I
vm.extra_free_kbytes = 0
( G8 L  M/ r2 O# [3 t' F/ B! v( Q7 e$ b$ sudo sysctl -w vm.extra_free_kbytes=836787  ######1GB
# N' x4 h8 B: ^& [  A9 {+ T 4. 举个例子,当low阈值被设置为1GB的时候,当系统free的内存小于1GB时,观察到kswapd进程开始工作(进程状态从Sleeping变为Running),同时dcache开始被系统回收,直到系统free的内存介于low阈值和high阈值之间,停止回收。
 楼主| 发表于 2018-4-23 10:15:54 | 显示全部楼层
如何运行 free
; i' d8 q7 ^  Z7 y; ~想要运行,只需在控制台输入free 即可。不带选项运行会显示一个以KB为单位的默认输出。  v" m8 c( L+ P+ `2 m$ g
, ?  d" B5 e9 s! [
$ free" E1 N, J: V: O6 D2 [3 p
free默认视图; t  w# t% |* S: o5 v3 }
9 C7 u+ V* T' w: q: y
从上面的截图我们看到:/ V2 s. f3 \0 l0 w% h

+ |5 g( n9 K7 r2 ?! b内存 (以KB计)
6 f" @: {# w, jTotal(全部) : 1026740) }( ~2 U7 |; X3 U
Used(已用) : 843396/ E% a, Q! T' j; ?6 r
Free(可用) : 183344
% Y1 z: p# b1 z" i" M2 ?$ RShared(共享) : 0' h8 M7 ^  O* A8 ]( E$ L, ~
Buffers(块设备缓存区) : 52704
; `, k3 x* W- V, M! F; }6 ]Cached(文件缓存) : 376384
$ N5 L8 K+ ?0 a0 b译注:关于Buffers和Cached的区别,来自 http://www.taobaotesting.com/blogs/qa?bid=2265 的一段解释如下:0 j+ \5 q* e+ q3 F3 Z% B

% w1 s  Z; L; h! h3 ybuffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.; r+ j8 }! V: k) u( ]6 ]$ }4 |
+ r7 }, R& k+ e4 i5 Y% x+ a, m
cached是用来给文件做缓冲。8 j9 d! f" J" S. g7 `

3 b1 Y. {1 g8 A; Z3 y6 d那就是说:buffers是用来存储,目录里面有什么内容,权限等等。而cached直接用来记忆我们打开的文件7 _4 l: K' R: u& O

" l7 V4 O( o4 F1 ^$ M3 bSwap (以KB计). y# X2 J! c& z( n" x0 H
Total(全部) : 1045500, Z1 J4 c: F: H/ M+ p# x  N- ?# y
Used(已用) : 3376
4 f% M) _9 a" Y; U0 B8 T) KFree(可用) : 10421249 ]1 W% t& n' F6 m0 x! L
当你看见 buffer/cache 的空闲空间低或者 swap 的空闲空间低,说明内存需要升级了。这意味这内存利用率很高。请注意 shared(共享)内存列应该被忽略 ,因为它已经被废弃了。  h2 l& h& N7 E% @4 y

5 ^3 V8 x7 h! Y: V' @4 G以其它单元显示内存信息
" `+ h& s- r# Y9 V) ?: Z如我们先前提到的,默认 free 会以 KB 为单位显示信息。free 同样提供给我们 b (B), -k (KB), -m (MB), -g (GB) and –tera (TB)这些单位。要显示我们想要的单位,只要选择一个并在 free 后面跟上。下面一个是以 MB 为单位的输出样例。
8 ^! p8 n# F! V! u5 W( O8 s2 s; x- V6 D: F: c0 O
$ free -m
9 U' I: d6 l( Q% ^free命令以MB为单位9 i2 v& b. y+ }% e

* t* J" Z/ H% t" l2 R9 t这个技巧同样适用于-b, -k, -g 以及 –tera 选项。; p# A! g2 K7 h% f( d

. z- h! F, Z% r% M! r: w以适于人类可读方式显示内存信息! N/ y, @  ~; W' y/ u, N: K
free 同样提供了-h选项,这意味着适于人类可读(译注:系统上可能并不存在-h选项,已被-m取代)。那么这与其它的选项有什么不同呢,如-m(MB)选项? 可见的最大不同是-h选项会在数字后面加上适于人类可读的单位。让我们看一个例子。2 ]9 ^3 S9 a1 y

% q" G. ^/ q, W5 P- a) g: b$ free -h+ U7 S& u- I# o3 D6 `  _/ W5 z
人类可读的free# X9 [  s& Q0 j  n6 v
( R" Y- E$ l% A) `
如我们一起看到的,在1,0数字后这里是G(GB)字母。当数字并没有达到GB时,free足够聪明来知道并在每个数字后面跟上合适的单位。后面的M - 数字929告诉我们它有929MB(译注: 原文为929 number tell us its 969 Megabytes,这里应该为输入错误)。) N1 \( j' C: N- j

7 F2 D' ?# x" m9 \! ?2 Y+ a( X间隔显示 free
) _9 w  f: I- U2 C4 x( H& l: n作为一个状态检查工具,最好的统计内存利用率的方法是使用延迟间隔。这么做的话,我们可以使用-s选项后面跟上我们想要间隔的N秒数。我们可以在后面合并几个选项来使输出满足我们的需求。假如我们想要每3秒统计一次内存利用率并且适于人类可读,那么就像这样做:
" C% ~+ l/ Y& v" _
  Y, N/ I8 J/ B1 X1 _) p& J" \7 a$ free -hs 3
* I! a0 [1 z: j7 I3 N) Y3 R' o间隔3s显示free" w' E5 _+ D3 B6 |( S5 t7 N

& B- I2 C" i4 W8 |9 p1 ?% i9 O9 x显示高低内存利用率% V4 s: @0 ^2 P9 P
如果我们想要知道高低内存统计,我们可以使用-l选项。下面是一个例子。) j* S9 q0 g: I* T4 B
( N/ d( P9 V1 N
$ free -l
4 A3 x. v  h. [5 ?9 x; e* b" nFree 的 低-高 统计/ ~; g' u$ ?1 k  j7 F7 y

7 i. @4 {4 i) F( ]3 e! u显示 Linux 全部内存
* x2 Y4 Y4 G8 N  n4 T; u如果我们需要每列的总计信息,我们可以在 free 命令后面跟上 -t 选项。这会在字底部额外加入一行显示。
% t( p$ p7 A! Y, S( x7 R9 X
% M$ V! Z$ i( ^* H0 Q% u, a; k6 p$ free -t5 p0 X5 @/ E9 k1 |' C
free命令带总计内存; Z  G- O! r" C6 Q  m! i

" N5 B# z3 j2 j0 |$ z* f总结
( s2 m$ K+ w% B除了vmstat以外,free 命令也是一个用于统计内存利用率的简单统计工具。用这个你可以快速查看你的 Linux 内存信息。free 命令使用 /proc/meminfo 作为基准来显示内存利用率信息。如往常一样,你可以在控制台下输入 man free 来获取更多关于 free 的信息。
; N1 W; g" O2 v' o
$ r! f4 Y+ j% |4 `  w6 V
; H5 o- Y! {) t* _) ^  S
: O8 W5 d& n. O6 f3 _5 G: K5 D
7 j8 y* B1 x: j) ^. F$ f+ p4 f5 o% Q( }3 s* X; x; b. G: ~' u

3 x, v2 }* p2 R. l; w% w5 A( @, P/ u3 T, w. L
前段时间有个项目的用C写的,性能测试时发现内存泄露问题。关于怎么观察内存使用问题,free是很好用的一个命令。3 T# N7 j" @) \/ u( I! a

# N  i" T; o6 }7 ^) \bash-3.00$ free1 y: K* E; x7 j, y

' r# Q6 N( u# ltotal       used       free     shared    buffers     cached' W/ m3 k$ d4 r) P8 J3 k: B# [
6 F8 M+ Q2 u2 Q% g' U' r
Mem:       1572988    1509260      63728          0      62800     277888
/ ?4 H; [# b  m: U8 c" e4 n& s
) z* j  d+ ^/ a0 Q3 ?" y8 {-/+ buffers/cache:    1168572     404416" y! ~5 _" r  C

* q* v8 x7 Y! B* @, A4 zSwap:      2096472      16628    20798446 [! b. x9 T% ^# K+ D

) C* i' C0 y& T# I; N
4 b1 N+ P' x) V1 y) V
8 ^; c) M' Z, [8 ?" v& pMem:表示物理内存统计
( D2 G! z/ Y$ j" k% |) ^3 p
; I  I2 Q" N3 ^8 a8 s-/+ buffers/cached:表示物理内存的缓存统计
4 G8 `  k6 J& S
$ s% }+ C- X* Q3 hSwap:表示硬盘上交换分区的使用情况,这里我们不去关心。" H. e5 L# _8 w( x2 Z
6 J% q( m4 C0 ^% d' {4 j
系统的总物理内存:255268Kb(256M),但系统当前真正可用的内存b并不是第一行free 标记的 16936Kb,它仅代表未被分配的内存。. @: y. W' R( O. \. }- h

+ l4 s% C4 v1 N6 F3 R7 k% o. I第1行 Mem: total:表示物理内存总量。
% Z0 `0 m1 q3 B3 _0 N( p# F2 I% ]$ i3 C5 B1 n
used:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。0 n" r* W9 s+ V0 x9 z

0 }" D9 R0 Z3 g' x( }" Dfree:未被分配的内存。
# k! V; I# U. d: y& x, B1 f/ R  B3 [) J4 w+ j+ l# O0 z
shared:共享内存,一般系统不会用到,这里也不讨论。
1 J4 w3 B8 S: ~: R2 p2 b8 s) s: J: Q# R3 S0 g! G# p. i
buffers:系统分配但未被使用的buffers 数量。
4 R5 J' v% r% h0 f7 j3 o  N3 i$ K
( @3 N* N+ E8 q7 P7 m. p+ Wcached:系统分配但未被使用的cache 数量。buffer 与cache 的区别见后面。 total = used + free 第2行 -/+ buffers/cached: used:也就是第一行中的used - buffers-cached 也是实际使用的内存总量。 # ]& |- n2 b( H$ ~( {

1 j% V$ x( _5 t) I; c0 A! Kfree:未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。 free 2= buffers1 + cached1 + free1 //free2为第二行、buffers1等为第一行( E; j" o( d4 \1 V4 j8 z% |9 I
, T9 E/ K0 o+ W  I; e/ O7 w
buffer 与cache 的区别, g2 ]) g, r- i' I
8 `  v6 C5 p1 X6 `  T+ o# D
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会很快地被回收。
& B5 Z3 E; B* @0 k8 I" p9 M2 \* G8 {+ k' W
所以从应用程序的角度来说,可用内存=系统free memory+buffers+cached.
6 D1 U* D1 f9 b# B) M; t6 B5 ]6 D! }
接下来解释什么时候内存会被交换,以及按什么方交换。, ^9 l4 J0 D& m
- U$ y+ O; ]$ G9 Q. u& D4 j) |
当可用内存少于额定值的时候,就会开会进行交换.# k6 x- x. W! Q

& h, j7 q2 G- ~, h* T如何看额定值(RHEL4.0):$ p4 i* Y& F& V" n
# m. A/ R* J4 _  W& F5 L
#cat /proc/meminfo
. ~4 s3 D' e# Y1 v9 M. v. E& J% Z% c# P' f2 @6 H" A# V
交换将通过三个途径来减少系统中使用的物理页面的个数:
$ E8 }4 r( J, R9 x" U6 a, o
6 x- i& H0 d9 d; J4 X- L. U7 M* k1.减少缓冲与页面cache的大小,% N# _, m4 h. p2 D/ W4 z1 z1 V

4 Z9 j3 n) B( Q8 \% w# H2.将系统V类型的内存页面交换出去,
4 T$ G$ S: N! I! V# n
, h% E* K2 b2 P1 f" Y3.换出或者丢弃页面。(Application 占用的内存页,也就是物理内存不足)。
8 M) k7 G$ W& T, p) N* U. _, N  C6 V$ E. ?- c1 I# S
事实上,少量地使用swap是不是影响到系统性能的。4 U7 G& F# C1 d, N0 _8 P

0 f' S9 s, x* v& `下面是buffers与cached的区别。
) D; i1 S6 h( K2 D2 f
  `& M& e# H! |! K( E5 e& a# kbuffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.. E; @+ J- B3 k, p( y5 k2 s0 Y
6 x7 U: K& }& i/ m# [4 S3 u
cached是用来给文件做缓冲。
" [9 u  |( l* G6 l  x# |) B  ]  S" q7 R% N
那就是说:buffers是用来存储,目录里面有什么内容,权限等等。2 }2 b+ h! N1 J3 ~: i8 U/ R- U# Y! j
/ B+ _4 K7 ]. q2 x6 p
而cached直接用来记忆我们打开的文件,如果你想知道他是不是真的生效,你可以试一下,先后执行两次命令#man X ,你就可以明显的感觉到第二次的开打的速度快很多。
9 O1 b' I- S8 h" d
9 ?& \2 Q$ S1 R! b6 L' t实验:在一台没有什么应用的机器上做会看得比较明显。记得实验只能做一次,如果想多做请换一个文件名。
4 y( K4 F) ?3 I8 _
! w6 A2 P% o9 }9 D% r1 Q: K#free& m5 Y/ P/ _- Y$ `

) a! c8 l: s7 Q1 `/ \4 J+ f6 k7 l#man X
0 Z! O/ B/ U" h3 O. J! D/ Z  E- c
#free
6 o8 T" j" }! m& I# s
! L: R$ ?$ f; x  A0 O#man X! ^1 R2 v5 c% `3 x& s8 q% @: l- ?
0 T/ m5 Q* Q2 t9 Z1 A, i
#free1 W2 f( z  @9 ]9 I" o! T4 C7 W
) F# W8 g4 v6 B
你可以先后比较一下free后显示buffers的大小。
% [# C" T4 W" r8 B5 H/ G* F: W8 G6 ?) u% y+ e( J
另一个实验:
9 @. L, q) e7 y5 `# w
/ J- }1 q$ x! I/ I" P#free
4 k& P- Q( t% P$ F3 G: v8 h6 C6 c# {: F
#ls /dev
( P) j  R, {* o. z: o) ~/ ~+ b
& X. l& w+ l4 A, m; G: P, X#free
0 y* J, r) L$ R: W+ s5 C. S! }
9 {! b4 C, ?/ z/ N你比较一下两个的大小,当然这个buffers随时都在增加,但你有ls过的话,增加的速度会变得快,这个就是buffers/chached的区别。' _- E! ^+ c# K) g9 K4 q
# I& i4 b8 a# J
因为Linux将你暂时不使用的内存作为文件和数据缓存,以提高系统性能,当你需要这些内存时,系统会自动释放(不像windows那样,即使你有很多空闲内存,他也要访问一下磁盘中的pagefiles)
5 w- R8 s& N( h9 S& I, L: {  v- L' Y+ U/ G
使用free命令0 p: Q6 @$ q  y

1 v  A! M# p( s0 ~7 S/ D7 @将used的值减去   buffer和cache的值就是你当前真实内存使用 ————– 对操作系统来讲是Mem的参数.buffers/cached 都是属于被使用,所以它认为free只有16936.
, }' S, _3 F- K% o: E8 x% f0 ]4 ~7 j
对应用程序来讲是(-/+ 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:50 , Processed in 0.053144 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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