在项目中我们发现了实时系统的pagefault开销比非实时要高,所以本文对pagefault做一下分析和对比。
1,pagefault调用栈(以arm64为例,内核版本为4.19.90)
el1_da (arch/arm64/kernel/entry.S) -- arm64发生data abort的异常处理入口
do_mem_abort
inf = esr_to_fault_info (fault_info, 异常向量表,见arch/arm64/mm/fault.c +661)
inf->fn(也就是 do_page_fault)
__do_page_fault
find_vma //如果找不到相应的vma,说明地址不合法
handle_mm_fault
__handle_mm_fault
pgd = pgd_offset(mm, address);
p4d = p4d_alloc(mm, pgd, address);//获取该进程的pgd(p4d一样)
vmf.pud = pud_alloc(mm, p4d, address); //获取pud,没有分配
vmf.pmd = pmd_alloc(mm, vmf.pud, address);//获取pmd,没有分配
handle_pte_fault(不知为什么,该函数没有出现在function_graph中)
do_anonymous_page//分配一个物理页,并把页表信息写到pte中
(本例是堆栈中的pagefault,进入函数do_anonymous_page,还有可能进入 swap等函数的major pagefault)
pte_alloc(vma->vm_mm, vmf->pmd...//获取或分配pte
vmf->pte = pte_offset_map_lock(vma->vm_mm,//得到pte索引
page = alloc_zeroed_user_highpage_movable//分配一页物理内存
alloc_page_vma
entry = mk_pte(page, vma->vm_page_prot);//设置页表属性
set_pte_at(...vmf->pte, entry); //将该页表项放到pte的索引位置上
异常处理结束,然后返回用户空间,用户进程继续访问该地址,这次已经映射好,可以正常使用。
2,测试程序
这个很简单,应用程序中,申请几页内存,然后循环写入,通常在第二页就发生pagefault。
3,测试方法
trace-cmd start -e all;./mem_test
trace-cmd start -e all -p function -l "do_page_fault";./mem_test
trace-cmd start -p function_graph -g do_page_fault;./mem_test
4,通过function_graph来对比pagefault在实时和标准内核的区别
1)实时系统
mem_test-2096 2....0 83.211342: funcgraph_entry: | do_page_fault() {
mem_test-2096 2....0 83.211342: funcgraph_entry: | down_read_trylock() {
mem_test-2096 2....0 83.211343: funcgraph_entry: | __down_read_trylock() {
mem_test-2096 2....0 83.211343: funcgraph_exit: 0.542 us | }
mem_test-2096 2....0 83.211344: funcgraph_exit: 1.646 us | }
mem_test-2096 2....0 83.211344: funcgraph_entry: | find_vma() {
mem_test-2096 2....0 83.211345: funcgraph_entry: | vmacache_find() {
mem_test-2096 2....0 83.211346: funcgraph_exit: 0.667 us | }
mem_test-2096 2....0 83.211346: funcgraph_exit: 1.792 us | }
mem_test-2096 2....0 83.211347: funcgraph_entry: | handle_mm_fault() {
mem_test-2096 2....0 83.211347: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...10 83.211348: funcgraph_exit: 0.562 us | }
mem_test-2096 2...10 83.211348: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....0 83.211349: funcgraph_exit: 0.521 us | }
mem_test-2096 2....0 83.211350: funcgraph_entry: | __rcu_read_lock() {
mem_test-2096 2....0 83.211350: funcgraph_exit: 0.542 us | }
mem_test-2096 2....0 83.211351: funcgraph_entry: | mem_cgroup_from_task() {
mem_test-2096 2....0 83.211351: funcgraph_exit: 0.542 us | }
mem_test-2096 2....0 83.211352: funcgraph_entry: | __rcu_read_unlock() {
mem_test-2096 2....0 83.211352: funcgraph_exit: 0.521 us | }
mem_test-2096 2....0 83.211353: funcgraph_entry: | __handle_mm_fault() {
mem_test-2096 2....0 83.211354: funcgraph_entry: | do_anonymous_page() {
mem_test-2096 2....0 83.211354: funcgraph_entry: | alloc_pages_vma() {
mem_test-2096 2....0 83.211355: funcgraph_entry: | __get_vma_policy() {
mem_test-2096 2....0 83.211356: funcgraph_exit: 0.542 us | }
mem_test-2096 2....0 83.211356: funcgraph_entry: | get_vma_policy.part.0() {
mem_test-2096 2....0 83.211357: funcgraph_entry: | get_task_policy.part.0() {
mem_test-2096 2....0 83.211357: funcgraph_exit: 0.542 us | }
mem_test-2096 2....0 83.211358: funcgraph_exit: 1.646 us | }
mem_test-2096 2....0 83.211358: funcgraph_entry: | policy_nodemask() {
mem_test-2096 2....0 83.211359: funcgraph_exit: 0.521 us | }
mem_test-2096 2....0 83.211359: funcgraph_entry: | policy_node() {
mem_test-2096 2....0 83.211360: funcgraph_exit: 0.541 us | }
mem_test-2096 2....0 83.211360: funcgraph_entry: | __alloc_pages_nodemask() {
mem_test-2096 2....0 83.211361: funcgraph_entry: | get_page_from_freelist() {
mem_test-2096 2....0 83.211362: funcgraph_entry: | rmqueue_pcplist.isra.0() {
mem_test-2096 2....0 83.211362: funcgraph_entry: | migrate_disable() {
mem_test-2096 2....0 83.211363: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...10 83.211363: funcgraph_exit: 0.541 us | }
mem_test-2096 2...10 83.211364: funcgraph_entry: | pin_current_cpu() {
mem_test-2096 2...10 83.211364: funcgraph_entry: | __read_rt_trylock() {
mem_test-2096 2...10 83.211365: funcgraph_exit: 0.541 us | }
mem_test-2096 2...10 83.211366: funcgraph_exit: 1.625 us | }
mem_test-2096 2...10 83.211366: funcgraph_entry: | task_rq_lock() {
mem_test-2096 2...10 83.211367: funcgraph_entry: | _raw_spin_lock_irqsave() {
mem_test-2096 2d..10 83.211367: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..20 83.211368: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211368: funcgraph_exit: 1.584 us | }
mem_test-2096 2d..20 83.211369: funcgraph_entry: | _raw_spin_lock() {
mem_test-2096 2d..20 83.211369: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..30 83.211370: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..30 83.211370: funcgraph_exit: 1.541 us | }
mem_test-2096 2d..30 83.211371: funcgraph_exit: 4.666 us | }
mem_test-2096 2d..30 83.211371: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2d..20 83.211372: funcgraph_exit: 0.542 us | }
mem_test-2096 2d..20 83.211372: funcgraph_entry: | _raw_spin_unlock_irqrestore() {
mem_test-2096 2...20 83.211373: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2...10 83.211373: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211374: funcgraph_exit: 1.541 us | }
mem_test-2096 2...11 83.211374: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....1 83.211375: funcgraph_exit: 0.542 us | }
mem_test-2096 2....1 83.211375: funcgraph_exit: + 13.250 us | }
mem_test-2096 2....1 83.211376: funcgraph_entry: | rt_spin_lock() {
mem_test-2096 2....1 83.211377: funcgraph_entry: | migrate_disable() {
mem_test-2096 2....2 83.211377: funcgraph_exit: 0.542 us | }
mem_test-2096 2....2 83.211378: funcgraph_exit: 1.646 us | }
mem_test-2096 2....2 83.211378: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...12 83.211379: funcgraph_exit: 0.563 us | }
mem_test-2096 2...12 83.211379: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....2 83.211380: funcgraph_exit: 0.520 us | }
mem_test-2096 2....2 83.211381: funcgraph_entry: | __inc_numa_state() {
mem_test-2096 2....2 83.211381: funcgraph_exit: 0.583 us | }
mem_test-2096 2....2 83.211382: funcgraph_entry: | __inc_numa_state() {
mem_test-2096 2....2 83.211382: funcgraph_exit: 0.562 us | }
mem_test-2096 2....2 83.211383: funcgraph_entry: | rt_spin_unlock() {
mem_test-2096 2....2 83.211383: funcgraph_entry: | migrate_enable() {
mem_test-2096 2....1 83.211384: funcgraph_exit: 0.562 us | }
mem_test-2096 2....1 83.211384: funcgraph_exit: 1.666 us | }
mem_test-2096 2....1 83.211385: funcgraph_entry: | migrate_enable() {
mem_test-2096 2....1 83.211386: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...11 83.211386: funcgraph_exit: 0.625 us | }
mem_test-2096 2...10 83.211387: funcgraph_entry: | task_rq_lock() {
mem_test-2096 2...10 83.211387: funcgraph_entry: | _raw_spin_lock_irqsave() {
mem_test-2096 2d..10 83.211388: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..20 83.211388: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211389: funcgraph_exit: 1.562 us | }
mem_test-2096 2d..20 83.211389: funcgraph_entry: | _raw_spin_lock() {
mem_test-2096 2d..20 83.211390: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..30 83.211390: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..30 83.211391: funcgraph_exit: 1.542 us | }
mem_test-2096 2d..30 83.211391: funcgraph_exit: 4.646 us | }
mem_test-2096 2d..30 83.211392: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2d..20 83.211393: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211393: funcgraph_entry: | _raw_spin_unlock_irqrestore() {
mem_test-2096 2...20 83.211394: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2...10 83.211394: funcgraph_exit: 0.500 us | }
mem_test-2096 2...10 83.211395: funcgraph_exit: 1.562 us | }
mem_test-2096 2...10 83.211395: funcgraph_entry: | unpin_current_cpu() {
mem_test-2096 2...10 83.211396: funcgraph_entry: | __read_rt_unlock() {
mem_test-2096 2...10 83.211396: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211397: funcgraph_exit: 1.604 us | }
mem_test-2096 2...10 83.211397: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....0 83.211398: funcgraph_exit: 0.500 us | }
mem_test-2096 2....0 83.211398: funcgraph_exit: + 13.312 us | }
mem_test-2096 2....0 83.211399: funcgraph_exit: + 37.229 us | }
mem_test-2096 2....0 83.211399: funcgraph_exit: + 38.333 us | }
mem_test-2096 2....0 83.211400: mm_page_alloc: page=0xffa09b71 pfn=2139273 order=0 migratetype=1 gfp_flags=GFP_HIGHUSER_MOVABLE
mem_test-2096 2....0 83.211400: funcgraph_exit: + 39.979 us | }
mem_test-2096 2....0 83.211401: funcgraph_exit: + 46.584 us | }
mem_test-2096 2....0 83.211402: funcgraph_entry: | migrate_disable() {
mem_test-2096 2....0 83.211402: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...10 83.211403: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211403: funcgraph_entry: | pin_current_cpu() {
mem_test-2096 2...10 83.211404: funcgraph_entry: | __read_rt_trylock() {
mem_test-2096 2...10 83.211404: funcgraph_exit: 0.562 us | }
mem_test-2096 2...10 83.211405: funcgraph_exit: 1.625 us | }
mem_test-2096 2...10 83.211405: funcgraph_entry: | task_rq_lock() {
mem_test-2096 2...10 83.211406: funcgraph_entry: | _raw_spin_lock_irqsave() {
mem_test-2096 2d..10 83.211406: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..20 83.211407: funcgraph_exit: 0.479 us | }
mem_test-2096 2d..20 83.211407: funcgraph_exit: 1.563 us | }
mem_test-2096 2d..20 83.211408: funcgraph_entry: | _raw_spin_lock() {
mem_test-2096 2d..20 83.211409: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..30 83.211409: funcgraph_exit: 0.521 us | }
mem_test-2096 2d..30 83.211409: funcgraph_exit: 1.541 us | }
mem_test-2096 2d..30 83.211410: funcgraph_exit: 4.666 us | }
mem_test-2096 2d..30 83.211410: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2d..20 83.211411: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211412: funcgraph_entry: | _raw_spin_unlock_irqrestore() {
mem_test-2096 2...20 83.211412: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2...10 83.211413: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211413: funcgraph_exit: 1.563 us | }
mem_test-2096 2...11 83.211414: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....1 83.211414: funcgraph_exit: 0.521 us | }
mem_test-2096 2....1 83.211415: funcgraph_exit: + 13.146 us | }
mem_test-2096 2....1 83.211415: funcgraph_entry: | __cpu_clear_user_page() {
mem_test-2096 2....1 83.211420: funcgraph_exit: 4.270 us | }
mem_test-2096 2....1 83.211420: funcgraph_entry: | migrate_enable() {
mem_test-2096 2....1 83.211421: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...11 83.211421: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211422: funcgraph_entry: | task_rq_lock() {
mem_test-2096 2...10 83.211422: funcgraph_entry: | _raw_spin_lock_irqsave() {
mem_test-2096 2d..10 83.211423: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..20 83.211423: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211424: funcgraph_exit: 1.583 us | }
mem_test-2096 2d..20 83.211424: funcgraph_entry: | _raw_spin_lock() {
mem_test-2096 2d..20 83.211425: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..30 83.211425: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..30 83.211426: funcgraph_exit: 1.563 us | }
mem_test-2096 2d..30 83.211426: funcgraph_exit: 4.687 us | }
mem_test-2096 2d..30 83.211427: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2d..20 83.211427: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211428: funcgraph_entry: | _raw_spin_unlock_irqrestore() {
mem_test-2096 2...20 83.211429: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2...10 83.211429: funcgraph_exit: 0.542 us | }
mem_test-2096 2...10 83.211430: funcgraph_exit: 1.563 us | }
mem_test-2096 2...10 83.211430: funcgraph_entry: | unpin_current_cpu() {
mem_test-2096 2...10 83.211431: funcgraph_entry: | __read_rt_unlock() {
mem_test-2096 2...10 83.211431: funcgraph_exit: 0.542 us | }
mem_test-2096 2...10 83.211432: funcgraph_exit: 1.605 us | }
mem_test-2096 2...10 83.211432: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....0 83.211433: funcgraph_exit: 0.521 us | }
mem_test-2096 2....0 83.211433: funcgraph_exit: + 13.187 us | }
mem_test-2096 2....0 83.211434: funcgraph_entry: | mem_cgroup_try_charge_delay() {
mem_test-2096 2....0 83.211434: funcgraph_entry: | mem_cgroup_try_charge() {
mem_test-2096 2....0 83.211435: funcgraph_entry: | get_mem_cgroup_from_mm() {
mem_test-2096 2....0 83.211436: funcgraph_entry: | __rcu_read_lock() {
mem_test-2096 2....0 83.211436: funcgraph_exit: 0.521 us | }
mem_test-2096 2....0 83.211437: funcgraph_entry: | __rcu_read_unlock() {
mem_test-2096 2....0 83.211437: funcgraph_exit: 0.521 us | }
mem_test-2096 2....0 83.211438: funcgraph_exit: 2.708 us | }
mem_test-2096 2....0 83.211438: funcgraph_entry: | try_charge() {
mem_test-2096 2....0 83.211439: funcgraph_exit: 0.521 us | }
mem_test-2096 2....0 83.211439: funcgraph_exit: 4.834 us | }
mem_test-2096 2....0 83.211440: funcgraph_entry: | mem_cgroup_throttle_swaprate() {
mem_test-2096 2....0 83.211440: funcgraph_entry: | __rcu_read_lock() {
mem_test-2096 2....0 83.211441: funcgraph_exit: 0.520 us | }
mem_test-2096 2....0 83.211441: funcgraph_entry: | kthread_blkcg() {
mem_test-2096 2....0 83.211442: funcgraph_exit: 0.542 us | }
mem_test-2096 2....0 83.211443: funcgraph_entry: | __rcu_read_unlock() {
mem_test-2096 2....0 83.211443: funcgraph_exit: 0.542 us | }
mem_test-2096 2....0 83.211444: funcgraph_exit: 3.813 us | }
mem_test-2096 2....0 83.211444: funcgraph_exit: + 10.229 us | }
mem_test-2096 2....0 83.211445: funcgraph_entry: | rt_spin_lock() {
mem_test-2096 2....0 83.211445: funcgraph_entry: | migrate_disable() {
mem_test-2096 2....0 83.211446: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...10 83.211446: funcgraph_exit: 0.542 us | }
mem_test-2096 2...10 83.211447: funcgraph_entry: | pin_current_cpu() {
mem_test-2096 2...10 83.211447: funcgraph_entry: | __read_rt_trylock() {
mem_test-2096 2...10 83.211448: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211448: funcgraph_exit: 1.605 us | }
mem_test-2096 2...10 83.211449: funcgraph_entry: | task_rq_lock() {
mem_test-2096 2...10 83.211450: funcgraph_entry: | _raw_spin_lock_irqsave() {
mem_test-2096 2d..10 83.211450: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..20 83.211451: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211451: funcgraph_exit: 1.583 us | }
mem_test-2096 2d..20 83.211452: funcgraph_entry: | _raw_spin_lock() {
mem_test-2096 2d..20 83.211452: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..30 83.211453: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..30 83.211453: funcgraph_exit: 1.542 us | }
mem_test-2096 2d..30 83.211454: funcgraph_exit: 4.688 us | }
mem_test-2096 2d..30 83.211454: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2d..20 83.211455: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211455: funcgraph_entry: | _raw_spin_unlock_irqrestore() {
mem_test-2096 2...20 83.211456: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2...10 83.211456: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211457: funcgraph_exit: 1.584 us | }
mem_test-2096 2...11 83.211457: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....1 83.211458: funcgraph_exit: 0.520 us | }
mem_test-2096 2....1 83.211458: funcgraph_exit: + 13.187 us | }
mem_test-2096 2....1 83.211459: funcgraph_exit: + 14.271 us | }
mem_test-2096 2....1 83.211459: funcgraph_entry: | page_add_new_anon_rmap() {
mem_test-2096 2....1 83.211460: funcgraph_entry: | __mod_node_page_state() {
mem_test-2096 2....1 83.211461: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...11 83.211461: funcgraph_exit: 0.563 us | }
mem_test-2096 2...11 83.211462: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....1 83.211462: funcgraph_exit: 0.521 us | }
mem_test-2096 2....1 83.211463: funcgraph_exit: 2.792 us | }
mem_test-2096 2....1 83.211463: funcgraph_entry: | __page_set_anon_rmap() {
mem_test-2096 2....1 83.211464: funcgraph_exit: 0.542 us | }
mem_test-2096 2....1 83.211464: funcgraph_exit: 4.958 us | }
mem_test-2096 2....1 83.211465: funcgraph_entry: | mem_cgroup_commit_charge() {
mem_test-2096 2....1 83.211466: funcgraph_entry: | migrate_disable() {
mem_test-2096 2....2 83.211466: funcgraph_exit: 0.563 us | }
mem_test-2096 2....2 83.211467: funcgraph_entry: | rt_spin_lock() {
mem_test-2096 2....2 83.211467: funcgraph_entry: | migrate_disable() {
mem_test-2096 2....3 83.211468: funcgraph_exit: 0.542 us | }
mem_test-2096 2....3 83.211468: funcgraph_exit: 1.646 us | }
mem_test-2096 2....3 83.211469: funcgraph_entry: | mem_cgroup_charge_statistics() {
mem_test-2096 2....3 83.211470: funcgraph_exit: 0.688 us | }
mem_test-2096 2....3 83.211470: funcgraph_entry: | memcg_check_events() {
mem_test-2096 2....3 83.211471: funcgraph_entry: | mem_cgroup_event_ratelimit.isra.0() {
mem_test-2096 2....3 83.211471: funcgraph_exit: 0.605 us | }
mem_test-2096 2....3 83.211472: funcgraph_exit: 1.729 us | }
mem_test-2096 2....3 83.211472: funcgraph_entry: | rt_spin_unlock() {
mem_test-2096 2....3 83.211473: funcgraph_entry: | migrate_enable() {
mem_test-2096 2....2 83.211474: funcgraph_exit: 0.542 us | }
mem_test-2096 2....2 83.211474: funcgraph_exit: 1.646 us | }
mem_test-2096 2....2 83.211475: funcgraph_entry: | migrate_enable() {
mem_test-2096 2....1 83.211475: funcgraph_exit: 0.563 us | }
mem_test-2096 2....1 83.211476: funcgraph_exit: + 10.708 us | }
mem_test-2096 2....1 83.211476: funcgraph_entry: | lru_cache_add_active_or_unevictable() {
mem_test-2096 2....1 83.211477: funcgraph_entry: | __lru_cache_add() {
mem_test-2096 2....1 83.211477: funcgraph_entry: | migrate_disable() {
mem_test-2096 2....2 83.211478: funcgraph_exit: 0.542 us | }
mem_test-2096 2....2 83.211479: funcgraph_entry: | rt_spin_lock() {
mem_test-2096 2....2 83.211479: funcgraph_entry: | migrate_disable() {
mem_test-2096 2....3 83.211480: funcgraph_exit: 0.500 us | }
mem_test-2096 2....3 83.211480: funcgraph_exit: 1.625 us | }
mem_test-2096 2....3 83.211481: funcgraph_entry: | rt_spin_unlock() {
mem_test-2096 2....3 83.211481: funcgraph_entry: | migrate_enable() {
mem_test-2096 2....2 83.211482: funcgraph_exit: 0.541 us | }
mem_test-2096 2....2 83.211482: funcgraph_exit: 1.667 us | }
mem_test-2096 2....2 83.211483: funcgraph_entry: | migrate_enable() {
mem_test-2096 2....1 83.211483: funcgraph_exit: 0.562 us | }
mem_test-2096 2....1 83.211484: funcgraph_exit: 7.229 us | }
mem_test-2096 2....1 83.211484: funcgraph_exit: 8.291 us | }
mem_test-2096 2....1 83.211485: funcgraph_entry: | rt_spin_unlock() {
mem_test-2096 2....1 83.211486: funcgraph_entry: | migrate_enable() {
mem_test-2096 2....1 83.211486: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2...11 83.211487: funcgraph_exit: 0.541 us | }
mem_test-2096 2...10 83.211487: funcgraph_entry: | task_rq_lock() {
mem_test-2096 2...10 83.211488: funcgraph_entry: | _raw_spin_lock_irqsave() {
mem_test-2096 2d..10 83.211488: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..20 83.211489: funcgraph_exit: 0.479 us | }
mem_test-2096 2d..20 83.211490: funcgraph_exit: 2.042 us | }
mem_test-2096 2d..20 83.211490: funcgraph_entry: | _raw_spin_lock() {
mem_test-2096 2d..20 83.211491: funcgraph_entry: | preempt_count_add() {
mem_test-2096 2d..30 83.211492: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..30 83.211492: funcgraph_exit: 1.708 us | }
mem_test-2096 2d..30 83.211493: funcgraph_exit: 5.333 us | }
mem_test-2096 2d..30 83.211493: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2d..20 83.211494: funcgraph_exit: 0.500 us | }
mem_test-2096 2d..20 83.211494: funcgraph_entry: | _raw_spin_unlock_irqrestore() {
mem_test-2096 2...20 83.211495: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2...10 83.211495: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211496: funcgraph_exit: 1.583 us | }
mem_test-2096 2...10 83.211496: funcgraph_entry: | unpin_current_cpu() {
mem_test-2096 2...10 83.211497: funcgraph_entry: | __read_rt_unlock() {
mem_test-2096 2...10 83.211497: funcgraph_exit: 0.521 us | }
mem_test-2096 2...10 83.211498: funcgraph_exit: 1.583 us | }
mem_test-2096 2...10 83.211498: funcgraph_entry: | preempt_count_sub() {
mem_test-2096 2....0 83.211499: funcgraph_exit: 0.520 us | }
mem_test-2096 2....0 83.211500: funcgraph_exit: + 13.896 us | }
mem_test-2096 2....0 83.211500: funcgraph_exit: + 14.979 us | }
mem_test-2096 2....0 83.211501: funcgraph_exit: ! 146.792 us | }
mem_test-2096 2....0 83.211501: funcgraph_exit: ! 148.188 us | }
mem_test-2096 2....0 83.211502: funcgraph_exit: ! 154.813 us | }
mem_test-2096 2....0 83.211502: funcgraph_entry: | up_read() {
mem_test-2096 2....0 83.211503: funcgraph_entry: | __up_read() {
mem_test-2096 2....0 83.211503: funcgraph_exit: 0.562 us | }
mem_test-2096 2....0 83.211504: funcgraph_exit: 1.646 us | }
mem_test-2096 2....0 83.211504: funcgraph_exit: ! 162.729 us | }
2)标准内核
mem_test-2234 3.... 438.228220: funcgraph_entry: | do_page_fault() {
mem_test-2234 3.... 438.228220: funcgraph_entry: | down_read_trylock() {
mem_test-2234 3.... 438.228221: funcgraph_exit: 0.355 us | }
mem_test-2234 3.... 438.228221: funcgraph_entry: | find_vma() {
mem_test-2234 3.... 438.228222: funcgraph_entry: | vmacache_find() {
mem_test-2234 3.... 438.228222: funcgraph_exit: 0.333 us | }
mem_test-2234 3.... 438.228222: funcgraph_exit: 1.041 us | }
mem_test-2234 3.... 438.228223: funcgraph_entry: | handle_mm_fault() {
mem_test-2234 3.... 438.228223: funcgraph_entry: | mem_cgroup_from_task() {
mem_test-2234 3.... 438.228223: funcgraph_exit: 0.334 us | }
mem_test-2234 3.... 438.228224: funcgraph_entry: | __handle_mm_fault() {
mem_test-2234 3.... 438.228224: funcgraph_entry: | pmd_devmap_trans_unstable() {
mem_test-2234 3.... 438.228224: funcgraph_exit: 0.334 us | }
mem_test-2234 3.... 438.228225: funcgraph_entry: | do_anonymous_page() {
mem_test-2234 3.... 438.228225: funcgraph_entry: | alloc_pages_vma() {
mem_test-2234 3.... 438.228226: funcgraph_entry: | __get_vma_policy() {
mem_test-2234 3.... 438.228226: funcgraph_exit: 0.333 us | }
mem_test-2234 3.... 438.228226: funcgraph_entry: | get_vma_policy.part.10() {
mem_test-2234 3.... 438.228227: funcgraph_entry: | get_task_policy.part.7() {
mem_test-2234 3.... 438.228227: funcgraph_exit: 0.354 us | }
mem_test-2234 3.... 438.228227: funcgraph_exit: 1.021 us | }
mem_test-2234 3.... 438.228228: funcgraph_entry: | policy_nodemask() {
mem_test-2234 3.... 438.228228: funcgraph_exit: 0.354 us | }
mem_test-2234 3.... 438.228228: funcgraph_entry: | policy_node() {
mem_test-2234 3.... 438.228229: funcgraph_exit: 0.334 us | }
mem_test-2234 3.... 438.228229: funcgraph_entry: | __alloc_pages_nodemask() {
mem_test-2234 3.... 438.228229: funcgraph_entry: | get_page_from_freelist() {
mem_test-2234 3d... 438.228230: funcgraph_entry: | __inc_numa_state() {
mem_test-2234 3d... 438.228230: funcgraph_exit: 0.313 us | }
mem_test-2234 3d... 438.228231: funcgraph_entry: | __inc_numa_state() {
mem_test-2234 3d... 438.228231: funcgraph_exit: 0.334 us | }
mem_test-2234 3.... 438.228231: funcgraph_exit: 1.833 us | }
mem_test-2234 3.... 438.228232: mm_page_alloc: page=0xffa0b329 pfn=2145349 order=0 migratetype=1 gfp_flags=GFP_HIGHUSER_MOVABLE
mem_test-2234 3.... 438.228232: funcgraph_exit: 2.750 us | }
mem_test-2234 3.... 438.228232: funcgraph_exit: 6.917 us | }
mem_test-2234 3.... 438.228232: funcgraph_entry: | __cpu_clear_user_page() {
mem_test-2234 3.... 438.228237: funcgraph_exit: 4.000 us | }
mem_test-2234 3.... 438.228237: funcgraph_entry: | mem_cgroup_try_charge_delay() {
mem_test-2234 3.... 438.228237: funcgraph_entry: | mem_cgroup_try_charge() {
mem_test-2234 3.... 438.228238: funcgraph_entry: | get_mem_cgroup_from_mm() {
mem_test-2234 3.... 438.228238: funcgraph_exit: 0.334 us | }
mem_test-2234 3.... 438.228238: funcgraph_entry: | try_charge() {
mem_test-2234 3.... 438.228239: funcgraph_exit: 0.333 us | }
mem_test-2234 3.... 438.228239: funcgraph_exit: 1.730 us | }
mem_test-2234 3.... 438.228239: funcgraph_entry: | mem_cgroup_throttle_swaprate() {
mem_test-2234 3.... 438.228240: funcgraph_entry: | kthread_blkcg() {
mem_test-2234 3.... 438.228240: funcgraph_exit: 0.354 us | }
mem_test-2234 3.... 438.228240: funcgraph_exit: 1.021 us | }
mem_test-2234 3.... 438.228241: funcgraph_exit: 3.792 us | }
mem_test-2234 3.... 438.228241: funcgraph_entry: | page_add_new_anon_rmap() {
mem_test-2234 3.... 438.228242: funcgraph_entry: | __mod_node_page_state() {
mem_test-2234 3.... 438.228242: funcgraph_exit: 0.333 us | }
mem_test-2234 3.... 438.228242: funcgraph_entry: | __page_set_anon_rmap() {
mem_test-2234 3.... 438.228243: funcgraph_exit: 0.333 us | }
mem_test-2234 3.... 438.228243: funcgraph_exit: 1.729 us | }
mem_test-2234 3.... 438.228243: funcgraph_entry: | mem_cgroup_commit_charge() {
mem_test-2234 3d... 438.228244: funcgraph_entry: | mem_cgroup_charge_statistics() {
mem_test-2234 3d... 438.228244: funcgraph_exit: 0.333 us | }
mem_test-2234 3d... 438.228244: funcgraph_entry: | memcg_check_events() {
mem_test-2234 3d... 438.228245: funcgraph_entry: | mem_cgroup_event_ratelimit.isra.2() {
mem_test-2234 3d... 438.228245: funcgraph_exit: 0.333 us | }
mem_test-2234 3d... 438.228245: funcgraph_exit: 1.000 us | }
mem_test-2234 3.... 438.228246: funcgraph_exit: 2.354 us | }
mem_test-2234 3.... 438.228246: funcgraph_entry: | lru_cache_add_active_or_unevictable() {
mem_test-2234 3.... 438.228246: funcgraph_entry: | __lru_cache_add() {
mem_test-2234 3.... 438.228247: funcgraph_exit: 0.354 us | }
mem_test-2234 3.... 438.228247: funcgraph_exit: 1.042 us | }
mem_test-2234 3.... 438.228247: funcgraph_exit: + 22.541 us | }
mem_test-2234 3.... 438.228248: funcgraph_exit: + 23.980 us | }
mem_test-2234 3.... 438.228248: funcgraph_exit: + 25.437 us | }
mem_test-2234 3.... 438.228248: funcgraph_entry: | up_read() {
mem_test-2234 3.... 438.228249: funcgraph_exit: 0.333 us | }
mem_test-2234 3.... 438.228249: funcgraph_exit: + 29.021 us | }
5,分析
从上述log的对比来看,实时内核的do_page_fault比非实时内核耗时多100+us,但主要是由于function_graph的开销引起的,实测没有多那么多,大约多5us左右。
实时内核调用了get_page_from_freelist--rmqueue_pcplist--rmqueue--local_lock_irqsave--rt_spin_lock--migrate_disable,migrate_disable里包含了很多preempt的操作,同时还有其成对出现的migrate_enable,也有同样的操作,所以导致了额外的开销以及耗时。
在申请大量内存并使用的情况下,系统会发生多次这种minor pagefault,累计起来,会有一定的性能损失。同时,migrate disable/enable也会使用_raw_spin_lock,task_rq_lock,如果申请的资源没有空闲的话,还有额外的等待时间。
6,参考
本文参考了链接“(十四)Linux内存管理之page fault处理【转】 - sky-heaven - 博客园”对pagefault的分析,结合代码来看,分析的很准确。