diff mbox series

[v5,37/37] memprofiling: Documentation

Message ID 20240306182440.2003814-38-surenb@google.com (mailing list archive)
State New
Headers show
Series Memory allocation profiling | expand

Commit Message

Suren Baghdasaryan March 6, 2024, 6:24 p.m. UTC
From: Kent Overstreet <kent.overstreet@linux.dev>

Provide documentation for memory allocation profiling.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
---
 Documentation/mm/allocation-profiling.rst | 91 +++++++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 Documentation/mm/allocation-profiling.rst

Comments

Randy Dunlap March 7, 2024, 3:18 a.m. UTC | #1
Hi,
This includes some editing suggestions and some doc build fixes.


On 3/6/24 10:24, Suren Baghdasaryan wrote:
> From: Kent Overstreet <kent.overstreet@linux.dev>
> 
> Provide documentation for memory allocation profiling.
> 
> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
> Signed-off-by: Suren Baghdasaryan <surenb@google.com>
> ---
>  Documentation/mm/allocation-profiling.rst | 91 +++++++++++++++++++++++
>  1 file changed, 91 insertions(+)
>  create mode 100644 Documentation/mm/allocation-profiling.rst
> 
> diff --git a/Documentation/mm/allocation-profiling.rst b/Documentation/mm/allocation-profiling.rst
> new file mode 100644
> index 000000000000..8a862c7d3aab
> --- /dev/null
> +++ b/Documentation/mm/allocation-profiling.rst
> @@ -0,0 +1,91 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +===========================
> +MEMORY ALLOCATION PROFILING
> +===========================
> +
> +Low overhead (suitable for production) accounting of all memory allocations,
> +tracked by file and line number.
> +
> +Usage:
> +kconfig options:
> + - CONFIG_MEM_ALLOC_PROFILING
> + - CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT
> + - CONFIG_MEM_ALLOC_PROFILING_DEBUG
> +   adds warnings for allocations that weren't accounted because of a
> +   missing annotation
> +
> +Boot parameter:
> +  sysctl.vm.mem_profiling=0|1|never
> +
> +  When set to "never", memory allocation profiling overheads is minimized and it

                                                      overhead is

> +  cannot be enabled at runtime (sysctl becomes read-only).
> +  When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=y, default value is "1".
> +  When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=n, default value is "never".
> +
> +sysctl:
> +  /proc/sys/vm/mem_profiling
> +
> +Runtime info:
> +  /proc/allocinfo
> +
> +Example output:
> +  root@moria-kvm:~# sort -g /proc/allocinfo|tail|numfmt --to=iec
> +        2.8M    22648 fs/kernfs/dir.c:615 func:__kernfs_new_node
> +        3.8M      953 mm/memory.c:4214 func:alloc_anon_folio
> +        4.0M     1010 drivers/staging/ctagmod/ctagmod.c:20 [ctagmod] func:ctagmod_start
> +        4.1M        4 net/netfilter/nf_conntrack_core.c:2567 func:nf_ct_alloc_hashtable
> +        6.0M     1532 mm/filemap.c:1919 func:__filemap_get_folio
> +        8.8M     2785 kernel/fork.c:307 func:alloc_thread_stack_node
> +         13M      234 block/blk-mq.c:3421 func:blk_mq_alloc_rqs
> +         14M     3520 mm/mm_init.c:2530 func:alloc_large_system_hash
> +         15M     3656 mm/readahead.c:247 func:page_cache_ra_unbounded
> +         55M     4887 mm/slub.c:2259 func:alloc_slab_page
> +        122M    31168 mm/page_ext.c:270 func:alloc_page_ext
> +===================
> +Theory of operation
> +===================
> +
> +Memory allocation profiling builds off of code tagging, which is a library for
> +declaring static structs (that typcially describe a file and line number in

                                  typically

> +some way, hence code tagging) and then finding and operating on them at runtime

                                                                        at runtime,

