[v3,1/3] Tunables: Add tunables of spin count for pthread adaptive spin mutex

Message ID 1527067354-13333-1-git-send-email-kemi.wang@intel.com
State New, archived
Headers

Commit Message

Kemi Wang May 23, 2018, 9:22 a.m. UTC
  This patch does not have any functionality change, we only provide a spin
count tunes for pthread adaptive spin mutex. The tunable
glibc.mutex.spin_count tunes can be used by system administrator to squeeze
system performance according to different hardware capabilities and
workload characteristics.

The maximum value of spin count is limited to 30000 to avoid the overflow
of mutex->__data.__spins variable with the possible type of short in
pthread_mutex_lock ().

The default value of spin count is set to 100 with the reference to the
previous number of times of spinning via trylock. This value would be
architecture-specific and can be tuned with kinds of benchmarks to fit most
cases in future.

This is the preparation work for the next patch, in which the way of
adaptive spin would be changed from an expensive cmpxchg to read while
spinning.

   * elf/dl-tunables.list: Add glibc.mutex.spin_count entry.
   * manual/tunables.texi: Add glibc.mutex.spin_count description.
   * nptl/Makefile: Add pthread_mutex_conf.c for compilation.
   * nptl/pthread_mutex_conf.h: New file.
   * nptl/pthread_mutex_conf.c: New file.

ChangeLog:
    V2->V3
    a) Polish the description of glibc.mutex.spin_count tunable with the
    help from Rical Jasan.
    b) Get rid of the TUNABLE_CALLBACK_FNDECL macros in
    pthread_mutex_conf.c, as suggested by Florian Weimer.
    c) Adjust the default value of spin count to 100 with the reference of
    the previous spinning way via trylock.

    V1->V2
    a) Renamed nptl/mutex-conf.h -> nptl/pthread_mutex_conf.h
    b) Renamed nptl/mutex-conf.c -> nptl/pthread_mutex_conf.c
    c) Change the Makefile to compile pthread_mutex_conf.c
    d) Modify the copyright "2013-2018" -> "2018" for new added files
    e) Fix the indentation issue (tab -> double space) in
    elf/dl-tunables.list
    f) Remove the env alias LD_SPIN_COUNT in elf/dl-tunables.list
    g) Fix the typo errors and refresh glibc.mutex.spin_count tunable
    description in manual/tunables.texi.
    h) Fix the indentation issue in nptl/pthread_mutex_conf.c
    i) Fix the indentation issue for nested preprocessor (add one space for
    each level)

Suggested-by: Andi Kleen <andi.kleen@intel.com>
Signed-off-by: Kemi Wang <kemi.wang@intel.com>
---
 ChangeLog                 |  8 +++++
 elf/dl-tunables.list      |  9 ++++++
 manual/tunables.texi      | 22 ++++++++++++++
 nptl/Makefile             |  3 +-
 nptl/pthread_mutex_conf.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
 nptl/pthread_mutex_conf.h | 31 ++++++++++++++++++++
 6 files changed, 146 insertions(+), 1 deletion(-)
 create mode 100644 nptl/pthread_mutex_conf.c
 create mode 100644 nptl/pthread_mutex_conf.h
  

Comments

Szabolcs Nagy June 7, 2018, 1:06 p.m. UTC | #1
On 23/05/18 10:22, Kemi Wang wrote:
> This patch does not have any functionality change, we only provide a spin
> count tunes for pthread adaptive spin mutex. The tunable
> glibc.mutex.spin_count tunes can be used by system administrator to squeeze
> system performance according to different hardware capabilities and
> workload characteristics.
> 
> The maximum value of spin count is limited to 30000 to avoid the overflow
> of mutex->__data.__spins variable with the possible type of short in
> pthread_mutex_lock ().
> 
> The default value of spin count is set to 100 with the reference to the
> previous number of times of spinning via trylock. This value would be
> architecture-specific and can be tuned with kinds of benchmarks to fit most
> cases in future.
> 

i'm not against this tunable, but do ppl use
PTHREAD_MUTEX_ADAPTIVE_NP in practice?

