linux铁三角之内存(五)

  • 作者: 雪山肥鱼
  • 时间:20210329 21:50
  • 目的:DMA与Cache的一致性等问题探讨
# DMA与Cache 的一致性
 ## 一致性问题
 ## dma_alloc_coherent的例外
 ## SMMU|IOMMU
# cgroup
# dirty page 的写回机制
# 内存回收的机制
 swappiness
# 相关工具介绍
 ## getdelays
 ## vmstat

CPU、内存、I/O,如果不理解内存,很多知识都会模糊。不能贯穿一个体系。比如做I/O的时候要经过内存,内存何时真正的去找文件系统去写。内存又什么时候开始回收。为什么内存的大小又严重影响系统性能。

DMA与Cache 的一致性

一致性问题

一致性问题.png

mem中有一块报文,cpu会将这块报文读到cache,cpu再读这块,cache hit。则会从cache中取值。

  • 如果外设是一张网卡,通过DMA 数据传到内存,将红色这块涂成了绿色。内存已经绿了,但是cpu读这块数据却还是红色。造成内存 cache 不一致。
  • 同样 CPU 写红色区域数据的告诉cache, cache 并没有与mem做同步的话,此时数据经过DMA,发送的报文也是有问题的。
    解决方案:
  1. Coherent DMA buffers 一致性
  2. DMA Streaming Mapping 流式DMA映射
  • Coherent DMA buffers 一致性


    示意图.png

    对于一个很弱的硬件,当硬件没有对一致性问题有帮助的时候。
    dma_alloc_coherent, 写驱动的时候自己申请的一片内存。

    • cpu 读写不带cache
    • dma读写也不带cache
      这样就不会出现一致性问题。但是很多情况下你又不能用dma_alloc_coherent, 除非自己写驱动,自己申请的内存。
      但是很多情况下,一个tcp/ip 协议栈,有一个 socket buffer, 这块buffer 并不是程序员申请出来的内存。这时候不可能用dma_alloc_coherent.
  • DMA Streaming Mapping 流式DMA映射
    • 发包
      此时可以用 dma_map_single 与 dma_unmap_single, 这个api 会将cache里的非程序员用dma申请的内存做一次flush,同步到内存中。
    • 收包
      会将cache 里的内容 置换为 invalid, 详情见cache line 那一章节的 关于MESI一致性的阐述。CPU是可以控制cache 的 flag,但他不能访问某块cache的 第几个byte的
      还有 dma_map_sg, dma_unmap_sg这两个API,有的dma引擎较强,支持 聚集散列,自动传n个buffer,第一个传完,传第二个,并不需要连续的内存做DMA.可以用上述两个api,可以将多个不连续的 buffer 做自动传输(以后接触到再查资料学习把)。

dma_alloc_coherent的例外

Interconnect.png

一般情况下这个api 是不带cache(绿色)。但是当cpu支持cache互联网络。cache coherent interconnnect,CPU的cache 可以感知到外部设备。硬件做同步。 (就是MESI的同步手段)。此时dam_alloc_coherent申请的内存就可以带上cache
表面上都是 上述关于dma的API,但是后端针对不同的平台,实现的可能不同。

SMMU | IOMMU

有IOMMU和无IOMMU的dma区别.png

MMU与IOMMU.png

DMA 自带 MMU,因此带有SMMU的DMA并不在乎申请的内存是否连续,会将物理地址映射成虚拟连续的。但是申请内存依旧使用dma_alloc_coherent。上述几个不带MMU的DMA 申请的内存 都是通过CMA (管CMA要)申请的连续内存。
但是带有MMU的DMA申请内存可以不连续
由此可以看出硬件帮你做了很多工作后,你就少操心很多啦。

dma_alloc_coherent 后端内存来源.png

cgroup

cgroup进程分组.png

进程分组。明显qq的体验会优于word。QOS引入。以后遇到再继续学习

dirty page 的写回机制

脏页的写回有两个维度:

  • 时间维度
    dirty_expire_centisecs
    当APP将内容写进脏页,脏页不能在内存中呆的时间太长。假设dirty_expire_centisecs设置成5个小时,一旦掉电数据全部丢失。时间维度不考虑脏页的数量,哪怕只有一页,只要到了时间点就写到硬盘中。
    当然写硬盘的操作对于APP来说是透明的,APP感知不到写硬盘的操作。
  • 空间维度
    dirty_ratio & dirty_background ratio
    主要受到这两个空间维度的影响。
cd /proc/sys/vm
cat dirty_background_ratio

假设 dirty_background_ratio 20%, dirty_ratio 30%. 1G内存
当脏页到达200MB的时候,此时你感知不到 在写硬盘,linux后台会帮你在后台将数据写回。
继续写,脏页到达300MB,后台写硬盘的速度 赶不上 APP 写内存的速度,那么linux会直接堵住前台APP进程。保证dirty_ratio 不能超过30%。

  1. 比如当你写word的时候,流量达不到 dirty_bg_ratio. 根本感觉不到在写硬盘,真正起到作用的是时间维度。dirty_expire_centisecs.
    2.当写的比较剧烈,达到dirty_bg_ratio,但是并没有达到dirty_ratio. 还是感觉不到
  2. 达到dirty_ratio,linux堵住前台APP 不让你写了。会感觉非常卡顿。

内存回收的机制

内存回收与脏页写回是两回事。内存回收,指的是这块内存不要了,下次再需要的时候,重新再申请。


水位.png
cat /proc/zoneinfo
cat min_free_kbyes 最小内存。根据最小内存算出 low 与 high水位