> +- i.e. iterating over them to print them in debugfs/procfs.

  i.e., iterating

> +
> +To add accounting for an allocation call, we replace it with a macro
> +invocation, alloc_hooks(), that
> + - declares a code tag
> + - stashes a pointer to it in task_struct
> + - calls the real allocation function
> + - and finally, restores the task_struct alloc tag pointer to its previous value.
> +
> +This allows for alloc_hooks() calls to be nested, with the most recent one
> +taking effect. This is important for allocations internal to the mm/ code that
> +do not properly belong to the outer allocation context and should be counted
> +separately: for example, slab object extension vectors, or when the slab
> +allocates pages from the page allocator.
> +
> +Thus, proper usage requires determining which function in an allocation call
> +stack should be tagged. There are many helper functions that essentially wrap
> +e.g. kmalloc() and do a little more work, then are called in multiple places;
> +we'll generally want the accounting to happen in the callers of these helpers,
> +not in the helpers themselves.
> +
> +To fix up a given helper, for example foo(), do the following:
> + - switch its allocation call to the _noprof() version, e.g. kmalloc_noprof()
> + - rename it to foo_noprof()
> + - define a macro version of foo() like so:
> +   #define foo(...) alloc_hooks(foo_noprof(__VA_ARGS__))
> +
> +It's also possible to stash a pointer to an alloc tag in your own data structures.
> +
> +Do this when you're implementing a generic data structure that does allocations
> +"on behalf of" some other code - for example, the rhashtable code. This way,
> +instead of seeing a large line in /proc/allocinfo for rhashtable.c, we can
> +break it out by rhashtable type.
> +
> +To do so:
> + - Hook your data structure's init function, like any other allocation function

maybe end the line above with a '.' like the following line.

> + - Within your init function, use the convenience macro alloc_tag_record() to
> +   record alloc tag in your data structure.
> + - Then, use the following form for your allocations:
> +   alloc_hooks_tag(ht->your_saved_tag, kmalloc_noprof(...))