it's a non-standard extension, if the normal mutex is not
good enough that should be fixed (e.g. it should do some
spinning on SMP systems if that's useful in general, the
futex syscall overhead is way bigger than a few atomic loads).
  
Florian Weimer June 7, 2018, 1:09 p.m. UTC | #2
On 05/23/2018 11:22 AM, Kemi Wang wrote:
> +#ifdef SHARED
> +# define INIT_SECTION ".init_array"
> +#else
> +# define INIT_SECTION ".preinit_array"
> +#endif
> +
> +void (*const __pthread_mutex_tunables_init_array []) (int, char **, char **)
> +  __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
> +{
> +  &mutex_tunables_init
> +};


Did you try to get rid of this?

Thanks,
Florian
  
Florian Weimer June 7, 2018, 1:10 p.m. UTC | #3
On 05/23/2018 11:22 AM, Kemi Wang wrote:
> +  mutex {
> +    spin_count {
> +      type: INT_32
> +      minval: 0
> +      maxval: 30000
> +      default: 100
> +    }
> +  }

I think the applicable comments from the commit message should be 
included in here.

Thanks,
Florian
  
Kemi Wang June 7, 2018, 2:58 p.m. UTC | #4
> i'm not against this tunable, but do ppl use PTHREAD_MUTEX_ADAPTIVE_NP in practice?


Absolutely!  Our customers complained to us that  adaptive mutex does not run well on Intel Skylake platform.
I am not a fan of adding code that no one cares. The tuning work is on going with kinds of benchmarks I can get.
If we can find a suitable threshold of spin count to fit most cases in future, I don't mind to remove this tunable. 
But now, it indeed need.

> it's a non-standard extension, if the normal mutex is not good enough that should be fixed (e.g. it should do some spinning on SMP systems if that's useful in general, the futex syscall overhead is way bigger than a few atomic loads).


That is what adaptive mutex does now, spinning for a while before going to block. 
If the adaptive mutex is optimized good enough, maybe we should make it as a default option (e.g. the mutex used in kernel spins for a while before sleep, and it also use mcs lock to queue spinners)

-----Original Message-----
From: libc-alpha-owner@sourceware.org [mailto:libc-alpha-owner@sourceware.org] On Behalf Of Szabolcs Nagy

Sent: Thursday, June 7, 2018 9:07 PM
To: Wang, Kemi <kemi.wang@intel.com>; Adhemerval Zanella <adhemerval.zanella@linaro.org>; Florian Weimer <fweimer@redhat.com>; Rical Jason <rj@2c3t.io>; Carlos Donell <carlos@redhat.com>; Glibc alpha <libc-alpha@sourceware.org>
Cc: nd@arm.com; Dave Hansen <dave.hansen@linux.intel.com>; Chen, Tim C <tim.c.chen@intel.com>; Kleen, Andi <andi.kleen@intel.com>; Huang, Ying <ying.huang@intel.com>; Lu, Aaron <aaron.lu@intel.com>; Li, Aubrey <aubrey.li@intel.com>
Subject: Re: [PATCH v3 1/3] Tunables: Add tunables of spin count for pthread adaptive spin mutex

On 23/05/18 10:22, Kemi Wang wrote:
> This patch does not have any functionality change, we only provide a 

> spin count tunes for pthread adaptive spin mutex. The tunable 

> glibc.mutex.spin_count tunes can be used by system administrator to 

> squeeze system performance according to different hardware 

> capabilities and workload characteristics.

> 

> The maximum value of spin count is limited to 30000 to avoid the 

> overflow of mutex->__data.__spins variable with the possible type of 

> short in pthread_mutex_lock ().

> 

> The default value of spin count is set to 100 with the reference to 

> the previous number of times of spinning via trylock. This value would 

> be architecture-specific and can be tuned with kinds of benchmarks to 

> fit most cases in future.

> 


i'm not against this tunable, but do ppl use PTHREAD_MUTEX_ADAPTIVE_NP in practice?

it's a non-standard extension, if the normal mutex is not good enough that should be fixed (e.g. it should do some spinning on SMP systems if that's useful in general, the futex syscall overhead is way bigger than a few atomic loads).
  
Kemi Wang June 7, 2018, 2:59 p.m. UTC | #5
> Did you try to get rid of this?


