Skip to content

Latest commit

 

History

History
145 lines (100 loc) · 8.07 KB

其他工程问题以及调优.md

File metadata and controls

145 lines (100 loc) · 8.07 KB

其他工程问题以及调优

  • DMA和cache一致性
  • 内存的cgroup
  • memcg子系统分析
  • 性能方面的调优: page in/out, swap in/out
  • Dirty ratio的一些设置
  • swappiness

DMA和cache一致性

image

工程中,DMA可以直接在内存和外设进行数据搬移,而CPU访问内存时要经过MMU。DMA访问不到CPU内部的cache,所以会出现cache不一致的问题。因为CPU读写内存时,如果在cache中命中,就不会再访问内存。

当CPU 写memory时,cache有两种算法:write_back ,write_through。一般都采用write_back。cache的硬件,使用LRU算法,把cache中的数据替换到磁盘。

image

cache一致性问题,主要靠以上两类api来解决这个问题。一致性DMA缓冲区api,和流式DMA映射api。CPU通过MMU访问DMA区域,在页表项中可以配置这片区域是否带cache。

现代的SoC,DMA引擎可以自动维护cache的同步。

内存的cgroup

进程分group,内存也分group。

进程调度时,把一组进程加到一个cgroup,控制这一组进程的CPU权重和最大CPU占用率。在/sys/fs/cgroup/memory创建一个目录,把进程放到这个group。可以限制某个group下的进程不用swap,每个group的swapiness都可以配置。

比如,当你把某个group下的swapiness设置为0,那么这个group下进程的匿名页就不允许交换了。
/proc/sys/vm/swapiness是控制全局的swap特性,不影响加到group中的进程。

也可以控制每个group的最大内存消耗为200M,当这个group下进程使用的内存达到200M,就oom。

demo: 演示用memory cgroup来限制进程group内存资源消耗的方法

swapoff -a
echo 1 > /proc/sys/vm/overcommit_memory  # 进程申请多少资源,内核都允许

root@whale:/sys/fs/cgroup/memory# mkdir A
root@whale:/sys/fs/cgroup/memory# cd A
root@whale:/sys/fs/cgroup/memory/A# echo $((200*1024*1024)) > memory.limit_in_bytes

cgexec -g memory:A ./a.out


[  560.618666] Memory cgroup out of memory: Kill process 5062 (a.out) score 977 or sacrifice child
[  560.618817] Killed process 5062 (a.out) total-vm:2052084kB, anon-rss:204636kB, file-rss:1240kB

memory cgroup子系统分析

memcg v1的参数有25个, 通过数据结构 res_counter 来计算。

~~~
/* * The core object. the cgroup that wishes to account for some 
* resource may include this counter into its structures and use 
* the helpers described beyond */

struct res_counter {        
  unsigned long long usage;      /*         * 目前资源消费的级别         */          
  unsigned long long max_usage;        /*         *从counter创建的最大使用值       */      
  unsigned long long limit;       /*         * 不能超过的使用限制       */       
  unsigned long long soft_limit;      /*         * 可以超过使用的限制        */   
  unsigned long long failcnt;        /*         * 尝试消费资源的失败数         */        
  spinlock_t lock;        /*         * the lock to protect all of the above.        
                                              * the routines below consider this to be IRQ-safe         */        
  struct res_counter *parent; /*         * Parent counter, used for hierarchial resource accounting         */     
};

内存的使用量 mem_cgroup_usage 通过递归RSS和page cache之和来计算。

struct mem_cgroup是负责内存 cgroup 的结构

struct mem_cgroup {        
  struct cgroup_subsys_state css; // 通过css关联cgroup.        
  struct res_counter res; // mem统计变量	
  res_counter memsw; // mem+sw的和        
  struct res_counter kmem; // 内核内存统计量	...
}

这些参数的入口都在mm/memcontrol.c下,比如说memory.usage_in_bytes的读取调用的是mem_cgroup_read函数, 统计的入口是mem_cgroup_charge_common(),如果统计值超过限制就会在cgroup内进行回收。调用者分别是缺页时调用的mem_cgroup_newpage_charge和 page cache相关的mem_cgroup_cache_charge。

当进程进入缺页异常的时候就会分配具体的物理内存,当物理内存使用超过高水平线以后,换页daemon(kswapd)就会被唤醒用于把内存交换到交换空间以腾出内存,当内存恢复至高水平线以后换页daemon进入睡眠。

缺页异常的入口是 __do_fault,

RSS在page_fault的时候记录,page cache是插入到inode的radix-tree中才记录的。
RSS在完全unmap的时候减少计数,page cache的page在离开inode的radix-tree才减少计数。
即使RSS完全unmap,也就是被kswapd给换出,可能作为SwapCache存留在系统中,除非不作为SwapCache,不然还是会被计数。
一个换入的page不会马上计数,只有被map的时候才会,当进行换页的时候,会预读一些不属于当前进程的page,而不是通过page fault,所以不在换入的时候计数。

脏页写回的“时空”控制

image

“脏页”:当进程修改了高速缓存里的数据时,该页就被内核标记为脏页,内核将会在合适的时间把脏页的数据写到磁盘中去,以保持高速缓存中的数据和磁盘中的数据是一致的。

通过时间(dirty_expire_centisecs)和比例,控制Linux脏页返回。

dirty_expire_centisecs:当Linux中脏页的时间到达dirty_expire_centisecs,无论脏页的数量多少,必须立即写回。通过在后台启动进程,进行脏页写回。
默认时间设置为30s。

dirty_ratio,dirty_background_ratio 基于空间的脏页写回控制。
不能让内存中存在太多空间的脏页。如果一个进程在循环调用write,当达到dirty_background_ratio后,后台进程就开始写回脏页。默认值5%。当达到第2个阈值dirty_ratio时,应用进程被阻塞。当内存中的脏页在两个阈值之间时,应用程序是不会阻塞。

内存何时回收:水位控制

脏页写回不是 内存回收。

脏页写回:是保证在内存不在磁盘的数据不要太多。
水位控制:是指内存何时开始回收。

image

由/pro/sys/vm/min_free_kbytes 控制,根据内存大小算出来的平方根。
pf_mem_alloc,允许内存达到低水位以下,还可以继续申请。内存的回收,在最低水位以上就开始回收。

image

每个Zone都有自己的三个水位,最小的水位是根据min_free_kbytes控制。5/4min_free_kbytes =low 3/2min_free_kbytes =high ,
Zone的最小内存达到5/4的low 水位,Linux开始后台回收内存。直到达到6/4的high水位,开始不回收。
当Zone的最小内存达到min水位,应用程序的写会直接阻塞。

实时操作系统,

image

当你要开始回收内存时,回收比例通过swappiness越大,越倾向于回收匿名页;swappiness越小,越倾向于回收file-backed的页面。
当把cgroup中的swapiness设置为0,就不回收匿名页了。
当你的应用会经常去访问数据malloc的内存,需要把swapiness设置小。dirty的设置,水位的设置都没有一个标准,要看应用使用内存的情况而定。

getdelays工具:用来评估应用等待CPU,内存,IO,的时间。
linux/Documents/accounting

image

CONFIG_TASK_DELAY_ACCT=y CONFIG_TASKSTATS=y

vmstat 可以展现给定时间间隔的服务器的状态值,包括Linux的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。

vmstat 1

Documents/sysctl/vm.txt 中有所有参数最细节的描述。