找回密码
 注册
查看: 4041|回复: 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项被创建)。9 s/ I8 O/ ]- n* L+ N  _; _

- |% d7 O4 }' _% D4 T- f9 ]7 L2. 当前服务器是storm集群的节点,首先想到了storm相关的工作进程,strace一下storm的worker进程发现其中有非常频繁的stat系统调用发生,而且stat的文件总是新的文件名:& n/ Q! `% J) Y6 n9 O, r* N4 B- u
2 M+ U4 Q+ k' V' l1 \
sudo strace -fp <pid> -e trace=stat
' x- M) K8 e# Z1 S3. 进一步观察到storm的worker进程会在本地目录下频繁的创建、打开、关闭、删除心跳文件,每秒钟一个新的文件名:
" g4 @& m/ w/ ~2 {# _
* }) y  \! w) e# O# w5 Z2 t7 M! Msudo strace -fp <pid> -e trace=open,stat,close,unlink) v! N+ d, _' |4 y  ^- x* }  h
以上就是系统中为何有如此多的dentry_cache的原因所在。* k; M4 d# Q, g
0 |+ z& C( ?8 e% `2 J% h
一个奇怪的现象
  b- C- C' p- x: Q% ?0 I通过观察/proc/meminfo发现,slab内存分为两部分:
' r1 {# l! |) l* `- a$ e; H
0 G; p/ I7 Q2 T  B$ Z& p7 XSReclaimable // 可回收的slab
  g! k- F4 w9 T4 t3 u& WSUnreclaim // 不可回收的slab+ i. v" r; B/ b7 Z3 R
当时服务器的现状是:slab部分占用的内存,大部分显示的都是SReclaimable,也就是说可以被回收的。
6 Z' T$ N7 F) X# e7 D3 x" O; ~! I1 O8 c* W8 H9 b
但是通过slabtop观察到slab内存中最主要的部分(dentry_cache)的OBJS几乎都是ACTIVE的,显示100%处于被使用状态。  }* z* N( a7 q8 j" K6 o

* f3 ~0 r* r4 Z# Y6 G( O3 B' l6 J; `4 K% Q  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                  
; K  T. e- z. H3 C6 r  F13926348 13926348 100%    0.21K 773686       18   3494744K dentry_cache! t! @9 m  }3 ]4 d7 b
334040 262056  78%    0.09K   8351       40     33404K buffer_head
7 G; G: T- g3 n% p151040 150537  99%    0.74K  30208        5    120832K ext3_inode_cache
3 c0 l1 A; e! H5 j# F0 E9 Y为什么显示可回收的,但是又处于ACTIVE状态呢?求Linux内核达人看到后热心解释下:(
! k; `# m5 p; c6 z
' C: M$ }' {1 S会不会由于是ACTIVE状态,导致dcache没有被自动回收释放掉呢?
: `& H- n4 T/ g- k( n- V
1 A+ K; \( N6 Z: P" b让系统自动回收dcache
0 d$ e  r* S' ^8 }0 t% ~  B/ v上一小节,我们已经提到,服务器上大部分的slab内存是SReclaimable可回收状态的,那么,我们能不能交给操作系统让他在某个时机自动触发回收操作呢?答案是肯定的。
( T& |- t& V' @2 K; @/ R; c& |3 v( B: s7 O
查了一些关于Linux dcache的相关资料,发现操作系统会在到了内存临界阈值后,触发kswapd内核进程工作才进行释放,这个阈值的计算方法如下:% A' a5 @7 f* |( V6 o3 ]5 z! |
& P- [1 [+ i+ t0 P  w
1. 首先,grep low /proc/zoneinfo,得到如下结果:- F# y" N6 w0 b: \6 y: J. e

% c4 t+ ?1 u) }        low      1+ o" L0 A9 x- j: V, o0 d+ y
        low      380: O& Y$ h1 Y  r* h
        low      120679 S* \# G. B( d. o& K7 u
2. 将以上3列加起来,乘以4KB,就是这个阈值,通过这个方法计算后发现当前服务器的回收阈值只有48MB,因此很难看到这一现象,实际中可能等不到回收,操作系统就会hang住没响应了。
" R0 _7 m' U9 Z5 V" ]' R7 ]1 G: A+ I6 w! |9 g  I- B
3. 可以通过以下方法调大这个阈值:将vm.extra_free_kbytes设置为vm.min_free_kbytes和一样大,则/proc/zoneinfo中对应的low阈值就会增大一倍,同时high阈值也会随之增长,以此类推。
( g3 Z0 h/ W3 |/ J. s
& v( o8 S" Y* N5 P# ]$ sudo sysctl -a | grep free_kbytes       . e4 n  ]7 G4 A& n) I2 ]! U
vm.min_free_kbytes = 398470 d' e5 y( a: _; ?/ E
vm.extra_free_kbytes = 0/ Y* H" Y- f" l" a9 O; M" c0 h
$ sudo sysctl -w vm.extra_free_kbytes=836787  ######1GB
+ N9 ^0 k. ^# p! T; @ 4. 举个例子,当low阈值被设置为1GB的时候,当系统free的内存小于1GB时,观察到kswapd进程开始工作(进程状态从Sleeping变为Running),同时dcache开始被系统回收,直到系统free的内存介于low阈值和high阈值之间,停止回收。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2018-4-23 10:15:54 | 显示全部楼层
如何运行 free4 f& m9 M2 A  X: K' V
想要运行,只需在控制台输入free 即可。不带选项运行会显示一个以KB为单位的默认输出。
% F7 a( t* w* u2 {- r& n+ a) @" W' P+ V6 V
$ free
' U- P, n3 p8 b$ g, K# _free默认视图. s( ], F- M- G- b
' V2 `" T# u  F( q& Y2 n
从上面的截图我们看到:! {1 a+ Q5 k1 S& l* Z

0 ^0 a" Q$ g5 g7 q0 S, l内存 (以KB计)
% \# J- P. V9 w/ mTotal(全部) : 10267406 E5 P. Z0 I8 W$ Z# i/ W
Used(已用) : 843396
& r+ X" Y4 K/ L* Y5 ?Free(可用) : 183344
9 F! h' N+ b' N3 X2 U& TShared(共享) : 0  q& Y% j& Q  K8 F/ A) K& l" U5 H# k/ x
Buffers(块设备缓存区) : 52704: ?* E  z  }4 L4 ~7 x7 A& B
Cached(文件缓存) : 3763846 c1 q9 w4 a( i2 @& o: e
译注:关于Buffers和Cached的区别,来自 http://www.taobaotesting.com/blogs/qa?bid=2265 的一段解释如下:5 t0 L" {# b) G* E* g& x

5 K5 n- {% o  W! ebuffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.8 C% a! U9 X9 @. w1 \

; S6 m2 B$ O3 \* M9 U& K" R, icached是用来给文件做缓冲。2 i( J/ e# b5 C" Z9 s% m

1 H4 ?& e+ U3 e+ B$ B( d那就是说:buffers是用来存储,目录里面有什么内容,权限等等。而cached直接用来记忆我们打开的文件
" x3 F9 f6 l6 O+ C( I3 o
  c+ q3 ~: E2 PSwap (以KB计), a2 `8 {  W0 z% `
Total(全部) : 1045500
. w/ x1 k' y, I( B9 e1 O- zUsed(已用) : 3376
  Q( X* t  U4 u  v, v3 l7 S* FFree(可用) : 1042124) T/ g( S: K9 A3 c) [% P
当你看见 buffer/cache 的空闲空间低或者 swap 的空闲空间低,说明内存需要升级了。这意味这内存利用率很高。请注意 shared(共享)内存列应该被忽略 ,因为它已经被废弃了。
: T+ t/ h) V$ [; o/ o. [/ |) H& e& [7 ]- S" y8 e! P
以其它单元显示内存信息& t) F* N4 `" M5 W' r8 c
如我们先前提到的,默认 free 会以 KB 为单位显示信息。free 同样提供给我们 b (B), -k (KB), -m (MB), -g (GB) and –tera (TB)这些单位。要显示我们想要的单位,只要选择一个并在 free 后面跟上。下面一个是以 MB 为单位的输出样例。
, r/ B  c! N/ L
9 f6 @" u) i/ c$ free -m# ]; J/ v* r& {8 v- E( H2 r5 w
free命令以MB为单位3 o: D( G# X1 u* I

. t' y, y% v! s) e4 B% z& e这个技巧同样适用于-b, -k, -g 以及 –tera 选项。
) `% Y6 U% ~4 c0 L" Y: B
! }% o0 S. a5 _8 ^6 \以适于人类可读方式显示内存信息
  x. a% _  @- x4 ffree 同样提供了-h选项,这意味着适于人类可读(译注:系统上可能并不存在-h选项,已被-m取代)。那么这与其它的选项有什么不同呢,如-m(MB)选项? 可见的最大不同是-h选项会在数字后面加上适于人类可读的单位。让我们看一个例子。4 h; Z1 i$ ~& x, G2 p& v

/ {% a- H( w& |$ q, B$ free -h; B8 J! L7 }! A
人类可读的free
- N( e0 `/ T8 x! b- x% n6 p* j6 L# o; v$ l! S4 h
如我们一起看到的,在1,0数字后这里是G(GB)字母。当数字并没有达到GB时,free足够聪明来知道并在每个数字后面跟上合适的单位。后面的M - 数字929告诉我们它有929MB(译注: 原文为929 number tell us its 969 Megabytes,这里应该为输入错误)。
" l4 j& u" B4 G0 b4 c' N/ v; F5 Z2 e. ]& ?+ K# F
间隔显示 free9 F, ^$ R+ w  R" Y7 N! O
作为一个状态检查工具,最好的统计内存利用率的方法是使用延迟间隔。这么做的话,我们可以使用-s选项后面跟上我们想要间隔的N秒数。我们可以在后面合并几个选项来使输出满足我们的需求。假如我们想要每3秒统计一次内存利用率并且适于人类可读,那么就像这样做:
( J# D( \/ q* m+ [' q- ~
7 f  n8 z8 @( ?4 {$ free -hs 37 X! p7 H' d6 ^2 z
间隔3s显示free
" K3 f% `) u- h7 F; x
- ~6 R% y6 @6 v0 f( d显示高低内存利用率
$ ~7 b/ F8 u5 d如果我们想要知道高低内存统计,我们可以使用-l选项。下面是一个例子。
9 b- g+ h4 G+ Y, x
  f* d8 u! t  p8 n( b- H3 @$ free -l
- R6 f) J8 B  N" G+ lFree 的 低-高 统计$ t& l3 M6 c& {9 E9 m7 X; y  x

1 `; h$ e  J6 S! T% A$ `7 K显示 Linux 全部内存
" M1 k. u; i, C- V) ^" S( U* w如果我们需要每列的总计信息,我们可以在 free 命令后面跟上 -t 选项。这会在字底部额外加入一行显示。
! D$ Y. _7 B8 P! o, m8 s# @
  Z* I, c; C0 R- P$ free -t
9 `6 m/ e$ }. @2 H0 {. ufree命令带总计内存$ L6 U0 d+ f7 A2 k! z; I

% }% @7 L& \' i& G0 C1 F9 H; h总结
2 b2 S( |& N2 E/ w除了vmstat以外,free 命令也是一个用于统计内存利用率的简单统计工具。用这个你可以快速查看你的 Linux 内存信息。free 命令使用 /proc/meminfo 作为基准来显示内存利用率信息。如往常一样,你可以在控制台下输入 man free 来获取更多关于 free 的信息。) D* H7 z/ i0 n

8 M7 W# R) a. p# i* N7 y 5 {* @" w8 D3 I0 e5 E2 b

4 |" h( V" T8 i9 w $ g- ?- s2 [, B: v. \

1 w  q  ~0 J6 S0 n9 a+ X ( J' d2 h) n2 }9 h4 \/ [: m, h

3 e) b  W/ e7 S前段时间有个项目的用C写的,性能测试时发现内存泄露问题。关于怎么观察内存使用问题,free是很好用的一个命令。
0 |" E1 q9 y! B, Q! _7 y
% h# T6 N5 D4 h, I- _) H" Obash-3.00$ free
& M0 @- D0 e2 I' m  O5 Z+ \  B1 v2 o( p  B/ ^
total       used       free     shared    buffers     cached0 V, [) b3 s: @9 v9 `% j. Q
! a: K# v0 @7 }. R
Mem:       1572988    1509260      63728          0      62800     277888
* I* z( _! K( R0 T! M  F' Z7 r3 J  E  O" ]  d
-/+ buffers/cache:    1168572     404416! Z- Q/ }( S9 d; v+ ~$ c1 T; |
/ u& S. ~6 b8 r
Swap:      2096472      16628    20798447 x) s8 o" x% T2 u' ~
- v0 \- j9 ^# N& m- v1 N7 H& ?
% L& D  o+ v# y+ P1 J7 c
$ D, O% ]3 d; ^
Mem:表示物理内存统计8 y: [2 f" w& ]4 P  B9 L
$ t" z0 @: r0 C9 A
-/+ buffers/cached:表示物理内存的缓存统计8 r! U. O( W7 `
7 [6 B/ O, X. G( ?) d$ B7 F
Swap:表示硬盘上交换分区的使用情况,这里我们不去关心。
+ h" f+ Q8 s$ E9 l5 h# M8 L% [6 P& J0 j. N
系统的总物理内存:255268Kb(256M),但系统当前真正可用的内存b并不是第一行free 标记的 16936Kb,它仅代表未被分配的内存。
$ c& C5 w% J8 o1 u
# s2 O$ H* Z! l5 G第1行 Mem: total:表示物理内存总量。
( O% x; W* p* `
+ s& y* [' b+ C& w- _( c, fused:表示总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用。
/ O: w! ~' b' c& y2 a! a% {; }* e+ d/ R/ i$ r
free:未被分配的内存。! o. n# A- z- E# d; _4 U) j, @
) @9 S8 l2 {$ c7 x* R; W0 @9 Y
shared:共享内存,一般系统不会用到,这里也不讨论。4 ?+ i. P; O2 f! q% j# `2 ^! K

7 z! S" ~. o, c6 ~  r7 Y  Bbuffers:系统分配但未被使用的buffers 数量。
' v8 A# H5 f  w4 J
1 m* P3 I" d! L) ]cached:系统分配但未被使用的cache 数量。buffer 与cache 的区别见后面。 total = used + free 第2行 -/+ buffers/cached: used:也就是第一行中的used - buffers-cached 也是实际使用的内存总量。 9 p3 G  G# S9 T- J9 d

* q% Q+ V3 u* d) Q# J) V4 B, Cfree:未被使用的buffers 与cache 和未被分配的内存之和,这就是系统当前实际可用内存。 free 2= buffers1 + cached1 + free1 //free2为第二行、buffers1等为第一行
) J7 j- t% a/ x" Y7 q
* e: u7 Q: }0 y3 t' G7 vbuffer 与cache 的区别
5 \  S; e  L" J7 p0 f3 j) [0 a0 [* Z( s0 t  I
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会很快地被回收。% m6 r, T' T5 i" h' C
  a5 X: Q6 }* j4 p' l2 f4 k4 Z" o
所以从应用程序的角度来说,可用内存=系统free memory+buffers+cached.
, s; @' ]6 e1 C/ c; I4 i& x6 ]) d1 p6 N  U) o7 {" ^7 K
接下来解释什么时候内存会被交换,以及按什么方交换。
/ Q" \9 p  P- n
2 Z& A  [; j6 O: F4 |. a& J当可用内存少于额定值的时候,就会开会进行交换.
- ?  l1 j- }7 B: E# }* h$ o. |4 T+ N  r
如何看额定值(RHEL4.0):* V" l3 L! L2 M

% Q) i) q, ~# ^; |6 D#cat /proc/meminfo# R* G) f; ^& T3 D

* n) O5 H# C: D: C交换将通过三个途径来减少系统中使用的物理页面的个数:0 U7 j& D$ H8 p7 e. v5 w
& T! O- f. S$ K" N0 L
1.减少缓冲与页面cache的大小,
: u. Z' ]2 L) l; y% S- b# q1 m& S2 `2 k# B
2.将系统V类型的内存页面交换出去,* q+ a& ^0 g& Z- y3 I

  C% o, B% e* ~- q6 a& K* x3.换出或者丢弃页面。(Application 占用的内存页,也就是物理内存不足)。
& D: t4 c9 ]; g, j. U5 M$ ?* b8 a8 n; [' E8 O9 [
事实上,少量地使用swap是不是影响到系统性能的。
7 I/ b( u# l! r0 L( a
% J& a, F; F, n# k$ ]下面是buffers与cached的区别。9 M) E; d# r) [

4 x7 D& w9 O5 S# M6 Fbuffers是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.
9 }* _$ R+ Z6 D) V% H& k7 t/ o, [% \! [
3 N" N9 W; Z; ]6 q' n- p2 |cached是用来给文件做缓冲。
$ [, V; x' w7 Z' T( W
6 i( D2 M3 x7 B) u6 _那就是说:buffers是用来存储,目录里面有什么内容,权限等等。2 z) y1 w$ j- `9 _7 @5 c/ v6 o

  E: H5 ]" i: h$ e& r而cached直接用来记忆我们打开的文件,如果你想知道他是不是真的生效,你可以试一下,先后执行两次命令#man X ,你就可以明显的感觉到第二次的开打的速度快很多。% M% o% g6 l/ Y  h5 C

1 K1 ^3 |) M# o  @( V4 n* j1 F/ j实验:在一台没有什么应用的机器上做会看得比较明显。记得实验只能做一次,如果想多做请换一个文件名。
: Y# H$ ]( O+ d2 B7 f( K
0 X# D" Q8 p1 t$ n" M#free
1 \/ V! F  [3 P9 G. A7 a0 o& }
5 ]9 o- M$ v0 Z/ w) g#man X8 \6 G5 Q  T( k0 A- M% |2 s: Q( W
2 g' m" U2 T# s7 ~. [$ }; G7 t6 K
#free
( j6 v% ?- F* B# N# [, I
, y$ G( U  V0 F6 m% D* |* W#man X& H6 ]3 @: A+ |; B
) z2 A* j( U( ?% O
#free, U4 O6 z& F+ ?+ I
! C3 D: f, D2 @
你可以先后比较一下free后显示buffers的大小。- z, S+ ]9 O# R
5 @2 P7 H( e9 R* e5 T9 `: m8 d/ ~
另一个实验:/ T% p. ]" v1 `" I& b
' N* S0 K, q* q8 D
#free2 k# J$ c- X& U+ x+ \* A

% t) n6 N* x$ ]% I/ k5 O2 [2 H#ls /dev
7 K7 s9 ^6 z2 t" d& I4 l, E: |% [4 Y( C; P1 S
#free7 W5 M& W. C5 E! ?4 l

. n3 Z* t' k+ T% e你比较一下两个的大小,当然这个buffers随时都在增加,但你有ls过的话,增加的速度会变得快,这个就是buffers/chached的区别。! {% h4 [0 ?& N. t8 n/ r

! j" u  ]; r- ]9 p, T因为Linux将你暂时不使用的内存作为文件和数据缓存,以提高系统性能,当你需要这些内存时,系统会自动释放(不像windows那样,即使你有很多空闲内存,他也要访问一下磁盘中的pagefiles)
2 _& Q3 R% ]' s9 R' S3 }4 d) S" E0 i# w3 W0 n* H- N  _
使用free命令: @  V' Z$ m9 Q( u

. C, h- O, E% v( i# D2 f0 D1 b将used的值减去   buffer和cache的值就是你当前真实内存使用 ————– 对操作系统来讲是Mem的参数.buffers/cached 都是属于被使用,所以它认为free只有16936.
# X" ]( H4 l9 J, [: [3 K$ @  H6 w! f3 g/ ^3 d4 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 02:59 , Processed in 0.042796 second(s), 25 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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