Finally, there are a number of documentation build warnings in this patch.
I'm no ReST expert, but the attached patch fixes them for me.
Suren Baghdasaryan March 7, 2024, 4:51 p.m. UTC | #2
On Thu, Mar 7, 2024 at 3:19 AM Randy Dunlap <rdunlap@infradead.org> wrote:
>
> Hi,
> This includes some editing suggestions and some doc build fixes.
>
>
> On 3/6/24 10:24, Suren Baghdasaryan wrote:
> > From: Kent Overstreet <kent.overstreet@linux.dev>
> >
> > Provide documentation for memory allocation profiling.
> >
> > Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
> > Signed-off-by: Suren Baghdasaryan <surenb@google.com>
> > ---
> >  Documentation/mm/allocation-profiling.rst | 91 +++++++++++++++++++++++
> >  1 file changed, 91 insertions(+)
> >  create mode 100644 Documentation/mm/allocation-profiling.rst
> >
> > diff --git a/Documentation/mm/allocation-profiling.rst b/Documentation/mm/allocation-profiling.rst
> > new file mode 100644
> > index 000000000000..8a862c7d3aab
> > --- /dev/null
> > +++ b/Documentation/mm/allocation-profiling.rst
> > @@ -0,0 +1,91 @@
> > +.. SPDX-License-Identifier: GPL-2.0
> > +
> > +===========================
> > +MEMORY ALLOCATION PROFILING
> > +===========================
> > +
> > +Low overhead (suitable for production) accounting of all memory allocations,
> > +tracked by file and line number.
> > +
> > +Usage:
> > +kconfig options:
> > + - CONFIG_MEM_ALLOC_PROFILING
> > + - CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT
> > + - CONFIG_MEM_ALLOC_PROFILING_DEBUG
> > +   adds warnings for allocations that weren't accounted because of a
> > +   missing annotation
> > +
> > +Boot parameter:
> > +  sysctl.vm.mem_profiling=0|1|never
> > +
> > +  When set to "never", memory allocation profiling overheads is minimized and it
>
>                                                       overhead is
>
> > +  cannot be enabled at runtime (sysctl becomes read-only).
> > +  When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=y, default value is "1".
> > +  When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=n, default value is "never".
> > +
> > +sysctl:
> > +  /proc/sys/vm/mem_profiling
> > +
> > +Runtime info:
> > +  /proc/allocinfo
> > +
> > +Example output:
> > +  root@moria-kvm:~# sort -g /proc/allocinfo|tail|numfmt --to=iec
> > +        2.8M    22648 fs/kernfs/dir.c:615 func:__kernfs_new_node
> > +        3.8M      953 mm/memory.c:4214 func:alloc_anon_folio
> > +        4.0M     1010 drivers/staging/ctagmod/ctagmod.c:20 [ctagmod] func:ctagmod_start
> > +        4.1M        4 net/netfilter/nf_conntrack_core.c:2567 func:nf_ct_alloc_hashtable
> > +        6.0M     1532 mm/filemap.c:1919 func:__filemap_get_folio
> > +        8.8M     2785 kernel/fork.c:307 func:alloc_thread_stack_node
> > +         13M      234 block/blk-mq.c:3421 func:blk_mq_alloc_rqs
> > +         14M     3520 mm/mm_init.c:2530 func:alloc_large_system_hash
> > +         15M     3656 mm/readahead.c:247 func:page_cache_ra_unbounded
> > +         55M     4887 mm/slub.c:2259 func:alloc_slab_page
> > +        122M    31168 mm/page_ext.c:270 func:alloc_page_ext
> > +===================
> > +Theory of operation
> > +===================
> > +
> > +Memory allocation profiling builds off of code tagging, which is a library for
> > +declaring static structs (that typcially describe a file and line number in
>
>                                   typically
>
> > +some way, hence code tagging) and then finding and operating on them at runtime
>
>                                                                         at runtime,
>
> > +- i.e. iterating over them to print them in debugfs/procfs.
>
>   i.e., iterating
>
> > +
> > +To add accounting for an allocation call, we replace it with a macro
> > +invocation, alloc_hooks(), that
> > + - declares a code tag
> > + - stashes a pointer to it in task_struct
> > + - calls the real allocation function
> > + - and finally, restores the task_struct alloc tag pointer to its previous value.
> > +
> > +This allows for alloc_hooks() calls to be nested, with the most recent one
> > +taking effect. This is important for allocations internal to the mm/ code that
> > +do not properly belong to the outer allocation context and should be counted
> > +separately: for example, slab object extension vectors, or when the slab
> > +allocates pages from the page allocator.
> > +
> > +Thus, proper usage requires determining which function in an allocation call
> > +stack should be tagged. There are many helper functions that essentially wrap
> > +e.g. kmalloc() and do a little more work, then are called in multiple places;
> > +we'll generally want the accounting to happen in the callers of these helpers,
> > +not in the helpers themselves.
> > +
> > +To fix up a given helper, for example foo(), do the following:
> > + - switch its allocation call to the _noprof() version, e.g. kmalloc_noprof()
> > + - rename it to foo_noprof()
> > + - define a macro version of foo() like so:
> > +   #define foo(...) alloc_hooks(foo_noprof(__VA_ARGS__))
> > +
> > +It's also possible to stash a pointer to an alloc tag in your own data structures.
> > +
> > +Do this when you're implementing a generic data structure that does allocations
> > +"on behalf of" some other code - for example, the rhashtable code. This way,
> > +instead of seeing a large line in /proc/allocinfo for rhashtable.c, we can
> > +break it out by rhashtable type.
> > +
> > +To do so:
> > + - Hook your data structure's init function, like any other allocation function
>
> maybe end the line above with a '.' like the following line.
>
> > + - Within your init function, use the convenience macro alloc_tag_record() to
> > +   record alloc tag in your data structure.
> > + - Then, use the following form for your allocations:
> > +   alloc_hooks_tag(ht->your_saved_tag, kmalloc_noprof(...))
>
>
> Finally, there are a number of documentation build warnings in this patch.
> I'm no ReST expert, but the attached patch fixes them for me.

