Skip to content

Commit 0650b2b

Browse files
captain5050namhyung
authored andcommitted
perf sharded_mutex: Introduce sharded_mutex
Per object mutexes may come with significant memory cost while a global mutex can suffer from unnecessary contention. A sharded mutex is a compromise where objects are hashed and then a particular mutex for the hash of the object used. Contention can be controlled by the number of shards. v2. Use hashmap.h's hash_bits in case of contention from alignment of objects. Signed-off-by: Ian Rogers <[email protected]> Acked-by: Namhyung Kim <[email protected]> Cc: Andres Freund <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Yuan Can <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Huacai Chen <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Kan Liang <[email protected]> Cc: Ingo Molnar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent 5e37ef5 commit 0650b2b

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

tools/perf/util/Build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ perf-y += mem2node.o
145145
perf-y += clockid.o
146146
perf-y += list_sort.o
147147
perf-y += mutex.o
148+
perf-y += sharded_mutex.o
148149

149150
perf-$(CONFIG_LIBBPF) += bpf-loader.o
150151
perf-$(CONFIG_LIBBPF) += bpf_map.o

tools/perf/util/sharded_mutex.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include "sharded_mutex.h"
3+
4+
#include <stdlib.h>
5+
6+
struct sharded_mutex *sharded_mutex__new(size_t num_shards)
7+
{
8+
struct sharded_mutex *result;
9+
size_t size;
10+
unsigned int bits;
11+
12+
for (bits = 0; ((size_t)1 << bits) < num_shards; bits++)
13+
;
14+
15+
size = sizeof(*result) + sizeof(struct mutex) * (1 << bits);
16+
result = malloc(size);
17+
if (!result)
18+
return NULL;
19+
20+
result->cap_bits = bits;
21+
for (size_t i = 0; i < ((size_t)1 << bits); i++)
22+
mutex_init(&result->mutexes[i]);
23+
24+
return result;
25+
}
26+
27+
void sharded_mutex__delete(struct sharded_mutex *sm)
28+
{
29+
for (size_t i = 0; i < ((size_t)1 << sm->cap_bits); i++)
30+
mutex_destroy(&sm->mutexes[i]);
31+
32+
free(sm);
33+
}

tools/perf/util/sharded_mutex.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef PERF_SHARDED_MUTEX_H
3+
#define PERF_SHARDED_MUTEX_H
4+
5+
#include "mutex.h"
6+
#include "hashmap.h"
7+
8+
/*
9+
* In a situation where a lock is needed per object, having a mutex can be
10+
* relatively memory expensive (40 bytes on x86-64). If the object can be
11+
* constantly hashed, a sharded mutex is an alternative global pool of mutexes
12+
* where the mutex is looked up from a hash value. This can lead to collisions
13+
* if the number of shards isn't large enough.
14+
*/
15+
struct sharded_mutex {
16+
/* mutexes array is 1<<cap_bits in size. */
17+
unsigned int cap_bits;
18+
struct mutex mutexes[];
19+
};
20+
21+
struct sharded_mutex *sharded_mutex__new(size_t num_shards);
22+
void sharded_mutex__delete(struct sharded_mutex *sm);
23+
24+
static inline struct mutex *sharded_mutex__get_mutex(struct sharded_mutex *sm, size_t hash)
25+
{
26+
return &sm->mutexes[hash_bits(hash, sm->cap_bits)];
27+
}
28+
29+
#endif /* PERF_SHARDED_MUTEX_H */

0 commit comments

Comments
 (0)