I didn't try to get rid of this.
Will  try soon and let you know the result

-----Original Message-----
From: Florian Weimer [mailto:fweimer@redhat.com] 

Sent: Thursday, June 7, 2018 9:09 PM
To: Wang, Kemi <kemi.wang@intel.com>; Adhemerval Zanella <adhemerval.zanella@linaro.org>; Rical Jason <rj@2c3t.io>; Carlos Donell <carlos@redhat.com>; Glibc alpha <libc-alpha@sourceware.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>; Chen, Tim C <tim.c.chen@intel.com>; Kleen, Andi <andi.kleen@intel.com>; Huang, Ying <ying.huang@intel.com>; Lu, Aaron <aaron.lu@intel.com>; Li, Aubrey <aubrey.li@intel.com>
Subject: Re: [PATCH v3 1/3] Tunables: Add tunables of spin count for pthread adaptive spin mutex

On 05/23/2018 11:22 AM, Kemi Wang wrote:
> +#ifdef SHARED

> +# define INIT_SECTION ".init_array"

> +#else

> +# define INIT_SECTION ".preinit_array"

> +#endif

> +

> +void (*const __pthread_mutex_tunables_init_array []) (int, char **, 

> +char **)

> +  __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) 

> += {

> +  &mutex_tunables_init

> +};



Did you try to get rid of this?

Thanks,
Florian
  
Kemi Wang June 7, 2018, 3:02 p.m. UTC | #6
> I think the applicable comments from the commit message should be included in here.


Sure.

BTW,  I plan to make this optimization opt-in, and enable it for x86 architecture as default.
As you suggested before. 

-----Original Message-----
From: Florian Weimer [mailto:fweimer@redhat.com] 

Sent: Thursday, June 7, 2018 9:10 PM
To: Wang, Kemi <kemi.wang@intel.com>; Adhemerval Zanella <adhemerval.zanella@linaro.org>; Rical Jason <rj@2c3t.io>; Carlos Donell <carlos@redhat.com>; Glibc alpha <libc-alpha@sourceware.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>; Chen, Tim C <tim.c.chen@intel.com>; Kleen, Andi <andi.kleen@intel.com>; Huang, Ying <ying.huang@intel.com>; Lu, Aaron <aaron.lu@intel.com>; Li, Aubrey <aubrey.li@intel.com>
Subject: Re: [PATCH v3 1/3] Tunables: Add tunables of spin count for pthread adaptive spin mutex

On 05/23/2018 11:22 AM, Kemi Wang wrote:
> +  mutex {

> +    spin_count {

> +      type: INT_32

> +      minval: 0

> +      maxval: 30000

> +      default: 100

> +    }

> +  }


I think the applicable comments from the commit message should be included in here.

Thanks,
Florian
  
Kemi Wang June 8, 2018, 7:57 a.m. UTC | #7
On 2018年06月07日 21:09, Florian Weimer wrote:
> On 05/23/2018 11:22 AM, Kemi Wang wrote:
>> +#ifdef SHARED
>> +# define INIT_SECTION ".init_array"
>> +#else
>> +# define INIT_SECTION ".preinit_array"
>> +#endif
>> +
>> +void (*const __pthread_mutex_tunables_init_array []) (int, char **, char **)
>> +  __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
>> +{
>> +  &mutex_tunables_init
>> +};
> 
> 
> Did you try to get rid of this?
> 

I remembered you suggested me to put this initialization as part of pthread initialization.

https://sourceware.org/ml/libc-alpha/2018-05/msg00289.html

But, mutex_tunables_init need three parameters such as argc, argv, and env from libc_start_main, 
while the pthread initialization function __pthread_initialize_minimal does not include any parameter.
I don't think we can simply put it as part of overall thread initialization unless we change the API 
of __pthread_initialize_minimal.

Maybe you have better idea.

> Thanks,
> Florian
  