Thanks Randy! I'll use your cleaned-up patch in the next submission.
Cheers,
Suren.

>
> --
> #Randy
Kent Overstreet March 7, 2024, 6:17 p.m. UTC | #3
On Wed, Mar 06, 2024 at 07:18:57PM -0800, Randy Dunlap wrote:
> Hi,
> This includes some editing suggestions and some doc build fixes.
> 
> 
> On 3/6/24 10:24, Suren Baghdasaryan wrote:
> > From: Kent Overstreet <kent.overstreet@linux.dev>
> > 
> > Provide documentation for memory allocation profiling.
> > 
> > Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
> > Signed-off-by: Suren Baghdasaryan <surenb@google.com>
> > ---
> >  Documentation/mm/allocation-profiling.rst | 91 +++++++++++++++++++++++
> >  1 file changed, 91 insertions(+)
> >  create mode 100644 Documentation/mm/allocation-profiling.rst
> > 
> > diff --git a/Documentation/mm/allocation-profiling.rst b/Documentation/mm/allocation-profiling.rst
> > new file mode 100644
> > index 000000000000..8a862c7d3aab
> > --- /dev/null
> > +++ b/Documentation/mm/allocation-profiling.rst
> > @@ -0,0 +1,91 @@
> > +.. SPDX-License-Identifier: GPL-2.0
> > +
> > +===========================
> > +MEMORY ALLOCATION PROFILING
> > +===========================
> > +
> > +Low overhead (suitable for production) accounting of all memory allocations,
> > +tracked by file and line number.
> > +
> > +Usage:
> > +kconfig options:
> > + - CONFIG_MEM_ALLOC_PROFILING
> > + - CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT
> > + - CONFIG_MEM_ALLOC_PROFILING_DEBUG
> > +   adds warnings for allocations that weren't accounted because of a
> > +   missing annotation
> > +
> > +Boot parameter:
> > +  sysctl.vm.mem_profiling=0|1|never
> > +
> > +  When set to "never", memory allocation profiling overheads is minimized and it
> 
>                                                       overhead is
> 
> > +  cannot be enabled at runtime (sysctl becomes read-only).
> > +  When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=y, default value is "1".
> > +  When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=n, default value is "never".
> > +
> > +sysctl:
> > +  /proc/sys/vm/mem_profiling
> > +
> > +Runtime info:
> > +  /proc/allocinfo
> > +
> > +Example output:
> > +  root@moria-kvm:~# sort -g /proc/allocinfo|tail|numfmt --to=iec
> > +        2.8M    22648 fs/kernfs/dir.c:615 func:__kernfs_new_node
> > +        3.8M      953 mm/memory.c:4214 func:alloc_anon_folio
> > +        4.0M     1010 drivers/staging/ctagmod/ctagmod.c:20 [ctagmod] func:ctagmod_start
> > +        4.1M        4 net/netfilter/nf_conntrack_core.c:2567 func:nf_ct_alloc_hashtable
> > +        6.0M     1532 mm/filemap.c:1919 func:__filemap_get_folio
> > +        8.8M     2785 kernel/fork.c:307 func:alloc_thread_stack_node
> > +         13M      234 block/blk-mq.c:3421 func:blk_mq_alloc_rqs
> > +         14M     3520 mm/mm_init.c:2530 func:alloc_large_system_hash
> > +         15M     3656 mm/readahead.c:247 func:page_cache_ra_unbounded
> > +         55M     4887 mm/slub.c:2259 func:alloc_slab_page
> > +        122M    31168 mm/page_ext.c:270 func:alloc_page_ext
> > +===================
> > +Theory of operation
> > +===================
> > +
> > +Memory allocation profiling builds off of code tagging, which is a library for
> > +declaring static structs (that typcially describe a file and line number in
> 
>                                   typically
> 
> > +some way, hence code tagging) and then finding and operating on them at runtime
> 
>                                                                         at runtime,
> 
> > +- i.e. iterating over them to print them in debugfs/procfs.
> 
>   i.e., iterating

