Skip to content

Commit ec33687

Browse files
Barry Songakpm00
authored andcommitted
mm: add per-order mTHP anon_fault_alloc and anon_fault_fallback counters
Patch series "mm: add per-order mTHP alloc and swpout counters", v6. The patchset introduces a framework to facilitate mTHP counters, starting with the allocation and swap-out counters. Currently, only four new nodes are appended to the stats directory for each mTHP size. /sys/kernel/mm/transparent_hugepage/hugepages-<size>/stats anon_fault_alloc anon_fault_fallback anon_fault_fallback_charge anon_swpout anon_swpout_fallback These nodes are crucial for us to monitor the fragmentation levels of both the buddy system and the swap partitions. In the future, we may consider adding additional nodes for further insights. This patch (of 4): Profiling a system blindly with mTHP has become challenging due to the lack of visibility into its operations. Presenting the success rate of mTHP allocations appears to be pressing need. Recently, I've been experiencing significant difficulty debugging performance improvements and regressions without these figures. It's crucial for us to understand the true effectiveness of mTHP in real-world scenarios, especially in systems with fragmented memory. This patch establishes the framework for per-order mTHP counters. It begins by introducing the anon_fault_alloc and anon_fault_fallback counters. Additionally, to maintain consistency with thp_fault_fallback_charge in /proc/vmstat, this patch also tracks anon_fault_fallback_charge when mem_cgroup_charge fails for mTHP. Incorporating additional counters should now be straightforward as well. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Barry Song <[email protected]> Acked-by: David Hildenbrand <[email protected]> Cc: Chris Li <[email protected]> Cc: Domenico Cerasuolo <[email protected]> Cc: Kairui Song <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: Peter Xu <[email protected]> Cc: Ryan Roberts <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Cc: Yosry Ahmed <[email protected]> Cc: Yu Zhao <[email protected]> Cc: Jonathan Corbet <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent d199483 commit ec33687

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

include/linux/huge_mm.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,27 @@ unsigned long thp_vma_allowable_orders(struct vm_area_struct *vma,
264264
enforce_sysfs, orders);
265265
}
266266

267+
enum mthp_stat_item {
268+
MTHP_STAT_ANON_FAULT_ALLOC,
269+
MTHP_STAT_ANON_FAULT_FALLBACK,
270+
MTHP_STAT_ANON_FAULT_FALLBACK_CHARGE,
271+
__MTHP_STAT_COUNT
272+
};
273+
274+
struct mthp_stat {
275+
unsigned long stats[ilog2(MAX_PTRS_PER_PTE) + 1][__MTHP_STAT_COUNT];
276+
};
277+
278+
DECLARE_PER_CPU(struct mthp_stat, mthp_stats);
279+
280+
static inline void count_mthp_stat(int order, enum mthp_stat_item item)
281+
{
282+
if (order <= 0 || order > PMD_ORDER)
283+
return;
284+
285+
this_cpu_inc(mthp_stats.stats[order][item]);
286+
}
287+
267288
#define transparent_hugepage_use_zero_page() \
268289
(transparent_hugepage_flags & \
269290
(1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG))

mm/huge_memory.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,48 @@ static const struct kobj_type thpsize_ktype = {
526526
.sysfs_ops = &kobj_sysfs_ops,
527527
};
528528

529+
DEFINE_PER_CPU(struct mthp_stat, mthp_stats) = {{{0}}};
530+
531+
static unsigned long sum_mthp_stat(int order, enum mthp_stat_item item)
532+
{
533+
unsigned long sum = 0;
534+
int cpu;
535+
536+
for_each_possible_cpu(cpu) {
537+
struct mthp_stat *this = &per_cpu(mthp_stats, cpu);
538+
539+
sum += this->stats[order][item];
540+
}
541+
542+
return sum;
543+
}
544+
545+
#define DEFINE_MTHP_STAT_ATTR(_name, _index) \
546+
static ssize_t _name##_show(struct kobject *kobj, \
547+
struct kobj_attribute *attr, char *buf) \
548+
{ \
549+
int order = to_thpsize(kobj)->order; \
550+
\
551+
return sysfs_emit(buf, "%lu\n", sum_mthp_stat(order, _index)); \
552+
} \
553+
static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
554+
555+
DEFINE_MTHP_STAT_ATTR(anon_fault_alloc, MTHP_STAT_ANON_FAULT_ALLOC);
556+
DEFINE_MTHP_STAT_ATTR(anon_fault_fallback, MTHP_STAT_ANON_FAULT_FALLBACK);
557+
DEFINE_MTHP_STAT_ATTR(anon_fault_fallback_charge, MTHP_STAT_ANON_FAULT_FALLBACK_CHARGE);
558+
559+
static struct attribute *stats_attrs[] = {
560+
&anon_fault_alloc_attr.attr,
561+
&anon_fault_fallback_attr.attr,
562+
&anon_fault_fallback_charge_attr.attr,
563+
NULL,
564+
};
565+
566+
static struct attribute_group stats_attr_group = {
567+
.name = "stats",
568+
.attrs = stats_attrs,
569+
};
570+
529571
static struct thpsize *thpsize_create(int order, struct kobject *parent)
530572
{
531573
unsigned long size = (PAGE_SIZE << order) / SZ_1K;
@@ -549,6 +591,12 @@ static struct thpsize *thpsize_create(int order, struct kobject *parent)
549591
return ERR_PTR(ret);
550592
}
551593