Florian Weimer June 8, 2018, 2:54 p.m. UTC | #8
On 06/08/2018 09:57 AM, kemi wrote:
> 
> 
> On 2018年06月07日 21:09, Florian Weimer wrote:
>> On 05/23/2018 11:22 AM, Kemi Wang wrote:
>>> +#ifdef SHARED
>>> +# define INIT_SECTION ".init_array"
>>> +#else
>>> +# define INIT_SECTION ".preinit_array"
>>> +#endif
>>> +
>>> +void (*const __pthread_mutex_tunables_init_array []) (int, char **, char **)
>>> +  __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
>>> +{
>>> +  &mutex_tunables_init
>>> +};
>>
>>
>> Did you try to get rid of this?
>>
> 
> I remembered you suggested me to put this initialization as part of pthread initialization.
> 
> https://sourceware.org/ml/libc-alpha/2018-05/msg00289.html
> 
> But, mutex_tunables_init need three parameters such as argc, argv, and env from libc_start_main,
> while the pthread initialization function __pthread_initialize_minimal does not include any parameter.
> I don't think we can simply put it as part of overall thread initialization unless we change the API
> of __pthread_initialize_minimal.
> 
> Maybe you have better idea.

I will have a lok at it next week.

We need to do this as part of the main initialization of the library, so 
that the tunable is stripped from the environment if necessary.

Thanks,
Florian
  
Kemi Wang June 14, 2018, 1:36 a.m. UTC | #9
On 2018年06月08日 22:54, Florian Weimer wrote:
> On 06/08/2018 09:57 AM, kemi wrote:
>>
>>
>> On 2018年06月07日 21:09, Florian Weimer wrote:
>>> On 05/23/2018 11:22 AM, Kemi Wang wrote:
>>>> +#ifdef SHARED
>>>> +# define INIT_SECTION ".init_array"
>>>> +#else
>>>> +# define INIT_SECTION ".preinit_array"
>>>> +#endif
>>>> +
>>>> +void (*const __pthread_mutex_tunables_init_array []) (int, char **, char **)
>>>> +  __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
>>>> +{
>>>> +  &mutex_tunables_init
>>>> +};
>>>
>>>
>>> Did you try to get rid of this?
>>>
>>
>> I remembered you suggested me to put this initialization as part of pthread initialization.
>>
>> https://sourceware.org/ml/libc-alpha/2018-05/msg00289.html
>>
>> But, mutex_tunables_init need three parameters such as argc, argv, and env from libc_start_main,
>> while the pthread initialization function __pthread_initialize_minimal does not include any parameter.
>> I don't think we can simply put it as part of overall thread initialization unless we change the API
>> of __pthread_initialize_minimal.
>>
>> Maybe you have better idea.
> 
> I will have a lok at it next week.
> 
> We need to do this as part of the main initialization of the library, so that the tunable is stripped from the environment if necessary.
> 

Do you have any idea for this issue? How about doing it as part of tunable initialization. (__tunables_init).
And could you explain a bit more on the value of this change. Thanks.

> Thanks,
> Florian
  

Patch

diff --git a/ChangeLog b/ChangeLog
index 8032adf..c1e2a44 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@ 
+2018-05-23  Kemi Wang <kemi.wang@intel.com>
+
+	* elf/dl-tunables.list: Add glibc.mutex.spin_count entry.
+	* manual/tunables.texi: Add glibc.mutex.spin_count description.
+	* nptl/Makefile: Add pthread_mutex_conf.c for compilation.
+	* nptl/pthread_mutex_conf.h: New file.
+	* nptl/pthread_mutex_conf.c: New file.
+
 2018-05-23  Andreas Schwab  <schwab@suse.de>
 
 	[BZ #23196]
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
index 1f8ecb8..f1f3546 100644
--- a/elf/dl-tunables.list
+++ b/elf/dl-tunables.list
@@ -121,4 +121,13 @@  glibc {
       default: 3
     }
   }
+
+  mutex {
+    spin_count {
+      type: INT_32
+      minval: 0
+      maxval: 30000
+      default: 100
+    }
+  }
 }
diff --git a/manual/tunables.texi b/manual/tunables.texi
index be33c9f..05c5e4a 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -281,6 +281,28 @@  of try lock attempts.
 The default value of this tunable is @samp{3}.
 @end deftp
 