a) linux 回收进程直到high水位为止,认为系统内存是足够的
b) min 系统拥有的进程不能比这个再小
假设 malloc 内存后,不断的去写内存。

  1. 到达low水位后,系统后台启动kswapd reclaim。
  2. 应用程序此时没有那么疯狂,则应用程序不会被堵死
  3. 但内存回收的速度并不一定比你写的速度快,继续疯狂的拿内存
  4. 到达min 水位,linux 堵住前台 直接做 direct_reclaim.(write 有时慢,有时快,因为到达了dirty_ratio,前台被堵死啦)
    程序变得卡顿 可以从水位上查看问题。

swappniess

那么回收的内存可能是 swap的,也可能是file_backed ,也有可能是swap。
这里用swappiness 参数决定。swappiness反应是否积极的使用swap空间
swappiness 参数设置的越大,那么就越倾向回收匿名页。

  1. swappiness = 0 仅在 (free and file-backed pages < high water marked in a zone),说明只回收file-backed的页面是不够的,需要回收swap 空间,也就是说最后才回收swap空间。
  2. swappiness = 60 默认值
  3. swappiness = 100 内核将积极的使用swap空间

例外 cgroup 的 swappiness 只负责 这个gourp的,不影响其他group 的 swappiness参数。

  • 为什么要保证min_free_kbytes
    min_free_kbytes:
    This is used to force the linux VM to keep a minimum number of kilobytes free. The VM uses this number to computre a watermark[WMARK_MIN] value for each lowmem zone in the system. Each lowmem zone gets a number of reserved free pages based proportionally on its size.
    多个node 多个lowzone?
    https://blog.csdn.net/longwang155069/article/details/105451267
    linux内核中存在 PF_MEMALLOC 紧急内存,可以忽略内存管理的水位进行分配。比如回收内存的代码也是要申请内存的。会带上PF_MEMALLOC标记。内核发现带有这个标记,那么即使到达了min,还是会申请成功的。突破min水位。
    军队征粮,得派出征粮队,再不征粮要饿死啦。但是征粮队也是需要吃饭的。
    水位代码:
    /develop/linux/mm/ page_alloc.c

vfs_cache_pressure
该文件表示内核内存回收倾向于direcotry 和 inode cache. 针对 slab 级的 可回收。

相关工具介绍

用到再学习

getdelays

//测试代码

int main(int argc, char ** argv)
{
  int max = -1;
  int mb = 0;
  char * buffer;
  int i ;
#define SIZE 1000
  unsigned int * p = malloc(1024*1024*SIZE);
  print("malloc bufer:%p\n", p);
  /* trigger swap out, 内存不够,根据水位与swappiness,会发生swap out*/
  for(i = 0 ; i< 1024*1024 * (SIZE/sizeof(int)); i ++) {
      p[i] = 123;
      if((i & 0xFFFFF) == 0) {
        printf("%dMB written\n", i>>18);
      }
  }
/*trigger swap in,因为前面已经out出去了,所以一定要swapin,当然因为内存不够也会伴随swap out*/
  for(i = 0 ; i< 1024*1024 * (SIZE/sizeof(int)); i ++) {
      volatile unsigned int a;
      a = p[i]
      if((i & 0xFFFFF) == 0) {
        printf("%dMB read\n", i>>18);
      }
  }

  free(p);
  return 0
}

  • 虚拟机内存很小,代码里申请1g内存
  • trigger swap out, 内存不够,根据水位与swappiness,会发生swap out
  • trigger swap in,因为前面已经out出去了,所以一定要swapin,当然因为内存不够也会伴随swap out
    sudo ./getdelays -d -c ./swap
    得到结果
    结果.png
  1. CPU调度延迟
    平均等多久才会被调度到, io动作平均延迟1ms,total delay 总延迟 单位nm,会除count
  2. swap in count, 内存页的换入换出发生了将近3w次的swap in
  3. 因为不断的申请内存, 到达low水位 或者 min,内存块耗尽,系统帮我护手内存的relcaim 发生了148
    可以看出是有内存swap 和 回收的压力的。

明明只是写内存,但是为什么会有内存与硬盘之间的IO操作呢?

  • 主要是水位
  • 可能也会有一丢丢page 的 LRU

vmstat

man vm stat 有问题找男人 当然也可以用 man man
apropos timer 所有带timer的函数名都找出来了。
将上述代码里 加入while(1)

int main(int argc, char ** argv)
{
  int max = -1;
  int mb = 0;
  char * buffer;
  int i ;
#define SIZE 1000
  unsigned int * p = malloc(1024*1024*SIZE);
  print("malloc bufer:%p\n", p);
  /* trigger swap out, 内存不够,根据水位与swappiness,会发生swap out*/
  while(1)
  {
        for(i = 0 ; i< 1024*1024 * (SIZE/sizeof(int)); i ++) {
         p[i] = 123;
         if((i & 0xFFFFF) == 0) {
             printf("%dMB written\n", i>>18);
           }
         }
    /*trigger swap in,因为前面已经out出去了,所以一定要swapin,当然因为内存不够也会伴随swap out*/
      for(i = 0 ; i< 1024*1024 * (SIZE/sizeof(int)); i ++) {
      volatile unsigned int a;
      a = p[i]
      if((i & 0xFFFFF) == 0) {
          printf("%dMB read\n", i>>18);
        }
      }
  }
  free(p);
  return 0
}

vmstat 5 5s一次


vmstat.png

si so 大量的swapin swapout
in 中断等信息

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容