Skip to content

Commit 20401d1

Browse files
aquinitorvalds
authored andcommittedSep 8, 2021
ipc: replace costly bailout check in sysvipc_find_ipc()
sysvipc_find_ipc() was left with a costly way to check if the offset position fed to it is bigger than the total number of IPC IDs in use. So much so that the time it takes to iterate over /proc/sysvipc/* files grows exponentially for a custom benchmark that creates "N" SYSV shm segments and then times the read of /proc/sysvipc/shm (milliseconds): 12 msecs to read 1024 segs from /proc/sysvipc/shm 18 msecs to read 2048 segs from /proc/sysvipc/shm 65 msecs to read 4096 segs from /proc/sysvipc/shm 325 msecs to read 8192 segs from /proc/sysvipc/shm 1303 msecs to read 16384 segs from /proc/sysvipc/shm 5182 msecs to read 32768 segs from /proc/sysvipc/shm The root problem lies with the loop that computes the total amount of ids in use to check if the "pos" feeded to sysvipc_find_ipc() grew bigger than "ids->in_use". That is a quite inneficient way to get to the maximum index in the id lookup table, specially when that value is already provided by struct ipc_ids.max_idx. This patch follows up on the optimization introduced via commit 15df03c ("sysvipc: make get_maxid O(1) again") and gets rid of the aforementioned costly loop replacing it by a simpler checkpoint based on ipc_get_maxidx() returned value, which allows for a smooth linear increase in time complexity for the same custom benchmark: 2 msecs to read 1024 segs from /proc/sysvipc/shm 2 msecs to read 2048 segs from /proc/sysvipc/shm 4 msecs to read 4096 segs from /proc/sysvipc/shm 9 msecs to read 8192 segs from /proc/sysvipc/shm 19 msecs to read 16384 segs from /proc/sysvipc/shm 39 msecs to read 32768 segs from /proc/sysvipc/shm Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Rafael Aquini <[email protected]> Acked-by: Davidlohr Bueso <[email protected]> Acked-by: Manfred Spraul <[email protected]> Cc: Waiman Long <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent d42990f commit 20401d1

File tree

1 file changed

+4
-12
lines changed

1 file changed

+4
-12
lines changed
 

‎ipc/util.c

+4-12
Original file line numberDiff line numberDiff line change
@@ -788,21 +788,13 @@ struct pid_namespace *ipc_seq_pid_ns(struct seq_file *s)
788788
static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
789789
loff_t *new_pos)
790790
{
791-
struct kern_ipc_perm *ipc;
792-
int total, id;
793-
794-
total = 0;
795-
for (id = 0; id < pos && total < ids->in_use; id++) {
796-
ipc = idr_find(&ids->ipcs_idr, id);
797-
if (ipc != NULL)
798-
total++;
799-
}
791+
struct kern_ipc_perm *ipc = NULL;
792+
int max_idx = ipc_get_maxidx(ids);
800793

801-
ipc = NULL;
802-
if (total >= ids->in_use)
794+
if (max_idx == -1 || pos > max_idx)
803795
goto out;
804796

805-
for (; pos < ipc_mni; pos++) {
797+
for (; pos <= max_idx; pos++) {
806798
ipc = idr_find(&ids->ipcs_idr, pos);
807799
if (ipc != NULL) {
808800
rcu_read_lock();

0 commit comments

Comments
 (0)
Please sign in to comment.