找回密码
 注册
查看: 4040|回复: 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项被创建)。
) d4 o) a  L% j% l/ s) S9 s# p; X. e  L8 g: I
2. 当前服务器是storm集群的节点,首先想到了storm相关的工作进程,strace一下storm的worker进程发现其中有非常频繁的stat系统调用发生,而且stat的文件总是新的文件名:
7 S( C+ W: B+ A; n4 `/ ]$ E
  r/ ?# b; e) j4 W) h( qsudo strace -fp <pid> -e trace=stat& e1 ?4 T; ]0 c
3. 进一步观察到storm的worker进程会在本地目录下频繁的创建、打开、关闭、删除心跳文件,每秒钟一个新的文件名:
- x! R0 f) ]- N- ?( f
/ }  w' I. o0 p6 j& H4 ^6 Y7 c- ksudo strace -fp <pid> -e trace=open,stat,close,unlink. w8 @* ]8 d% S7 `% v( a  g) G
以上就是系统中为何有如此多的dentry_cache的原因所在。2 A- J5 M% p1 n' p2 m- v* n

! y; ^4 \3 D# G3 A一个奇怪的现象2 M; ^# y2 Y: @9 A
通过观察/proc/meminfo发现,slab内存分为两部分:' W7 |& G- n" _7 p5 h

+ x2 {, L/ ?/ b5 g( x4 uSReclaimable // 可回收的slab
& m, G. m3 B' ~* MSUnreclaim // 不可回收的slab% |2 H! Z4 a/ J1 G2 r
当时服务器的现状是:slab部分占用的内存,大部分显示的都是SReclaimable,也就是说可以被回收的。
8 j! h; [9 X" j; k7 x# f2 M# T  z
但是通过slabtop观察到slab内存中最主要的部分(dentry_cache)的OBJS几乎都是ACTIVE的,显示100%处于被使用状态。. t8 d' z9 U1 P  i

  H/ u' i, c, p  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                  
- n6 Q8 K, V1 p# B/ Z& e13926348 13926348 100%    0.21K 773686       18   3494744K dentry_cache# N2 v% a$ @1 f" O% x
334040 262056  78%    0.09K   8351       40     33404K buffer_head
/ j7 i. L; r5 |. P: n, b' ?151040 150537  99%    0.74K  30208        5    120832K ext3_inode_cache
* c0 `. v7 v0 r1 d3 Q4 k7 B为什么显示可回收的,但是又处于ACTIVE状态呢?求Linux内核达人看到后热心解释下:(/ w6 V  C1 G$ m1 `3 }9 P

  w6 B: K; ^5 F: i$ Z0 K( W. J会不会由于是ACTIVE状态,导致dcache没有被自动回收释放掉呢?, E* \, R$ a0 _5 X

7 G3 S" h+ _9 O让系统自动回收dcache
2 a( a" K* K- U1 G8 J! F: V上一小节,我们已经提到,服务器上大部分的slab内存是SReclaimable可回收状态的,那么,我们能不能交给操作系统让他在某个时机自动触发回收操作呢?答案是肯定的。# ~: K' C. F' |0 i& J
& D6 s! J: z" O0 o+ M9 B* V2 |# v6 P
查了一些关于Linux dcache的相关资料,发现操作系统会在到了内存临界阈值后,触发kswapd内核进程工作才进行释放,这个阈值的计算方法如下:
' S8 x6 L2 ~5 c4 z  O0 V  t1 q- E/ o: V# n
1. 首先,grep low /proc/zoneinfo,得到如下结果:1 F# v" ~. s9 A* J1 g- |: L

8 L/ F% ]) K% K& n        low      1# x4 k3 T5 V+ X7 g& P% O" A3 O) ~! v
        low      380
8 `6 T: j; }* ^9 T3 G        low      12067
4 Z, t7 u3 g2 U! J, d" g- h2. 将以上3列加起来,乘以4KB,就是这个阈值,通过这个方法计算后发现当前服务器的回收阈值只有48MB,因此很难看到这一现象,实际中可能等不到回收,操作系统就会hang住没响应了。+ O# ~' K7 L9 O, p8 f' _  E  J

, s: s* u3 M" f1 R5 T8 G7 P3. 可以通过以下方法调大这个阈值:将vm.extra_free_kbytes设置为vm.min_free_kbytes和一样大,则/proc/zoneinfo中对应的low阈值就会增大一倍,同时high阈值也会随之增长,以此类推。
. Z0 y+ P1 y* q3 O# }  v5 c8 f9 q+ N2 @" a4 S8 R& D) o
$ sudo sysctl -a | grep free_kbytes      
7 ~2 _, C. c% G2 O& r7 `: \* Dvm.min_free_kbytes = 39847
+ D8 a$ q$ g, p' _+ G3 T/ M% `vm.extra_free_kbytes = 0; u0 v8 _3 i: b/ n" f
$ sudo sysctl -w vm.extra_free_kbytes=836787  ######1GB, {+ T+ V2 g4 @$ S  L
4. 举个例子,当low阈值被设置为1GB的时候,当系统free的内存小于1GB时,观察到kswapd进程开始工作(进程状态从Sleeping变为Running),同时dcache开始被系统回收,直到系统free的内存介于low阈值和high阈值之间,停止回收。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2018-4-23 10:15:54 | 显示全部楼层
如何运行 free
2 x5 a% P& b! |+ h4 i; j% |2 i想要运行,只需在控制台输入free 即可。不带选项运行会显示一个以KB为单位的默认输出。
' H  ^' X& R: p3 W7 l" W+ l. P& p0 Y' }+ ]! g1 i# `! }. B
$ free( ?  @9 h; G% C  w0 G$ H5 _3 T
free默认视图
# n( X3 s  P& g9 w- L" R) y9 v: z( R4 a
从上面的截图我们看到:4 M" r; q- v: e) @4 O1 B, w6 g$ h3 l

2 M: r" R. {0 y2 ~# I内存 (以KB计)
% i8 r, N/ L" u0 u" b/ @Total(全部) : 1026740; I/ q9 b8 I# h0 l# p
Used(已用) : 843396
1 |* K  n. C' h  B6 D3 m& r& mFree(可用) : 183344. `3 C+ ]- R; q5 ?7 P% D' Q
Shared(共享) : 0/ B0 H0 @$ L/ L! a( T7 s- D2 W- w: {
Buffers(块设备缓存区) : 527049 _6 {7 T4 g2 |( K
Cached(文件缓存) : 376384
9 ?# D( a7 J. G  J译注:关于Buffers和Cached的区别,来自 http://www.taobaotesting.com/blogs/qa?bid=2265 的一段解释如下:1 P! ~" `% x* w( t% N$ y" `" C
' i5 X2 W' C* ^1 r6 c0 `
buffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.4 }& E/ f6 }6 N4 y2 i- g

: m# J1 f+ |; @$ k; Rcached是用来给文件做缓冲。0 D# s0 m$ e9 Z  D. w2 Q# r8 ]
- I3 U* x! K/ ]) @1 N, ]' P
那就是说:buffers是用来存储,目录里面有什么内容,权限等等。而cached直接用来记忆我们打开的文件: n# [: Y/ J. }. {: D% {
3 x" |9 v, i0 s# y
Swap (以KB计)( |1 P3 i$ r( U; J4 m% U, P1 S' f% l
Total(全部) : 10455001 [6 Q7 d3 z  L, \  ~+ |( d; e& Z
Used(已用) : 3376/ j3 h, r4 R% y2 h4 X
Free(可用) : 1042124' l1 |* w6 T7 j" n# y0 Z: u
当你看见 buffer/cache 的空闲空间低或者 swap 的空闲空间低,说明内存需要升级了。这意味这内存利用率很高。请注意 shared(共享)内存列应该被忽略 ,因为它已经被废弃了。
2 b2 r' u/ h* q  j' x
$ _$ @" k' l1 L* X: d' k$ x以其它单元显示内存信息- ]6 U. [: D# p- S' y
如我们先前提到的,默认 free 会以 KB 为单位显示信息。free 同样提供给我们 b (B), -k (KB), -m (MB), -g (GB) and –tera (TB)这些单位。要显示我们想要的单位,只要选择一个并在 free 后面跟上。下面一个是以 MB 为单位的输出样例。
( ?7 a* q! C' r4 q2 I: C, j0 _( v4 j. k- ]
$ free -m
4 |6 [# ?* b2 U1 D  C' l; ]# t" Ofree命令以MB为单位2 O0 b# E6 W3 T1 \# D, K

  ^* W& Z0 I8 e/ N这个技巧同样适用于-b, -k, -g 以及 –tera 选项。
: b6 A/ J& R& b, T% j  Z7 k4 o. \
以适于人类可读方式显示内存信息5 i& u  g: I" i8 d& u& \
free 同样提供了-h选项,这意味着适于人类可读(译注:系统上可能并不存在-h选项,已被-m取代)。那么这与其它的选项有什么不同呢,如-m(MB)选项? 可见的最大不同是-h选项会在数字后面加上适于人类可读的单位。让我们看一个例子。
* N1 n* _9 N! a1 \- q; t
: u$ ~/ @- ^' T! M' X  O# `$ free -h
" {; }1 O, f/ C: X8 U人类可读的free0 k) F/ v6 |6 O1 E
  K& Z: u; D/ S6 V; M1 H! O' F. C
如我们一起看到的,在1,0数字后这里是G(GB)字母。当数字并没有达到GB时,free足够聪明来知道并在每个数字后面跟上合适的单位。后面的M - 数字929告诉我们它有929MB(译注: 原文为929 number tell us its 969 Megabytes,这里应该为输入错误)。/ Y4 J% Y* W  G5 i/ o
8 x% a9 t8 l+ d
间隔显示 free, ^; s2 ?/ \3 C" A
作为一个状态检查工具,最好的统计内存利用率的方法是使用延迟间隔。这么做的话,我们可以使用-s选项后面跟上我们想要间隔的N秒数。我们可以在后面合并几个选项来使输出满足我们的需求。假如我们想要每3秒统计一次内存利用率并且适于人类可读,那么就像这样做:
5 D: v! ]4 R9 |" ]7 }! x$ |: k9 R
7 H1 C/ d& `0 o" w$ free -hs 3
+ W/ j" o6 v7 `& t2 A间隔3s显示free
* }$ ~4 o9 a2 j1 i8 u4 m! i* S0 V2 o8 s8 J9 V
显示高低内存利用率
4 x# c6 t* J" T, O+ y. T如果我们想要知道高低内存统计,我们可以使用-l选项。下面是一个例子。, ?% ~! Q( C, v; o
/ ]* L' M$ P/ A- l4 L
$ free -l
9 Z) ^2 |6 `, u( |Free 的 低-高 统计
# X% I! v  V( s9 t9 G+ {
5 o) r5 a8 T# u2 I显示 Linux 全部内存
5 r, ~: A0 f/ V  f, w1 O如果我们需要每列的总计信息,我们可以在 free 命令后面跟上 -t 选项。这会在字底部额外加入一行显示。; ~+ C  E  D# H5 G: S# S3 m
; [) w1 n4 g- W( G3 K+ o
$ free -t3 ]% Y+ T4 N# h1 V
free命令带总计内存
. U* X7 c$ p1 i9 R9 \( E% v7 V6 y3 P
总结) q0 u# }1 b$ u0 X9 l% _
除了vmstat以外,free 命令也是一个用于统计内存利用率的简单统计工具。用这个你可以快速查看你的 Linux 内存信息。free 命令使用 /proc/meminfo 作为基准来显示内存利用率信息。如往常一样,你可以在控制台下输入 man free 来获取更多关于 free 的信息。. }! a: d6 n5 P
. r7 I1 n  \: f+ W! s
1 r5 s! o/ W. t) T

2 }9 m; \2 d2 N% c( x1 F 6 w; ]+ i+ O! _& w& V1 B6 u9 Y; V7 d

1 b: \0 e+ f8 R5 N; P $ X3 z9 _6 R9 ^1 N. e

* b2 v, @- ?$ m5 W前段时间有个项目的用C写的,性能测试时发现内存泄露问题。关于怎么观察内存使用问题,free是很好用的一个命令。
6 W: |; J: G3 U: k  `5 Z- B( ^
( R; V  y( J4 [+ T* X3 W# vbash-3.00$ free: c( D+ t2 Z  m- r/ C% l$ Z- ^( I/ O
6 g% b4 E+ \( h7 Z' y+ F3 C
total       used       free     shared    buffers     cached' G) C0 a5 }8 j! d+ }
: W$ z- i+ [7 Y$ m  q
Mem:       1572988    1509260      63728          0      62800     277888
7 x+ ~1 v: F. R: D& b! N* w1 g: l' q3 {
" C+ I9 ~5 Y% M$ {) y-/+ buffers/cache:    1168572     4044166 b/ {3 Y- @. U$ D
1 L! T* V: @" P- k: S; T
Swap:      2096472      16628    2079844: \( ]# ]6 |8 z  A4 O8 G
9 ^( Y/ G: g2 G* c/ c7 G

3 ]' B2 X' Y6 y( y7 z. c2 i1 v; I$ a0 I* s' d4 ~: P& T6 J9 ~6 r
Mem:表示物理内存统计
' g+ `) ?) B) T/ @. z4 A
5 ], N4 q1 J9 w' G) m' K! c-/+ buffers/cached:表示物理内存的缓存统计
2 }5 r- T' J/ f7 r; i& b
0 u  L/ n2 b" e' U4 \8 ^) uSwap:表示硬盘上交换分区的使用情况,这里我们不去关心。8 _. a8 W" N% u3 E/ R, @

( u! B- u8 `- u& K系统的总物理内存:255268Kb(256M),但系统当前真正可用的内存b并不是第一行free 标记的 16936Kb,它仅代表未被分配的内存。
: c- J, Q6 D7 J
( T9 \6 J, r- j; e8 O第1行 Mem: total:表示物理内存总量。
% @2 i; n9 j( v/ e! K7 X, r$ |) z, l$ E# l( ~$ I5 ~
used:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。6 n2 S' Y& q$ H" _8 w
7 C$ ?+ e% l7 @. u3 ?
free:未被分配的内存。
9 N: _, w& z+ u5 z" z/ L( _8 Z1 F$ I* q3 M' ~, S5 x8 ~- ?. p+ e
shared:共享内存,一般系统不会用到,这里也不讨论。+ \* S# u5 o; b
& J9 @/ v7 [: x0 q6 N  k
buffers:系统分配但未被使用的buffers 数量。; @6 U: `1 D, |# U

7 H  D9 A, I1 N# icached:系统分配但未被使用的cache 数量。buffer 与cache 的区别见后面。 total = used + free 第2行 -/+ buffers/cached: used:也就是第一行中的used - buffers-cached 也是实际使用的内存总量。
" f+ n( {2 g! ~  m# q3 o
  x, P0 l( i  t) h3 m- dfree:未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。 free 2= buffers1 + cached1 + free1 //free2为第二行、buffers1等为第一行: n2 r; `& d1 r3 Y+ [$ I% X  \

  T! w8 b' l) g# j9 |$ g/ tbuffer 与cache 的区别+ g: c0 u+ M! \! k( R
9 f5 Z" m( o- l3 }9 e" x
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会很快地被回收。1 b8 |8 [* I& f/ u
# m, C1 u" ^6 f
所以从应用程序的角度来说,可用内存=系统free memory+buffers+cached.: j! |1 d1 o/ r; b3 `+ ^
: u# p& r% ]: |& c. V4 x7 a7 B7 t
接下来解释什么时候内存会被交换,以及按什么方交换。2 t; n! D/ y- H& H( h3 A' p
* S2 ]+ D6 Q- e6 s1 B2 m# x
当可用内存少于额定值的时候,就会开会进行交换.8 ~( Y. F" Y5 V  \$ t3 f5 F

* i: v0 a' ~2 G. y$ {' Y如何看额定值(RHEL4.0):
5 Z8 r! V) w. h* r9 L6 o, m4 p0 j/ U0 P# M5 Y
#cat /proc/meminfo
  f0 C9 t, I2 Q# d, G8 f, a4 N6 n- T' R6 d: f
交换将通过三个途径来减少系统中使用的物理页面的个数:
, Z, i- C' V" ^5 h- O$ A3 m9 [, y9 ]
1.减少缓冲与页面cache的大小,: Z% s3 y1 C$ h' j

; R& O5 d5 c, e' r5 }+ Z2.将系统V类型的内存页面交换出去,% Y, ?) a/ l8 r( z0 [! Q
! Z8 \( V4 B3 R" _( S
3.换出或者丢弃页面。(Application 占用的内存页,也就是物理内存不足)。9 U! ~! z3 m( `: ?7 k+ p% G
" i5 [& Y5 G/ B3 h* ?6 n" t( ?- c
事实上,少量地使用swap是不是影响到系统性能的。; }8 X: W' B% Y8 c* V+ d+ x3 K, L" r

8 T7 l8 W3 U. ]2 F# v8 `5 D% F下面是buffers与cached的区别。
' ?" y5 N6 Y. V* S( }8 K* {8 [2 m8 B: N! ?+ E- G
buffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.
( }# X9 i+ \; C( x4 \
. Y9 K  @. p3 }7 O" T" Z& C  X: ucached是用来给文件做缓冲。  l* R! x- ~7 t; M; S' |0 O8 A+ x

  ^; a: H) y  c那就是说:buffers是用来存储,目录里面有什么内容,权限等等。! e2 @6 [* X% A$ U2 o2 g1 [) \
2 J+ x& ?, R: ~5 X+ X7 M5 k
而cached直接用来记忆我们打开的文件,如果你想知道他是不是真的生效,你可以试一下,先后执行两次命令#man X ,你就可以明显的感觉到第二次的开打的速度快很多。
1 c8 Z. B6 g2 d- n2 H7 }2 \) p" J3 x! Q% U: \8 v, u, e1 o( M$ q
实验:在一台没有什么应用的机器上做会看得比较明显。记得实验只能做一次,如果想多做请换一个文件名。4 d) @3 |5 n9 E0 H
& v- i. o: H* c
#free
6 O' t4 J& a+ p# Z/ d+ r
2 d5 ?% f0 l" [/ K$ o! k* ^' m% U#man X4 X/ r8 o6 ~" \, D( q6 g7 K
! |. M. D+ u9 s; _3 f" U
#free
4 `4 \1 `# j1 u; c; P& i
' T8 w- O2 P" _- f9 A! N#man X
5 \0 }' E2 U3 p' k+ m* M$ S
7 a7 D! {8 q* X) s#free4 D: F8 E0 K( a
9 ^4 Q+ o$ v% M2 o. m2 P7 |4 E
你可以先后比较一下free后显示buffers的大小。
) w) a& {& f* l# Z& q: V
. o3 |) Y' E( h. Y1 z: V) o% ]另一个实验:, `9 O% O$ z; l

" n2 B1 E- G1 H#free
; Z$ ^  e: R# L( X$ ~; @2 X  K; A+ T' N- b) B& M2 `
#ls /dev
& w& P) j2 c+ |' j" h% T2 I: ]0 d" C, K, U
#free
7 o2 P1 E( n1 M  I) L8 A
( B3 @4 R3 R. ?( }& ~你比较一下两个的大小,当然这个buffers随时都在增加,但你有ls过的话,增加的速度会变得快,这个就是buffers/chached的区别。
* x2 Q/ R3 v# t. Z
" L% {+ R4 P" d2 n% j因为Linux将你暂时不使用的内存作为文件和数据缓存,以提高系统性能,当你需要这些内存时,系统会自动释放(不像windows那样,即使你有很多空闲内存,他也要访问一下磁盘中的pagefiles)7 H3 \3 W* m# |4 j1 p) Z
$ x3 ]4 x5 y+ N  b  l2 `
使用free命令8 I3 a% _: W  ?
, E2 z/ }9 S  Q, E# e0 y- R) ^0 [
将used的值减去   buffer和cache的值就是你当前真实内存使用 ————– 对操作系统来讲是Mem的参数.buffers/cached 都是属于被使用,所以它认为free只有16936.% I& t; K& F5 R3 t. q# U

; Y$ U2 v. d3 M% T对应用程序来讲是(-/+ 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 01:57 , Processed in 0.026655 second(s), 25 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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