+@node Pthread Mutex Tunables
+@section Pthread Mutex Tunables
+@cindex pthread mutex tunables
+
+@deftp {Tunable namespace} glibc.mutex
+The behavior of pthread mutexes can be tuned to gain performance improvements
+according to specific hardware capabilities and workload characteristics by
+setting the following tunables in the @code{mutex} namespace:
+@end deftp
+
+@deftp Tunable glibc.mutex.spin_count
+The @code{glibc.mutex.spin_count} tunable sets the maximum number of times
+a thread should spin on the lock before calling into the kernel to block.
+Adaptive spin is used for mutexes initialized with the PTHREAD_MUTEX_ADAPTIVE_NP
+GNU extension.  It affects both pthread_mutex_lock and pthread_mutex_timedlock.
+
+The spinning is done until either the maximum spin times is reached or
+the lock is acquired.
+
+The default value of this tunable is @samp{100}.
+@end deftp
+
 @node Hardware Capability Tunables
 @section Hardware Capability Tunables
 @cindex hardware capability tunables
diff --git a/nptl/Makefile b/nptl/Makefile
index 94be92c..bd1096f 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -139,7 +139,8 @@  libpthread-routines = nptl-init vars events version pt-interp \
 		      pthread_mutex_getprioceiling \
 		      pthread_mutex_setprioceiling \
 		      pthread_setname pthread_getname \
-		      pthread_setattr_default_np pthread_getattr_default_np
+		      pthread_setattr_default_np pthread_getattr_default_np \
+		      pthread_mutex_conf
 #		      pthread_setuid pthread_seteuid pthread_setreuid \
 #		      pthread_setresuid \
 #		      pthread_setgid pthread_setegid pthread_setregid \
diff --git a/nptl/pthread_mutex_conf.c b/nptl/pthread_mutex_conf.c
new file mode 100644
index 0000000..7f9eb23
--- /dev/null
+++ b/nptl/pthread_mutex_conf.c
@@ -0,0 +1,74 @@ 
+/* pthread_mutex_conf.c: Pthread mutex tunable parameters.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include <pthreadP.h>
+#include <init-arch.h>
+#include <pthread_mutex_conf.h>
+#include <unistd.h>
+
+#if HAVE_TUNABLES
+# define TUNABLE_NAMESPACE mutex
+#endif
+#include <elf/dl-tunables.h>
+
+
+struct mutex_config __mutex_aconf =
+{
+  /* The maximum number of times a thread should spin on the lock before
+  calling into kernel to block.  */
+  .spin_count = 100,
+};
+
+#if HAVE_TUNABLES
+static inline void __always_inline
+do_set_mutex_spin_count (int32_t value)
+{
+  __mutex_aconf.spin_count = value;
+}
+
+void
+TUNABLE_CALLBACK (set_mutex_spin_count) (tunable_val_t *valp)
+{
+  int32_t value = (int32_t) (valp)->numval;
+  do_set_mutex_spin_count (value);
+}
+#endif
+
+static void
+mutex_tunables_init (int argc __attribute__ ((unused)),
+			      char **argv  __attribute__ ((unused)),
+					      char **environ)
+{
+#if HAVE_TUNABLES
+  TUNABLE_GET (spin_count, int32_t,
+               TUNABLE_CALLBACK (set_mutex_spin_count));
+#endif
+}
+
+#ifdef SHARED
+# define INIT_SECTION ".init_array"
+#else
+# define INIT_SECTION ".preinit_array"
+#endif
+
+void (*const __pthread_mutex_tunables_init_array []) (int, char **, char **)
+  __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
+{
+  &mutex_tunables_init
+};
diff --git a/nptl/pthread_mutex_conf.h b/nptl/pthread_mutex_conf.h
new file mode 100644
index 0000000..e5b027c
--- /dev/null
+++ b/nptl/pthread_mutex_conf.h
@@ -0,0 +1,31 @@ 
+/* pthread_mutex_conf.h: Pthread mutex tunable parameters.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#ifndef _PTHREAD_MUTEX_CONF_H
+#define _PTHREAD_MUTEX_CONF_H 1
+
+#include <pthread.h>
+#include <time.h>
+
+struct mutex_config
+{
+  int spin_count;
+};
+
+extern struct mutex_config __mutex_aconf attribute_hidden;
+
+#endif