594+
ret = sysfs_create_group(&thpsize->kobj, &stats_attr_group);
595+
if (ret) {
596+
kobject_put(&thpsize->kobj);
597+
return ERR_PTR(ret);
598+
}
599+
552600
thpsize->order = order;
553601
return thpsize;
554602
}
@@ -880,6 +928,8 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
880928
folio_put(folio);
881929
count_vm_event(THP_FAULT_FALLBACK);
882930
count_vm_event(THP_FAULT_FALLBACK_CHARGE);
931+
count_mthp_stat(HPAGE_PMD_ORDER, MTHP_STAT_ANON_FAULT_FALLBACK);
932+
count_mthp_stat(HPAGE_PMD_ORDER, MTHP_STAT_ANON_FAULT_FALLBACK_CHARGE);
883933
return VM_FAULT_FALLBACK;
884934
}
885935
folio_throttle_swaprate(folio, gfp);
@@ -929,6 +979,7 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
929979
mm_inc_nr_ptes(vma->vm_mm);
930980
spin_unlock(vmf->ptl);
931981
count_vm_event(THP_FAULT_ALLOC);
982+
count_mthp_stat(HPAGE_PMD_ORDER, MTHP_STAT_ANON_FAULT_ALLOC);
932983
count_memcg_event_mm(vma->vm_mm, THP_FAULT_ALLOC);
933984
}
934985

@@ -1050,6 +1101,7 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
10501101
folio = vma_alloc_folio(gfp, HPAGE_PMD_ORDER, vma, haddr, true);
10511102
if (unlikely(!folio)) {
10521103
count_vm_event(THP_FAULT_FALLBACK);
1104+
count_mthp_stat(HPAGE_PMD_ORDER, MTHP_STAT_ANON_FAULT_FALLBACK);
10531105
return VM_FAULT_FALLBACK;
10541106
}
10551107
return __do_huge_pmd_anonymous_page(vmf, &folio->page, gfp);

mm/memory.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4368,6 +4368,7 @@ static struct folio *alloc_anon_folio(struct vm_fault *vmf)
43684368
folio = vma_alloc_folio(gfp, order, vma, addr, true);
43694369
if (folio) {
43704370
if (mem_cgroup_charge(folio, vma->vm_mm, gfp)) {
4371+
count_mthp_stat(order, MTHP_STAT_ANON_FAULT_FALLBACK_CHARGE);
43714372
folio_put(folio);
43724373
goto next;
43734374
}
@@ -4376,6 +4377,7 @@ static struct folio *alloc_anon_folio(struct vm_fault *vmf)
43764377
return folio;
43774378
}
43784379
next:
4380+
count_mthp_stat(order, MTHP_STAT_ANON_FAULT_FALLBACK);
43794381
order = next_order(&orders, order);
43804382
}
43814383

@@ -4485,6 +4487,9 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
44854487

44864488
folio_ref_add(folio, nr_pages - 1);
44874489
add_mm_counter(vma->vm_mm, MM_ANONPAGES, nr_pages);
4490+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
4491+
count_mthp_stat(folio_order(folio), MTHP_STAT_ANON_FAULT_ALLOC);
4492+
#endif
44884493
folio_add_new_anon_rmap(folio, vma, addr);
44894494
folio_add_lru_vma(folio, vma);
44904495
setpte:

0 commit comments

Comments
 (0)