i.e. latin id est, that is: grammatically my version is fine

> 
> > +
> > +To add accounting for an allocation call, we replace it with a macro
> > +invocation, alloc_hooks(), that
> > + - declares a code tag
> > + - stashes a pointer to it in task_struct
> > + - calls the real allocation function
> > + - and finally, restores the task_struct alloc tag pointer to its previous value.
> > +
> > +This allows for alloc_hooks() calls to be nested, with the most recent one
> > +taking effect. This is important for allocations internal to the mm/ code that
> > +do not properly belong to the outer allocation context and should be counted
> > +separately: for example, slab object extension vectors, or when the slab
> > +allocates pages from the page allocator.
> > +
> > +Thus, proper usage requires determining which function in an allocation call
> > +stack should be tagged. There are many helper functions that essentially wrap
> > +e.g. kmalloc() and do a little more work, then are called in multiple places;
> > +we'll generally want the accounting to happen in the callers of these helpers,
> > +not in the helpers themselves.
> > +
> > +To fix up a given helper, for example foo(), do the following:
> > + - switch its allocation call to the _noprof() version, e.g. kmalloc_noprof()
> > + - rename it to foo_noprof()
> > + - define a macro version of foo() like so:
> > +   #define foo(...) alloc_hooks(foo_noprof(__VA_ARGS__))
> > +
> > +It's also possible to stash a pointer to an alloc tag in your own data structures.
> > +
> > +Do this when you're implementing a generic data structure that does allocations
> > +"on behalf of" some other code - for example, the rhashtable code. This way,
> > +instead of seeing a large line in /proc/allocinfo for rhashtable.c, we can
> > +break it out by rhashtable type.
> > +
> > +To do so:
> > + - Hook your data structure's init function, like any other allocation function
> 
> maybe end the line above with a '.' like the following line.
> 
> > + - Within your init function, use the convenience macro alloc_tag_record() to
> > +   record alloc tag in your data structure.
> > + - Then, use the following form for your allocations:
> > +   alloc_hooks_tag(ht->your_saved_tag, kmalloc_noprof(...))
> 
> 
> Finally, there are a number of documentation build warnings in this patch.
> I'm no ReST expert, but the attached patch fixes them for me.
> 
> -- 
> #Randy
Randy Dunlap March 7, 2024, 7:58 p.m. UTC | #4
On 3/7/24 08:51, Suren Baghdasaryan wrote:
> On Thu, Mar 7, 2024 at 3:19 AM Randy Dunlap <rdunlap@infradead.org> wrote:
>>
>> Hi,
>> This includes some editing suggestions and some doc build fixes.
>>
>>

[snip]

>>
>>
>> Finally, there are a number of documentation build warnings in this patch.
>> I'm no ReST expert, but the attached patch fixes them for me.
> 
> Thanks Randy! I'll use your cleaned-up patch in the next submission.
> Cheers,
> Suren.

Hi Suren,

The patch did not include the grammar/punctuation changes, only the
doc build changes.

I can make a more complete patch if you like.

thanks.
Randy Dunlap March 7, 2024, 8:03 p.m. UTC | #5
On 3/7/24 10:17, Kent Overstreet wrote:
> On Wed, Mar 06, 2024 at 07:18:57PM -0800, Randy Dunlap wrote:
>> Hi,
>> This includes some editing suggestions and some doc build fixes.
>>
>>

[snip]

>>> +===================
>>> +Theory of operation
>>> +===================
>>> +
>>> +Memory allocation profiling builds off of code tagging, which is a library for
>>> +declaring static structs (that typcially describe a file and line number in
>>
>>                                   typically
>>
>>> +some way, hence code tagging) and then finding and operating on them at runtime
>>
>>                                                                         at runtime,
>>
>>> +- i.e. iterating over them to print them in debugfs/procfs.
>>
>>   i.e., iterating
> 
> i.e. latin id est, that is: grammatically my version is fine
> 

