mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
ipc: optimize semget/shmget/msgget for lots of keys
ipc_findkey() used to scan all objects to look for the wanted key. This
is slow when using a high number of keys. This change adds an rhashtable
of kern_ipc_perm objects in ipc_ids, so that one lookup cease to be O(n).
This change gives a 865% improvement of benchmark reaim.jobs_per_min on a
56 threads Intel(R) Xeon(R) CPU E5-2695 v3 @ 2.30GHz with 256G memory [1]
Other (more micro) benchmark results, by the author: On an i5 laptop, the
following loop executed right after a reboot took, without and with this
change:
for (int i = 0, k=0x424242; i < KEYS; ++i)
semget(k++, 1, IPC_CREAT | 0600);
total total max single max single
KEYS without with call without call with
1 3.5 4.9 µs 3.5 4.9
10 7.6 8.6 µs 3.7 4.7
32 16.2 15.9 µs 4.3 5.3
100 72.9 41.8 µs 3.7 4.7
1000 5,630.0 502.0 µs * *
10000 1,340,000.0 7,240.0 µs * *
31900 17,600,000.0 22,200.0 µs * *
*: unreliable measure: high variance
The duration for a lookup-only usage was obtained by the same loop once
the keys are present:
total total max single max single
KEYS without with call without call with
1 2.1 2.5 µs 2.1 2.5
10 4.5 4.8 µs 2.2 2.3
32 13.0 10.8 µs 2.3 2.8
100 82.9 25.1 µs * 2.3
1000 5,780.0 217.0 µs * *
10000 1,470,000.0 2,520.0 µs * *
31900 17,400,000.0 7,810.0 µs * *
Finally, executing each semget() in a new process gave, when still
summing only the durations of these syscalls:
creation:
total total
KEYS without with
1 3.7 5.0 µs
10 32.9 36.7 µs
32 125.0 109.0 µs
100 523.0 353.0 µs
1000 20,300.0 3,280.0 µs
10000 2,470,000.0 46,700.0 µs
31900 27,800,000.0 219,000.0 µs
lookup-only:
total total
KEYS without with
1 2.5 2.7 µs
10 25.4 24.4 µs
32 106.0 72.6 µs
100 591.0 352.0 µs
1000 22,400.0 2,250.0 µs
10000 2,510,000.0 25,700.0 µs
31900 28,200,000.0 115,000.0 µs
[1] http://lkml.kernel.org/r/20170814060507.GE23258@yexl-desktop
Link: http://lkml.kernel.org/r/20170815194954.ck32ta2z35yuzpwp@debix
Signed-off-by: Guillaume Knispel <[email protected]>
Reviewed-by: Marc Pardo <[email protected]>
Cc: Davidlohr Bueso <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Manfred Spraul <[email protected]>
Cc: Alexey Dobriyan <[email protected]>
Cc: "Eric W. Biederman" <[email protected]>
Cc: "Peter Zijlstra (Intel)" <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Sebastian Andrzej Siewior <[email protected]>
Cc: Serge Hallyn <[email protected]>
Cc: Andrey Vagin <[email protected]>
Cc: Guillaume Knispel <[email protected]>
Cc: Marc Pardo <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
e4243b8062
commit
0cfb6aee70
8 changed files with 130 additions and 50 deletions
21
ipc/util.h
21
ipc/util.h
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
#define SEQ_MULTIPLIER (IPCMNI)
|
||||
|
||||
void sem_init(void);
|
||||
void msg_init(void);
|
||||
int sem_init(void);
|
||||
int msg_init(void);
|
||||
void shm_init(void);
|
||||
|
||||
struct ipc_namespace;
|
||||
|
|
@ -30,17 +30,17 @@ static inline void mq_put_mnt(struct ipc_namespace *ns) { }
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_SYSVIPC
|
||||
void sem_init_ns(struct ipc_namespace *ns);
|
||||
void msg_init_ns(struct ipc_namespace *ns);
|
||||
void shm_init_ns(struct ipc_namespace *ns);
|
||||
int sem_init_ns(struct ipc_namespace *ns);
|
||||
int msg_init_ns(struct ipc_namespace *ns);
|
||||
int shm_init_ns(struct ipc_namespace *ns);
|
||||
|
||||
void sem_exit_ns(struct ipc_namespace *ns);
|
||||
void msg_exit_ns(struct ipc_namespace *ns);
|
||||
void shm_exit_ns(struct ipc_namespace *ns);
|
||||
#else
|
||||
static inline void sem_init_ns(struct ipc_namespace *ns) { }
|
||||
static inline void msg_init_ns(struct ipc_namespace *ns) { }
|
||||
static inline void shm_init_ns(struct ipc_namespace *ns) { }
|
||||
static inline int sem_init_ns(struct ipc_namespace *ns) { return 0; }
|
||||
static inline int msg_init_ns(struct ipc_namespace *ns) { return 0; }
|
||||
static inline int shm_init_ns(struct ipc_namespace *ns) { return 0; }
|
||||
|
||||
static inline void sem_exit_ns(struct ipc_namespace *ns) { }
|
||||
static inline void msg_exit_ns(struct ipc_namespace *ns) { }
|
||||
|
|
@ -79,7 +79,7 @@ struct ipc_ops {
|
|||
struct seq_file;
|
||||
struct ipc_ids;
|
||||
|
||||
void ipc_init_ids(struct ipc_ids *);
|
||||
int ipc_init_ids(struct ipc_ids *);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
void __init ipc_init_proc_interface(const char *path, const char *header,
|
||||
int ids, int (*show)(struct seq_file *, void *));
|
||||
|
|
@ -104,6 +104,9 @@ int ipc_get_maxid(struct ipc_ids *);
|
|||
/* must be called with both locks acquired. */
|
||||
void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);
|
||||
|
||||
/* must be called with both locks acquired. */
|
||||
void ipc_set_key_private(struct ipc_ids *, struct kern_ipc_perm *);
|
||||
|
||||
/* must be called with ipcp locked */
|
||||
int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flg);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue