[2/2] Document the M_ARENA_* mallopt parameters

Message ID 1476120388-26662-2-git-send-email-siddhesh@sourceware.org
State Committed
Headers

Commit Message

Siddhesh Poyarekar Oct. 10, 2016, 5:26 p.m. UTC
  The M_ARENA_* mallopt parameters are in wide use in production to
control the number of arenas that a long lived process creates and
hence there is no point in stating that this interface is non-public.
Document this interface and remove the obsolete comment.

	* manual/memory.texi (M_ARENA_TEST): Add documentation.
	(M_ARENA_MAX): Likewise.
	* malloc/malloc.c: Remove obsolete comment.
---
 malloc/malloc.c    |  1 -
 manual/memory.texi | 21 +++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)
  

Comments

Siddhesh Poyarekar Oct. 17, 2016, 2:04 p.m. UTC | #1
Ping!

On Monday 10 October 2016 10:56 PM, Siddhesh Poyarekar wrote:
> The M_ARENA_* mallopt parameters are in wide use in production to
> control the number of arenas that a long lived process creates and
> hence there is no point in stating that this interface is non-public.
> Document this interface and remove the obsolete comment.
> 
> 	* manual/memory.texi (M_ARENA_TEST): Add documentation.
> 	(M_ARENA_MAX): Likewise.
> 	* malloc/malloc.c: Remove obsolete comment.
> ---
>  malloc/malloc.c    |  1 -
>  manual/memory.texi | 21 +++++++++++++++++++++
>  2 files changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 09e004b..0011a6d 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -1718,7 +1718,6 @@ static struct malloc_par mp_ =
>  };
>  
>  
> -/*  Non public mallopt parameters.  */
>  #define M_ARENA_TEST -7
>  #define M_ARENA_MAX  -8
>  
> diff --git a/manual/memory.texi b/manual/memory.texi
> index 222f126..b98dcf2 100644
> --- a/manual/memory.texi
> +++ b/manual/memory.texi
> @@ -1153,6 +1153,27 @@ order to return memory to the system.
>  
>  This parameter can also be set for the process at startup by setting the
>  environment variable @code{MALLOC_TRIM_THRESHOLD_} to the desired value.
> +
> +@item M_ARENA_TEST
> +An arena is a memory pool that is allocated to act as a heap alongside the
> +system heap that the kernel creates for the process.  This is to provide
> +multiple heap structures for multiple threads of a process to reduce contention
> +between them.  The limit to the number of such arenas per process is determined
> +by the number of cores of the system and whether it is a 32-bit or a 64-bit
> +processor.
> +
> +The value is ignored if @code{M_ARENA_MAX} is set either via @code{mallopt} or
> +via the @code{MALLOC_ARENA_MAX} environment variable.
> +
> +This parameter can also be set for the process at startup by setting the
> +environment variable @code{MALLOC_ARENA_TEST} to the desired value.
> +
> +@item M_ARENA_MAX
> +This parameter sets the number of arenas to use regardless of the number of
> +cores in the system.
> +
> +This parameter can also be set for the process at startup by setting the
> +environment variable @code{MALLOC_ARENA_MAX} to the desired value.
>  @end table
>  
>  @end deftypefun
>
  
Carlos O'Donell Oct. 17, 2016, 4:08 p.m. UTC | #2
On 10/10/2016 01:26 PM, Siddhesh Poyarekar wrote:
> The M_ARENA_* mallopt parameters are in wide use in production to
> control the number of arenas that a long lived process creates and
> hence there is no point in stating that this interface is non-public.
> Document this interface and remove the obsolete comment.
> 
> 	* manual/memory.texi (M_ARENA_TEST): Add documentation.
> 	(M_ARENA_MAX): Likewise.
> 	* malloc/malloc.c: Remove obsolete comment.
> ---
>  malloc/malloc.c    |  1 -
>  manual/memory.texi | 21 +++++++++++++++++++++
>  2 files changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 09e004b..0011a6d 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -1718,7 +1718,6 @@ static struct malloc_par mp_ =
>  };
>  
>  
> -/*  Non public mallopt parameters.  */
>  #define M_ARENA_TEST -7
>  #define M_ARENA_MAX  -8
>  
> diff --git a/manual/memory.texi b/manual/memory.texi
> index 222f126..b98dcf2 100644
> --- a/manual/memory.texi
> +++ b/manual/memory.texi
> @@ -1153,6 +1153,27 @@ order to return memory to the system.
>  
>  This parameter can also be set for the process at startup by setting the
>  environment variable @code{MALLOC_TRIM_THRESHOLD_} to the desired value.
> +
> +@item M_ARENA_TEST

This description of an arena doesn't belong here, it belongs higher up in the
manual, and in fact I would suggest the following:

- Move 3.2.2.6 "Efficiency considerations for malloc" up to just under
  "Dynamic Memory allocation" and put it under a new subsection "The GNU allocator".

- Under "The GNU allocator" give a brief 1 paragraph description of how
  the allocator works e.g. https://sourceware.org/glibc/wiki/MallocInternals
  and talk about arenas.

> +An arena is a memory pool that is allocated to act as a heap alongside the
> +system heap that the kernel creates for the process.  This is to provide
> +multiple heap structures for multiple threads of a process to reduce contention
> +between them.  The limit to the number of such arenas per process is determined
> +by the number of cores of the system and whether it is a 32-bit or a 64-bit
> +processor.

You don't say what M_ARENA_TEST is for?

> +
> +The value is ignored if @code{M_ARENA_MAX} is set either via @code{mallopt} or
> +via the @code{MALLOC_ARENA_MAX} environment variable.
> +
> +This parameter can also be set for the process at startup by setting the
> +environment variable @code{MALLOC_ARENA_TEST} to the desired value.

What is the default?

> +
> +@item M_ARENA_MAX
> +This parameter sets the number of arenas to use regardless of the number of
> +cores in the system.
> +
> +This parameter can also be set for the process at startup by setting the
> +environment variable @code{MALLOC_ARENA_MAX} to the desired value.

What is the default?

>  @end table
>  
>  @end deftypefun
>
  
Michael Kerrisk \(man-pages\) Oct. 18, 2016, 7:15 a.m. UTC | #3
On Mon, Oct 17, 2016 at 6:08 PM, Carlos O'Donell <carlos@redhat.com> wrote:
> On 10/10/2016 01:26 PM, Siddhesh Poyarekar wrote:
>> The M_ARENA_* mallopt parameters are in wide use in production to
>> control the number of arenas that a long lived process creates and
>> hence there is no point in stating that this interface is non-public.
>> Document this interface and remove the obsolete comment.
>>
>>       * manual/memory.texi (M_ARENA_TEST): Add documentation.
>>       (M_ARENA_MAX): Likewise.
>>       * malloc/malloc.c: Remove obsolete comment.
>> ---
>>  malloc/malloc.c    |  1 -
>>  manual/memory.texi | 21 +++++++++++++++++++++
>>  2 files changed, 21 insertions(+), 1 deletion(-)
>>
>> diff --git a/malloc/malloc.c b/malloc/malloc.c
>> index 09e004b..0011a6d 100644
>> --- a/malloc/malloc.c
>> +++ b/malloc/malloc.c
>> @@ -1718,7 +1718,6 @@ static struct malloc_par mp_ =
>>  };
>>
>>
>> -/*  Non public mallopt parameters.  */
>>  #define M_ARENA_TEST -7
>>  #define M_ARENA_MAX  -8
>>
>> diff --git a/manual/memory.texi b/manual/memory.texi
>> index 222f126..b98dcf2 100644
>> --- a/manual/memory.texi
>> +++ b/manual/memory.texi
>> @@ -1153,6 +1153,27 @@ order to return memory to the system.
>>
>>  This parameter can also be set for the process at startup by setting the
>>  environment variable @code{MALLOC_TRIM_THRESHOLD_} to the desired value.
>> +
>> +@item M_ARENA_TEST
>
> This description of an arena doesn't belong here, it belongs higher up in the
> manual, and in fact I would suggest the following:
>
> - Move 3.2.2.6 "Efficiency considerations for malloc" up to just under
>   "Dynamic Memory allocation" and put it under a new subsection "The GNU allocator".
>
> - Under "The GNU allocator" give a brief 1 paragraph description of how
>   the allocator works e.g. https://sourceware.org/glibc/wiki/MallocInternals
>   and talk about arenas.
>
>> +An arena is a memory pool that is allocated to act as a heap alongside the
>> +system heap that the kernel creates for the process.  This is to provide
>> +multiple heap structures for multiple threads of a process to reduce contention
>> +between them.  The limit to the number of such arenas per process is determined
>> +by the number of cores of the system and whether it is a 32-bit or a 64-bit
>> +processor.
>
> You don't say what M_ARENA_TEST is for?
>
>> +
>> +The value is ignored if @code{M_ARENA_MAX} is set either via @code{mallopt} or
>> +via the @code{MALLOC_ARENA_MAX} environment variable.
>> +
>> +This parameter can also be set for the process at startup by setting the
>> +environment variable @code{MALLOC_ARENA_TEST} to the desired value.
>
> What is the default?

So my reading from malloc/malloc.c:

#define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
  .arena_test = NARENAS_FROM_NCORES (1)

So, the default value for this parameter is 2 on systems where
sizeof(long) is 4; otherwise the default value is 8.

>> +
>> +@item M_ARENA_MAX
>> +This parameter sets the number of arenas to use regardless of the number of
>> +cores in the system.
>> +
>> +This parameter can also be set for the process at startup by setting the
>> +environment variable @code{MALLOC_ARENA_MAX} to the desired value.
>
> What is the default?

So, IIUC, the default value of this parameter is 0, meaning that there
is no limit on the number of arenas that can be created. Do you
confirm, Siddhesh?

Siddhesh, in case you want to use any of my wordings (assuming they
are correct), I place them in the public domain. (The text will also
land in the mallopt(3) manual page.)

Cheers,

Michael
  
Siddhesh Poyarekar Oct. 18, 2016, 10:07 a.m. UTC | #4
On Tuesday 18 October 2016 12:45 PM, Michael Kerrisk wrote:
> So my reading from malloc/malloc.c:
> 
> #define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
>   .arena_test = NARENAS_FROM_NCORES (1)
> 
> So, the default value for this parameter is 2 on systems where
> sizeof(long) is 4; otherwise the default value is 8.

That is correct.

> So, IIUC, the default value of this parameter is 0, meaning that there
> is no limit on the number of arenas that can be created. Do you
> confirm, Siddhesh?

No, the default is a function of the number of cores using the
NARENAS_FROM_NCORES macro.  That is, 2 * (number of cores) where
sizeof(long) == 4 and 8 * (number of cores) otherwise.  If the number of
cores is not available (i.e. we can't read this info for some reason)
then we default to 4 and 16 respectively, i.e. assume 2 cores.

Note that this default only comes into force once the number of arenas
cross arena_test.

> Siddhesh, in case you want to use any of my wordings (assuming they
> are correct), I place them in the public domain. (The text will also
> land in the mallopt(3) manual page.)

Thanks.

Siddhesh
  
Michael Kerrisk \(man-pages\) Oct. 18, 2016, 1:50 p.m. UTC | #5
Hi Siddhesh,

On 10/18/2016 12:07 PM, Siddhesh Poyarekar wrote:
> On Tuesday 18 October 2016 12:45 PM, Michael Kerrisk wrote:
>> So my reading from malloc/malloc.c:
>>
>> #define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
>>   .arena_test = NARENAS_FROM_NCORES (1)
>>
>> So, the default value for this parameter is 2 on systems where
>> sizeof(long) is 4; otherwise the default value is 8.
> 
> That is correct.

Thanks for the confirmation.

[You've over trimmed the mail for this next piece. To be clear, below,
we are talking about M_ARENA_MAX; or at least I was.]

>> So, IIUC, the default value of this parameter is 0, meaning that there
>> is no limit on the number of arenas that can be created. Do you
>> confirm, Siddhesh?
> 
> No, the default is a function of the number of cores using the
> NARENAS_FROM_NCORES macro.  That is, 2 * (number of cores) where
> sizeof(long) == 4 and 8 * (number of cores) otherwise.  If the number of
> cores is not available (i.e. we can't read this info for some reason)
> then we default to 4 and 16 respectively, i.e. assume 2 cores.
> 
> Note that this default only comes into force once the number of arenas
> cross arena_test.

I don't think you're correct here. 'arena_max' is a field in a static
structure that is not otherwise initialized, AFAICT. So, it has the
value zero. (Some dirty hacking with a program that uses
malloc_get_state() and inspects the internal data structure seems
to confirm this.)

And then in malloc/arena.c we have

          if (mp_.arena_max != 0)
            narenas_limit = mp_.arena_max;
          else if (narenas > mp_.arena_test)
            {
              int n = __get_nprocs ();
              
              if (n >= 1)
                narenas_limit = NARENAS_FROM_NCORES (n);
              else
                /* We have no information about the system.  Assume two
                   cores.  */ 
                narenas_limit = NARENAS_FROM_NCORES (2);

So, I believe my original statement about M_ARENA_MAX is correct.
Have I missed something?

Cheers,

Michael

>> Siddhesh, in case you want to use any of my wordings (assuming they
>> are correct), I place them in the public domain. (The text will also
>> land in the mallopt(3) manual page.)
> 
> Thanks.
> 
> Siddhesh
>
  
Siddhesh Poyarekar Oct. 18, 2016, 2:30 p.m. UTC | #6
On Tuesday 18 October 2016 07:20 PM, Michael Kerrisk (man-pages) wrote:
> Hi Siddhesh,
> 
> On 10/18/2016 12:07 PM, Siddhesh Poyarekar wrote:
>> On Tuesday 18 October 2016 12:45 PM, Michael Kerrisk wrote:
>>> So my reading from malloc/malloc.c:
>>>
>>> #define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
>>>   .arena_test = NARENAS_FROM_NCORES (1)
>>>
>>> So, the default value for this parameter is 2 on systems where
>>> sizeof(long) is 4; otherwise the default value is 8.
>>
>> That is correct.
> 
> Thanks for the confirmation.
> 
> [You've over trimmed the mail for this next piece. To be clear, below,
> we are talking about M_ARENA_MAX; or at least I was.]
> 
>>> So, IIUC, the default value of this parameter is 0, meaning that there
>>> is no limit on the number of arenas that can be created. Do you
>>> confirm, Siddhesh?
>>
>> No, the default is a function of the number of cores using the
>> NARENAS_FROM_NCORES macro.  That is, 2 * (number of cores) where
>> sizeof(long) == 4 and 8 * (number of cores) otherwise.  If the number of
>> cores is not available (i.e. we can't read this info for some reason)
>> then we default to 4 and 16 respectively, i.e. assume 2 cores.
>>
>> Note that this default only comes into force once the number of arenas
>> cross arena_test.
> 
> I don't think you're correct here. 'arena_max' is a field in a static
> structure that is not otherwise initialized, AFAICT. So, it has the
> value zero. (Some dirty hacking with a program that uses
> malloc_get_state() and inspects the internal data structure seems
> to confirm this.)
> 
> And then in malloc/arena.c we have
> 
>           if (mp_.arena_max != 0)
>             narenas_limit = mp_.arena_max;
>           else if (narenas > mp_.arena_test)
>             {
>               int n = __get_nprocs ();
>               
>               if (n >= 1)
>                 narenas_limit = NARENAS_FROM_NCORES (n);
>               else
>                 /* We have no information about the system.  Assume two
>                    cores.  */ 
>                 narenas_limit = NARENAS_FROM_NCORES (2);
> 
> So, I believe my original statement about M_ARENA_MAX is correct.
> Have I missed something?

You're right in that the variable arena_max is initialized to 0.
However you also concluded that there is no limit to the number of
arenas that can be created when arena_max is 0, which is incorrect.  As
the code snippet you pasted above shows that if arena_max is 0, once we
cross arena_test arenas, the narenas_limit static variable is set to a
default upper limit based on the number of cores.  That acts as the
upper limit to the number of arenas that can be created when arena_max is 0.

Siddhesh
  
Michael Kerrisk \(man-pages\) Oct. 18, 2016, 4:03 p.m. UTC | #7
Hi Siddhesh,

On 10/18/2016 04:30 PM, Siddhesh Poyarekar wrote:
> On Tuesday 18 October 2016 07:20 PM, Michael Kerrisk (man-pages) wrote:
>> Hi Siddhesh,
>>
>> On 10/18/2016 12:07 PM, Siddhesh Poyarekar wrote:
>>> On Tuesday 18 October 2016 12:45 PM, Michael Kerrisk wrote:
>>>> So my reading from malloc/malloc.c:
>>>>
>>>> #define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
>>>>   .arena_test = NARENAS_FROM_NCORES (1)
>>>>
>>>> So, the default value for this parameter is 2 on systems where
>>>> sizeof(long) is 4; otherwise the default value is 8.
>>>
>>> That is correct.
>>
>> Thanks for the confirmation.
>>
>> [You've over trimmed the mail for this next piece. To be clear, below,
>> we are talking about M_ARENA_MAX; or at least I was.]
>>
>>>> So, IIUC, the default value of this parameter is 0, meaning that there
>>>> is no limit on the number of arenas that can be created. Do you
>>>> confirm, Siddhesh?
>>>
>>> No, the default is a function of the number of cores using the
>>> NARENAS_FROM_NCORES macro.  That is, 2 * (number of cores) where
>>> sizeof(long) == 4 and 8 * (number of cores) otherwise.  If the number of
>>> cores is not available (i.e. we can't read this info for some reason)
>>> then we default to 4 and 16 respectively, i.e. assume 2 cores.
>>>
>>> Note that this default only comes into force once the number of arenas
>>> cross arena_test.
>>
>> I don't think you're correct here. 'arena_max' is a field in a static
>> structure that is not otherwise initialized, AFAICT. So, it has the
>> value zero. (Some dirty hacking with a program that uses
>> malloc_get_state() and inspects the internal data structure seems
>> to confirm this.)
>>
>> And then in malloc/arena.c we have
>>
>>           if (mp_.arena_max != 0)
>>             narenas_limit = mp_.arena_max;
>>           else if (narenas > mp_.arena_test)
>>             {
>>               int n = __get_nprocs ();
>>               
>>               if (n >= 1)
>>                 narenas_limit = NARENAS_FROM_NCORES (n);
>>               else
>>                 /* We have no information about the system.  Assume two
>>                    cores.  */ 
>>                 narenas_limit = NARENAS_FROM_NCORES (2);
>>
>> So, I believe my original statement about M_ARENA_MAX is correct.
>> Have I missed something?
> 
> You're right in that the variable arena_max is initialized to 0.

Okay.

> However you also concluded that there is no limit to the number of
> arenas that can be created when arena_max is 0, which is incorrect.  As
> the code snippet you pasted above shows that if arena_max is 0, once we
> cross arena_test arenas, the narenas_limit static variable is set to a
> default upper limit based on the number of cores.  That acts as the
> upper limit to the number of arenas that can be created when arena_max is 0.

D'oh!  Yes, of course. Thanks for that. Not sure how I managed to 
misread that code :-}. So a better formulation would be something like:

    The default value of this parameter is 0, meaning that the limit on 
    the number of arenas is determined according to the setting of
    M_ARENA_TEST.

Seem okay?

Cheers,

Michael
  
Siddhesh Poyarekar Oct. 18, 2016, 4:46 p.m. UTC | #8
On Tuesday 18 October 2016 09:33 PM, Michael Kerrisk (man-pages) wrote:
>>> I don't think you're correct here. 'arena_max' is a field in a static
>>> structure that is not otherwise initialized, AFAICT. So, it has the
>>> value zero. (Some dirty hacking with a program that uses
>>> malloc_get_state() and inspects the internal data structure seems
>>> to confirm this.)
>>>
>>> And then in malloc/arena.c we have
>>>
>>>           if (mp_.arena_max != 0)
>>>             narenas_limit = mp_.arena_max;
>>>           else if (narenas > mp_.arena_test)
>>>             {
>>>               int n = __get_nprocs ();
>>>               
>>>               if (n >= 1)
>>>                 narenas_limit = NARENAS_FROM_NCORES (n);
>>>               else
>>>                 /* We have no information about the system.  Assume two
>>>                    cores.  */ 
>>>                 narenas_limit = NARENAS_FROM_NCORES (2);
>>>
>>> So, I believe my original statement about M_ARENA_MAX is correct.
>>> Have I missed something?
>>
>> You're right in that the variable arena_max is initialized to 0.
> 
> Okay.
> 
>> However you also concluded that there is no limit to the number of
>> arenas that can be created when arena_max is 0, which is incorrect.  As
>> the code snippet you pasted above shows that if arena_max is 0, once we
>> cross arena_test arenas, the narenas_limit static variable is set to a
>> default upper limit based on the number of cores.  That acts as the
>> upper limit to the number of arenas that can be created when arena_max is 0.
> 
> D'oh!  Yes, of course. Thanks for that. Not sure how I managed to 
> misread that code :-}. So a better formulation would be something like:
> 
>     The default value of this parameter is 0, meaning that the limit on 
>     the number of arenas is determined according to the setting of
>     M_ARENA_TEST.

No, it is not the value of M_ARENA_TEST :)

M_ARENA_TEST is set by default to NARENAS_FROM_CORES(1).  The limit on
the number of arenas is decided after M_ARENA_TEST number of arenas have
already created, but it is actually set to NARENAS_FROM_CORES(n), where
n is the number of cores.  If we can't find the number of cores for some
reason, then we set the limit to NARENAS_FROM_CORES(2).

So something like this is more accurate:

    The default value of this parameter is 0, meaning that the limit on
    the number of arenas is determined by the number of CPU cores
    online and the size of the '''long''' datatype.  For 32-bit systems
    the limit of on the number of arenas is 2 * '''number of CPU cores
    online''' while 64-bit systems, the limit on the number of arenas
    is 8 * '''number of CPU cores online'''.  If information on CPU
    cores is not available, it is assumed that there are 2 CPU cores
    online.

I have implicitly stated here that 32-bit long == 32-bit pointers since
I don't think there are Unix systems that have 32-bit long and 64-bit
pointers and also because the choice of multipliers for cores (2 and 8)
correlates better to the size of the address space than to size of long.

Siddhesh
  
Andreas Schwab Oct. 18, 2016, 5:18 p.m. UTC | #9
On Okt 18 2016, Siddhesh Poyarekar <siddhesh@sourceware.org> wrote:

> So something like this is more accurate:
>
>     The default value of this parameter is 0, meaning that the limit on
>     the number of arenas is determined by the number of CPU cores
>     online and the size of the '''long''' datatype.  For 32-bit systems
>     the limit of on the number of arenas is 2 * '''number of CPU cores
                                              twice the
>     online''' while 64-bit systems, the limit on the number of arenas
>     is 8 * '''number of CPU cores online'''.  If information on CPU
         eight times the
>     cores is not available, it is assumed that there are 2 CPU cores
>     online.

Andreas.
  
Michael Kerrisk \(man-pages\) Oct. 19, 2016, 6:53 a.m. UTC | #10
Hi Siddhesh,

On 10/18/2016 06:46 PM, Siddhesh Poyarekar wrote:
> On Tuesday 18 October 2016 09:33 PM, Michael Kerrisk (man-pages) wrote:
>>>> I don't think you're correct here. 'arena_max' is a field in a static
>>>> structure that is not otherwise initialized, AFAICT. So, it has the
>>>> value zero. (Some dirty hacking with a program that uses
>>>> malloc_get_state() and inspects the internal data structure seems
>>>> to confirm this.)
>>>>
>>>> And then in malloc/arena.c we have
>>>>
>>>>           if (mp_.arena_max != 0)
>>>>             narenas_limit = mp_.arena_max;
>>>>           else if (narenas > mp_.arena_test)
>>>>             {
>>>>               int n = __get_nprocs ();
>>>>               
>>>>               if (n >= 1)
>>>>                 narenas_limit = NARENAS_FROM_NCORES (n);
>>>>               else
>>>>                 /* We have no information about the system.  Assume two
>>>>                    cores.  */ 
>>>>                 narenas_limit = NARENAS_FROM_NCORES (2);
>>>>
>>>> So, I believe my original statement about M_ARENA_MAX is correct.
>>>> Have I missed something?
>>>
>>> You're right in that the variable arena_max is initialized to 0.
>>
>> Okay.
>>
>>> However you also concluded that there is no limit to the number of
>>> arenas that can be created when arena_max is 0, which is incorrect.  As
>>> the code snippet you pasted above shows that if arena_max is 0, once we
>>> cross arena_test arenas, the narenas_limit static variable is set to a
>>> default upper limit based on the number of cores.  That acts as the
>>> upper limit to the number of arenas that can be created when arena_max is 0.
>>
>> D'oh!  Yes, of course. Thanks for that. Not sure how I managed to 
>> misread that code :-}. So a better formulation would be something like:
>>
>>     The default value of this parameter is 0, meaning that the limit on 
>>     the number of arenas is determined according to the setting of
>>     M_ARENA_TEST.
> 
> No, it is not the value of M_ARENA_TEST :)

I agree. But it's also not what I said ;-). I said "determined according
to the value of..."

Currently, the M_ARENA_TEST text in mallopt(3) says:

       M_ARENA_TEST
              This  parameter specifies a value, in number of arenas cre‐
              ated, at which point the system configuration will be exam‐
              ined  to  determine  a  hard limit on the number of created
              arenas.  (See M_ARENA_MAX for the definition of an arena.)

              The computation of the arena hard limit is  implementation-
              defined and is usually calculated as a multiple of the num‐
              ber of available CPUs.  Once the hard  limit  is  computed,
              the result is final and constrains the total number of are‐
              nas.

              The default value for the M_ARENA_TEST parameter  is  2  on
              systems  where  sizeof(long)  is  4;  otherwise the default
              value is 8.

              This parameter has been  available  since  glibc  2.10  via
              --enable-experimental-malloc,   and  since  glibc  2.15  by
              default.

              The value of M_ARENA_TEST is not used when M_ARENA_MAX  has
              a nonzero value.

> M_ARENA_TEST is set by default to NARENAS_FROM_CORES(1).  The limit on
> the number of arenas is decided after M_ARENA_TEST number of arenas have
> already created, but it is actually set to NARENAS_FROM_CORES(n), where
> n is the number of cores.  If we can't find the number of cores for some
> reason, then we set the limit to NARENAS_FROM_CORES(2).
> 
> So something like this is more accurate:
> 
>     The default value of this parameter is 0, meaning that the limit on
>     the number of arenas is determined by the number of CPU cores
>     online and the size of the '''long''' datatype.  For 32-bit systems
>     the limit of on the number of arenas is 2 * '''number of CPU cores
>     online''' while 64-bit systems, the limit on the number of arenas
>     is 8 * '''number of CPU cores online'''.  If information on CPU
>     cores is not available, it is assumed that there are 2 CPU cores
>     online.

Your details following are a little more precise. But I believe Carlos,
when he wrote the text about how the limit was calculated, deliberately
chose to be more vague. I'm okay with including this level of detail 
in the man page, but, if I recall correctly, Carlos wanted to avoid it.

Cheers,

Michael

> I have implicitly stated here that 32-bit long == 32-bit pointers since
> I don't think there are Unix systems that have 32-bit long and 64-bit
> pointers and also because the choice of multipliers for cores (2 and 8)
> correlates better to the size of the address space than to size of long.
> 
> Siddhesh
>
  
Siddhesh Poyarekar Oct. 19, 2016, 7:09 a.m. UTC | #11
On Wednesday 19 October 2016 12:23 PM, Michael Kerrisk (man-pages) wrote:
> I agree. But it's also not what I said ;-). I said "determined according
> to the value of..."

Ahh, I wouldn't have caught that if you hadn't pointed it out.

> Your details following are a little more precise. But I believe Carlos,
> when he wrote the text about how the limit was calculated, deliberately
> chose to be more vague. I'm okay with including this level of detail 
> in the man page, but, if I recall correctly, Carlos wanted to avoid it.

I'll let Carlos take the call on that.  He asked for detail in the glibc
manual, so I'll propose that level and detail for the manual and see
what he thinks.

Siddhesh
  

Patch

diff --git a/malloc/malloc.c b/malloc/malloc.c
index 09e004b..0011a6d 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1718,7 +1718,6 @@  static struct malloc_par mp_ =
 };
 
 
-/*  Non public mallopt parameters.  */
 #define M_ARENA_TEST -7
 #define M_ARENA_MAX  -8
 
diff --git a/manual/memory.texi b/manual/memory.texi
index 222f126..b98dcf2 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1153,6 +1153,27 @@  order to return memory to the system.
 
 This parameter can also be set for the process at startup by setting the
 environment variable @code{MALLOC_TRIM_THRESHOLD_} to the desired value.
+
+@item M_ARENA_TEST
+An arena is a memory pool that is allocated to act as a heap alongside the
+system heap that the kernel creates for the process.  This is to provide
+multiple heap structures for multiple threads of a process to reduce contention
+between them.  The limit to the number of such arenas per process is determined
+by the number of cores of the system and whether it is a 32-bit or a 64-bit
+processor.
+
+The value is ignored if @code{M_ARENA_MAX} is set either via @code{mallopt} or
+via the @code{MALLOC_ARENA_MAX} environment variable.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @code{MALLOC_ARENA_TEST} to the desired value.
+
+@item M_ARENA_MAX
+This parameter sets the number of arenas to use regardless of the number of
+cores in the system.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @code{MALLOC_ARENA_MAX} to the desired value.
 @end table
 
 @end deftypefun