Some of my web search hits say that a comma is required after "i.e.".
At least one of them says that it is optional.
And one says that it is not required in British English.

But writing it with "that is":


hence code tagging) and then finding and operating on them at runtime
- that is iterating over them to print them in debugfs/procfs.

is not good IMO. But it's your document.
John Hubbard March 7, 2024, 8:15 p.m. UTC | #6
On 3/7/24 12:03, Randy Dunlap wrote:
> On 3/7/24 10:17, Kent Overstreet wrote:
>> On Wed, Mar 06, 2024 at 07:18:57PM -0800, Randy Dunlap wrote:
...
>>>> +- i.e. iterating over them to print them in debugfs/procfs.
>>>
>>>    i.e., iterating
>>
>> i.e. latin id est, that is: grammatically my version is fine
>>
> 
> Some of my web search hits say that a comma is required after "i.e.".
> At least one of them says that it is optional.
> And one says that it is not required in British English.
> 
> But writing it with "that is":
> 
> 
> hence code tagging) and then finding and operating on them at runtime
> - that is iterating over them to print them in debugfs/procfs.
> 
> is not good IMO. But it's your document.
> 

Technical writing often benefits from a small amount redundancy. Short
sentences and repetition of terms are helpful to most readers. And this
also stays out of the more advanced grammatical constructs, as a side
effect.

So, for example, something *approximately* like this, see what you
think:

Memory allocation profiling is based upon code tagging. Code tagging is
a library for declaring static structs (typically by associating a file
and line number with a descriptive string), and then finding and
operating on those structs at runtime. Memory allocation profiling's
runtime operation is simply: print the structs via debugfs/procfs.




thanks,
Randy Dunlap March 7, 2024, 8:53 p.m. UTC | #7
On 3/7/24 12:15, John Hubbard wrote:
> On 3/7/24 12:03, Randy Dunlap wrote:
>> On 3/7/24 10:17, Kent Overstreet wrote:
>>> On Wed, Mar 06, 2024 at 07:18:57PM -0800, Randy Dunlap wrote:
> ...
>>>>> +- i.e. iterating over them to print them in debugfs/procfs.
>>>>
>>>>    i.e., iterating
>>>
>>> i.e. latin id est, that is: grammatically my version is fine
>>>
>>
>> Some of my web search hits say that a comma is required after "i.e.".
>> At least one of them says that it is optional.
>> And one says that it is not required in British English.
>>
>> But writing it with "that is":
>>
>>
>> hence code tagging) and then finding and operating on them at runtime
>> - that is iterating over them to print them in debugfs/procfs.
>>
>> is not good IMO. But it's your document.
>>
> 
> Technical writing often benefits from a small amount redundancy. Short
> sentences and repetition of terms are helpful to most readers. And this
> also stays out of the more advanced grammatical constructs, as a side
> effect.
> 
> So, for example, something *approximately* like this, see what you
> think:
> 
> Memory allocation profiling is based upon code tagging. Code tagging is
> a library for declaring static structs (typically by associating a file
> and line number with a descriptive string), and then finding and
> operating on those structs at runtime. Memory allocation profiling's
> runtime operation is simply: print the structs via debugfs/procfs.

Works for me.  Thanks.
diff mbox series

Patch

