mm: add last level page table numa info to /proc/pid/numa_pgtable
Subsystems (3)
RFC PATCH 1/1 mm: add last level page table numa info to /proc/pid/numa_pgtable
In many data center servers, the shared memory architectures is Non-Uniform Memory Access (NUMA), remote numa node data access often brings a high latency problem, but what we are easy to ignore is that the page table remote numa access, It can also leads to a performance degradation.
So there add a new interface in /proc, This will help developers to get more info about performance issues if they are caused by cross-NUMA.
--- fs/proc/base.c | 6 ++- fs/proc/internal.h | 1 + fs/proc/task_mmu.c | 129 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 2 deletions(-)
fs/proc/base.c +4 -2
@@ -2626,7 +2626,7 @@ static struct dentry *proc_pident_instantiate(struct dentry *dentry,return d_splice_alias (inode, dentry); } -static struct dentry *proc_pident_lookup (struct inode *dir, +static struct dentry *proc_pident_lookup (struct inode *dir,struct dentry *dentry,const struct pid_entry *p,const struct pid_entry *end)
@@ -2839,7 +2839,7 @@ static const struct pid_entry attr_dir_stuff[] = {static int proc_attr_dir_readdir (struct file *file,struct dir_context *ctx) { -return proc_pident_readdir (file, ctx, +return proc_pident_readdir (file, ctx, attr_dir_stuff,ARRAY_SIZE (attr_dir_stuff)); }
@@ -3224,6 +3224,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("maps", S_IRUGO, proc_pid_maps_operations),#ifdef CONFIG_NUMA REG ("numa_maps" ,S_IRUGO , proc_pid_numa_maps_operations), +REG ("numa_pgtable" ,S_IRUGO , proc_pid_numa_pgtable_operations), #endifREG ("mem" ,S_IRUSR |S_IWUSR , proc_mem_operations), LNK("cwd", proc_cwd_link),
@@ -3571,6 +3572,7 @@ static const struct pid_entry tid_base_stuff[] = {#endif #ifdef CONFIG_NUMA REG ("numa_maps" ,S_IRUGO , proc_pid_numa_maps_operations), +REG ("numa_pgtable" ,S_IRUGO , proc_pid_numa_pgtable_operations), #endifREG ("mem" ,S_IRUSR |S_IWUSR , proc_mem_operations), LNK("cwd", proc_cwd_link),
fs/proc/internal.h +1 -0
@@ -296,6 +296,7 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode);extern const struct file_operations proc_pid_maps_operations;extern const struct file_operations proc_pid_numa_maps_operations; +extern const struct file_operations proc_pid_numa_pgtable_operations;extern const struct file_operations proc_pid_smaps_operations;extern const struct file_operations proc_pid_smaps_rollup_operations;extern const struct file_operations proc_clear_refs_operations;
fs/proc/task_mmu.c +129 -0
133 lines not on this page · raw message
--
2.31.0
Quoted 8 lines · Xin Hao
In many data center servers, the shared memory architectures is Non-Uniform Memory Access (NUMA), remote numa node data access often brings a high latency problem, but what we are easy to ignore is that the page table remote numa access, It can also leads to a performance degradation.
So there add a new interface in /proc, This will help developers to get more info about performance issues if they are caused by cross-NUMA.
Interesting. The implementation seems rather more complex than necessary though.
Quoted 6 lines
fs/proc/task_mmu.c +0
-0@@ -1999,4 +1999,133 @@ const struct file_operations proc_pid_numa_maps_operations = { .release = proc_map_release,
fs/proc/task_mmu.c const struct file_operations proc_pid_numa_maps_operations = { · line 2009
Quoted 10 lines
fs/proc/task_mmu.c +8
-0}; +struct pgtable_numa_maps { +unsigned long node[MAX_NUMNODES ]; +}; + +struct pgtable_numa_private { +struct proc_maps_private proc_maps; +struct pgtable_numa_maps md; +};
struct pgtable_numa_private {
struct proc_maps_private proc_maps;
unsigned long node[MAX_NUMNODES];
};Quoted 46 lines
fs/proc/task_mmu.c +46
-0+static void gather_pgtable_stats (struct page *page,struct pgtable_numa_maps *md) +{ + md->node[page_to_nid (page)] +=1 ; +} + +static struct page *can_gather_pgtable_numa_stats (pmd_t pmd,struct vm_area_struct *vma, +unsigned long addr) +{ +struct page *page; +int nid; + +if (!pmd_present (pmd)) +return NULL ; + +if (pmd_huge (pmd)) +return NULL ; + + page =pmd_page (pmd); + nid =page_to_nid (page); +if (!node_isset (nid, node_states[N_MEMORY ])) +return NULL ; + +return page; +} + +static int gather_pgtable_numa_stats (pmd_t *pmd,unsigned long addr, +unsigned long end,struct mm_walk *walk) +{ +struct pgtable_numa_maps *md = walk->private; +struct vm_area_struct *vma = walk->vma; +struct page *page; + +if (pmd_huge (*pmd)) { +struct page *pmd_page; + + pmd_page =virt_to_page (pmd); +if (!pmd_page) +return 0 ; + +if (!node_isset (page_to_nid (pmd_page), node_states[N_MEMORY ])) +return 0 ; + +gather_pgtable_stats (pmd_page, md); + goto out; + } +
fs/proc/task_mmu.c const struct file_operations proc_pid_numa_maps_operations = { · line 2066
Quoted 10 lines
fs/proc/task_mmu.c +10
-0+ page =can_gather_pgtable_numa_stats (*pmd, vma, addr); +if (!page) +return 0 ; + +gather_pgtable_stats (page, md); + +out: +cond_resched (); +return 0 ; +}
static int gather_pgtable_numa_stats(pmd_t *pmd, unsigned long addr,
unsigned long end, struct mm_walk *walk)
{
struct pgtable_numa_private *priv = walk->private;
struct vm_area_struct *vma = walk->vma;
struct page *page;
int nid;
if (pmd_huge(*pmd)) {
page = virt_to_page(pmd);
} else {
page = pmd_page(*pmd);
}
nid = page_to_nid(page);
priv->node[nid]++;
return 0;
}Quoted 100 lines · Matthew Wilcox
Quoted 8 lines · Xin Hao
In many data center servers, the shared memory architectures is Non-Uniform Memory Access (NUMA), remote numa node data access often brings a high latency problem, but what we are easy to ignore is that the page table remote numa access, It can also leads to a performance degradation.
So there add a new interface in /proc, This will help developers to get more info about performance issues if they are caused by cross-NUMA.
Interesting. The implementation seems rather more complex than necessary though.
Quoted 6 lines
fs/proc/task_mmu.c +0
-0@@ -1999,4 +1999,133 @@ const struct file_operations proc_pid_numa_maps_operations = { .release = proc_map_release,fs/proc/task_mmu.c const struct file_operations proc_pid_numa_maps_operations = { · line 2009
Quoted 10 lines
fs/proc/task_mmu.c +8
-0}; +struct pgtable_numa_maps { +unsigned long node[MAX_NUMNODES ]; +}; + +struct pgtable_numa_private { +struct proc_maps_private proc_maps; +struct pgtable_numa_maps md; +};struct pgtable_numa_private { struct proc_maps_private proc_maps; unsigned long node[MAX_NUMNODES]; };Quoted 46 lines
fs/proc/task_mmu.c +46
-0+static void gather_pgtable_stats (struct page *page,struct pgtable_numa_maps *md) +{ + md->node[page_to_nid (page)] +=1 ; +} + +static struct page *can_gather_pgtable_numa_stats (pmd_t pmd,struct vm_area_struct *vma, +unsigned long addr) +{ +struct page *page; +int nid; + +if (!pmd_present (pmd)) +return NULL ; + +if (pmd_huge (pmd)) +return NULL ; + + page =pmd_page (pmd); + nid =page_to_nid (page); +if (!node_isset (nid, node_states[N_MEMORY ])) +return NULL ; + +return page; +} + +static int gather_pgtable_numa_stats (pmd_t *pmd,unsigned long addr, +unsigned long end,struct mm_walk *walk) +{ +struct pgtable_numa_maps *md = walk->private; +struct vm_area_struct *vma = walk->vma; +struct page *page; + +if (pmd_huge (*pmd)) { +struct page *pmd_page; + + pmd_page =virt_to_page (pmd); +if (!pmd_page) +return 0 ; + +if (!node_isset (page_to_nid (pmd_page), node_states[N_MEMORY ])) +return 0 ; + +gather_pgtable_stats (pmd_page, md); + goto out; + } +fs/proc/task_mmu.c const struct file_operations proc_pid_numa_maps_operations = { · line 2066
Quoted 10 lines
fs/proc/task_mmu.c +10
-0+ page =can_gather_pgtable_numa_stats (*pmd, vma, addr); +if (!page) +return 0 ; + +gather_pgtable_stats (page, md); + +out: +cond_resched (); +return 0 ; +}static int gather_pgtable_numa_stats(pmd_t *pmd, unsigned long addr,
unsigned long end, structmm_walk*walk){ struct pgtable_numa_private *priv = walk->private; struct vm_area_struct *vma = walk->vma; struct page *page; int nid; if (pmd_huge(*pmd)) { page = virt_to_page(pmd); } else {
Quoted 8 lines
page = pmd_page(*pmd); } nid = page_to_nid(page); priv->node[nid]++; return 0; }
Oh, Thank you for reviewing the code, i will fix it in the next version.