Messages in this thread Patch in this message | | | Date | Sun, 27 Feb 2000 17:12:22 +0100 | From | Martin Schenk <> | Subject | [patch] better SMP performance for pipes [2.3.*] |
| |
On a SMP system, contention of PIPE_SEM leads to unnecessary scheduling. Using "adaptive semaphores" (from my previous post to this list), this problem is easily solved.
I originally tried to do this replacing PIPE_SEM with a spinlock, but this is a cleaner way and it should not deadlock when copy_from_user pagefaults (Thanks to Manfred Spraul for pointing out this problem).
Hope this patch is useful,
Martin
PS: a good example to show the performance problem of stock SMP 2.3.* kernels is the "pipedis" benchmark program in the IX_SSBA benchmark suite (basically it's just one process writing into a pipe and another reading from it).
Under 2.2.14. "pipedis 500000 1" takes about 2 seconds, under 2.3.47 almost 6 seconds - using this patch the time is back to a bit more than 2 seconds. [under 2.2.14 the access to pipe_read/pipe_write was protected by the kernel lock instead of the semaphore]--- /home/martin/linuxelf-2.3.orig/fs/pipe.c Fri Feb 11 20:02:05 2000 +++ pipe.c Sun Feb 27 16:34:33 2000 @@ -62,9 +62,9 @@ /* Get the pipe semaphore */ ret = -ERESTARTSYS; - if (down_interruptible(PIPE_SEM(*inode))) - goto out_nolock; + /* try to spin first, interruptible is not necessary */ + down_adapt(PIPE_SEM(*inode)); if (PIPE_EMPTY(*inode)) { do_more_read: ret = 0; @@ -82,8 +82,7 @@ ret = -ERESTARTSYS; if (signal_pending(current)) goto out_nolock; - if (down_interruptible(PIPE_SEM(*inode))) - goto out_nolock; + down_adapt(PIPE_SEM(*inode)); ret = 0; if (!PIPE_EMPTY(*inode)) break; @@ -159,9 +158,7 @@ goto out_nolock; ret = -ERESTARTSYS; - if (down_interruptible(PIPE_SEM(*inode))) - goto out_nolock; - + down_adapt(PIPE_SEM(*inode)); do_more_write: /* No readers yields SIGPIPE. */ if (!PIPE_READERS(*inode)) @@ -183,9 +180,7 @@ ret = -ERESTARTSYS; if (signal_pending(current)) goto out_nolock; - if (down_interruptible(PIPE_SEM(*inode))) - goto out_nolock; - + down_adapt(PIPE_SEM(*inode)); if (!PIPE_READERS(*inode)) goto sigpipe; } @@ -231,8 +226,7 @@ PIPE_WAITING_WRITERS(*inode)--; if (signal_pending(current)) goto out_nolock; - if (down_interruptible(PIPE_SEM(*inode))) - goto out_nolock; + down_adapt(PIPE_SEM(*inode)); if (!PIPE_READERS(*inode)) goto sigpipe; } while (!PIPE_FREE(*inode)); | |