diff --git a/Documentation/mm/allocation-profiling.rst b/Documentation/mm/allocation-profiling.rst
new file mode 100644
index 000000000000..8a862c7d3aab
--- /dev/null
+++ b/Documentation/mm/allocation-profiling.rst
@@ -0,0 +1,91 @@ 
+.. SPDX-License-Identifier: GPL-2.0
+
+===========================
+MEMORY ALLOCATION PROFILING
+===========================
+
+Low overhead (suitable for production) accounting of all memory allocations,
+tracked by file and line number.
+
+Usage:
+kconfig options:
+ - CONFIG_MEM_ALLOC_PROFILING
+ - CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT
+ - CONFIG_MEM_ALLOC_PROFILING_DEBUG
+   adds warnings for allocations that weren't accounted because of a
+   missing annotation
+
+Boot parameter:
+  sysctl.vm.mem_profiling=0|1|never
+
+  When set to "never", memory allocation profiling overheads is minimized and it
+  cannot be enabled at runtime (sysctl becomes read-only).
+  When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=y, default value is "1".
+  When CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=n, default value is "never".
+
+sysctl:
+  /proc/sys/vm/mem_profiling
+
+Runtime info:
+  /proc/allocinfo
+
+Example output:
+  root@moria-kvm:~# sort -g /proc/allocinfo|tail|numfmt --to=iec
+        2.8M    22648 fs/kernfs/dir.c:615 func:__kernfs_new_node
+        3.8M      953 mm/memory.c:4214 func:alloc_anon_folio
+        4.0M     1010 drivers/staging/ctagmod/ctagmod.c:20 [ctagmod] func:ctagmod_start
+        4.1M        4 net/netfilter/nf_conntrack_core.c:2567 func:nf_ct_alloc_hashtable
+        6.0M     1532 mm/filemap.c:1919 func:__filemap_get_folio
+        8.8M     2785 kernel/fork.c:307 func:alloc_thread_stack_node
+         13M      234 block/blk-mq.c:3421 func:blk_mq_alloc_rqs
+         14M     3520 mm/mm_init.c:2530 func:alloc_large_system_hash
+         15M     3656 mm/readahead.c:247 func:page_cache_ra_unbounded
+         55M     4887 mm/slub.c:2259 func:alloc_slab_page
+        122M    31168 mm/page_ext.c:270 func:alloc_page_ext
+===================
+Theory of operation
+===================
+
+Memory allocation profiling builds off of code tagging, which is a library for
+declaring static structs (that typcially describe a file and line number in
+some way, hence code tagging) and then finding and operating on them at runtime
+- i.e. iterating over them to print them in debugfs/procfs.
+
+To add accounting for an allocation call, we replace it with a macro
+invocation, alloc_hooks(), that
+ - declares a code tag
+ - stashes a pointer to it in task_struct
+ - calls the real allocation function
+ - and finally, restores the task_struct alloc tag pointer to its previous value.
+
+This allows for alloc_hooks() calls to be nested, with the most recent one
+taking effect. This is important for allocations internal to the mm/ code that
+do not properly belong to the outer allocation context and should be counted
+separately: for example, slab object extension vectors, or when the slab
+allocates pages from the page allocator.
+
+Thus, proper usage requires determining which function in an allocation call
+stack should be tagged. There are many helper functions that essentially wrap
+e.g. kmalloc() and do a little more work, then are called in multiple places;
+we'll generally want the accounting to happen in the callers of these helpers,
+not in the helpers themselves.
+
+To fix up a given helper, for example foo(), do the following:
+ - switch its allocation call to the _noprof() version, e.g. kmalloc_noprof()
+ - rename it to foo_noprof()
+ - define a macro version of foo() like so:
+   #define foo(...) alloc_hooks(foo_noprof(__VA_ARGS__))
+
+It's also possible to stash a pointer to an alloc tag in your own data structures.
+
+Do this when you're implementing a generic data structure that does allocations
+"on behalf of" some other code - for example, the rhashtable code. This way,
+instead of seeing a large line in /proc/allocinfo for rhashtable.c, we can
+break it out by rhashtable type.
+
+To do so:
+ - Hook your data structure's init function, like any other allocation function
+ - Within your init function, use the convenience macro alloc_tag_record() to
+   record alloc tag in your data structure.
+ - Then, use the following form for your allocations:
+   alloc_hooks_tag(ht->your_saved_tag, kmalloc_noprof(...))