nstraz | 8dbb34c | 2001-12-12 22:32:31 +0000 | [diff] [blame] | 1 | From linux-kernel-owner@vger.kernel.org Tue Dec 11 01:11:36 2001 |
| 2 | Received: from sgi.com (sgi.engr.sgi.com [192.26.80.37]) by tulip-e185.americas.sgi.com (980427.SGI.8.8.8/SGI-server-1.7) with ESMTP id BAA82859; Tue, 11 Dec 2001 01:11:36 -0600 (CST) |
| 3 | Received: from vger.kernel.org ([199.183.24.194]) |
| 4 | by sgi.com (980327.SGI.8.8.8-aspam/980304.SGI-aspam: |
| 5 | SGI does not authorize the use of its proprietary |
| 6 | systems or networks for unsolicited or bulk email |
| 7 | from the Internet.) |
| 8 | via ESMTP id XAA08571; Mon, 10 Dec 2001 23:11:32 -0800 (PST) |
| 9 | mail_from (linux-kernel-owner@vger.kernel.org) |
| 10 | Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand |
| 11 | id <S284902AbRLKHHQ>; Tue, 11 Dec 2001 02:07:16 -0500 |
| 12 | Received: (majordomo@vger.kernel.org) by vger.kernel.org |
| 13 | id <S284914AbRLKHG5>; Tue, 11 Dec 2001 02:06:57 -0500 |
| 14 | Received: from [202.135.142.194] ([202.135.142.194]:24588 "EHLO |
| 15 | wagner.rustcorp.com.au") by vger.kernel.org with ESMTP |
| 16 | id <S284913AbRLKHGr>; Tue, 11 Dec 2001 02:06:47 -0500 |
| 17 | Received: from wagner.rustcorp.com.au ([127.0.0.1] helo=rustcorp.com.au) |
| 18 | by wagner.rustcorp.com.au with esmtp (Exim 3.32 #1 (Debian)) |
| 19 | id 16Dh0t-0003yl-00; Tue, 11 Dec 2001 18:07:39 +1100 |
| 20 | From: Rusty Russell <rusty@rustcorp.com.au> |
| 21 | To: linux-kernel@vger.kernel.org |
| 22 | cc: lse-tech@lists.sourceforge.net |
| 23 | Subject: hackbench: New Multiqueue Scheduler Benchmark |
| 24 | Date: Tue, 11 Dec 2001 18:07:39 +1100 |
| 25 | Message-Id: <E16Dh0t-0003yl-00@wagner.rustcorp.com.au> |
| 26 | Sender: linux-kernel-owner@vger.kernel.org |
| 27 | Precedence: bulk |
| 28 | X-Mailing-List: linux-kernel@vger.kernel.org |
| 29 | Status: RO |
| 30 | Content-Length: 4977 |
| 31 | |
| 32 | Hi all, |
| 33 | |
| 34 | I've cut down the chat benchmark into a version which doesn't |
| 35 | use threads or semaphores, and called it hackbench: |
| 36 | |
| 37 | On a 12-way PPC64: |
| 38 | 2.4.17-pre7: |
| 39 | hackbench 50: Time: 851.469 Time: 847.143 Time: 826.868 |
| 40 | |
| 41 | 2.4.17-pre7-multiqueue-patch: |
| 42 | hackbench 50: Time: 15.120 Time: 14.766 Time: 15.067 |
| 43 | |
| 44 | "hackbench 1" creates a group of 20 processes listening on a socket |
| 45 | each, and 20 writers: each of the writers writes 100 messages to each |
| 46 | socket (ie. 20 x 100 messages each). |
| 47 | |
| 48 | "hackbench 50" simply runs 50 of these groups in parallel. You'd |
| 49 | expect it to be 5 times slower than hackbench 10, but without the |
| 50 | multiqueue patch: |
| 51 | |
| 52 | 10: Time: 10.573 Time: 13.471 Time: 9.289 |
| 53 | 50: Time: 851.469 Time: 847.143 Time: 826.868 |
| 54 | |
| 55 | Enjoy, |
| 56 | Rusty. |
| 57 | -- |
| 58 | Anyone who quotes me in their sig is an idiot. -- Rusty Russell. |
| 59 | |
| 60 | /* Test groups of 20 processes spraying to 20 receivers */ |
| 61 | #include <stdio.h> |
| 62 | #include <string.h> |
| 63 | #include <errno.h> |
| 64 | #include <sys/types.h> |
| 65 | #include <sys/socket.h> |
| 66 | #include <sys/wait.h> |
| 67 | #include <sys/time.h> |
| 68 | #include <sys/poll.h> |
| 69 | |
| 70 | #define DATASIZE 100 |
| 71 | static unsigned int loops = 100; |
| 72 | static int use_pipes = 0; |
| 73 | |
| 74 | static void barf(const char *msg) |
| 75 | { |
| 76 | fprintf(stderr, "%s (error: %s)\n", msg, strerror(errno)); |
| 77 | exit(1); |
| 78 | } |
| 79 | |
| 80 | static void fdpair(int fds[2]) |
| 81 | { |
| 82 | if (use_pipes) { |
| 83 | if (pipe(fds) == 0) |
| 84 | return; |
| 85 | } else { |
| 86 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0) |
| 87 | return; |
| 88 | } |
| 89 | barf("Creating fdpair"); |
| 90 | } |
| 91 | |
| 92 | /* Block until we're ready to go */ |
| 93 | static void ready(int ready_out, int wakefd) |
| 94 | { |
| 95 | char dummy; |
| 96 | struct pollfd pollfd = { .fd = wakefd, .events = POLLIN }; |
| 97 | |
| 98 | /* Tell them we're ready. */ |
| 99 | if (write(ready_out, &dummy, 1) != 1) |
| 100 | barf("CLIENT: ready write"); |
| 101 | |
| 102 | /* Wait for "GO" signal */ |
| 103 | if (poll(&pollfd, 1, -1) != 1) |
| 104 | barf("poll"); |
| 105 | } |
| 106 | |
| 107 | /* Sender sprays loops messages down each file descriptor */ |
| 108 | static void sender(unsigned int num_fds, |
| 109 | int out_fd[num_fds], |
| 110 | int ready_out, |
| 111 | int wakefd) |
| 112 | { |
| 113 | char data[DATASIZE]; |
| 114 | unsigned int i, j; |
| 115 | |
| 116 | ready(ready_out, wakefd); |
| 117 | |
| 118 | /* Now pump to every receiver. */ |
| 119 | for (i = 0; i < loops; i++) { |
| 120 | for (j = 0; j < num_fds; j++) { |
| 121 | int ret, done = 0; |
| 122 | |
| 123 | again: |
| 124 | ret = write(out_fd[j], data + done, sizeof(data)-done); |
| 125 | if (ret < 0) |
| 126 | barf("SENDER: write"); |
| 127 | done += ret; |
| 128 | if (done < sizeof(data)) |
| 129 | goto again; |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | /* One receiver per fd */ |
| 135 | static void receiver(unsigned int num_packets, |
| 136 | int in_fd, |
| 137 | int ready_out, |
| 138 | int wakefd) |
| 139 | { |
| 140 | unsigned int i; |
| 141 | |
| 142 | /* Wait for start... */ |
| 143 | ready(ready_out, wakefd); |
| 144 | |
| 145 | /* Receive them all */ |
| 146 | for (i = 0; i < num_packets; i++) { |
| 147 | char data[DATASIZE]; |
| 148 | int ret, done = 0; |
| 149 | |
| 150 | again: |
| 151 | ret = read(in_fd, data + done, DATASIZE - done); |
| 152 | if (ret < 0) |
| 153 | barf("SERVER: read"); |
| 154 | done += ret; |
| 155 | if (done < DATASIZE) |
| 156 | goto again; |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | /* One group of senders and receivers */ |
| 161 | static unsigned int group(unsigned int num_fds, |
| 162 | int ready_out, |
| 163 | int wakefd) |
| 164 | { |
| 165 | unsigned int i; |
| 166 | unsigned int out_fds[num_fds]; |
| 167 | |
| 168 | for (i = 0; i < num_fds; i++) { |
| 169 | int fds[2]; |
| 170 | |
| 171 | /* Create the pipe between client and server */ |
| 172 | fdpair(fds); |
| 173 | |
| 174 | /* Fork the receiver. */ |
| 175 | switch (fork()) { |
| 176 | case -1: barf("fork()"); |
| 177 | case 0: |
| 178 | close(fds[1]); |
| 179 | receiver(num_fds*loops, fds[0], ready_out, wakefd); |
| 180 | exit(0); |
| 181 | } |
| 182 | |
| 183 | out_fds[i] = fds[1]; |
| 184 | close(fds[0]); |
| 185 | } |
| 186 | |
| 187 | /* Now we have all the fds, fork the senders */ |
| 188 | for (i = 0; i < num_fds; i++) { |
| 189 | switch (fork()) { |
| 190 | case -1: barf("fork()"); |
| 191 | case 0: |
| 192 | sender(num_fds, out_fds, ready_out, wakefd); |
| 193 | exit(0); |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | /* Close the fds we have left */ |
| 198 | for (i = 0; i < num_fds; i++) |
| 199 | close(out_fds[i]); |
| 200 | |
| 201 | /* Return number of children to reap */ |
| 202 | return num_fds * 2; |
| 203 | } |
| 204 | |
| 205 | int main(int argc, char *argv[]) |
| 206 | { |
| 207 | unsigned int i, num_groups, total_children; |
| 208 | struct timeval start, stop, diff; |
| 209 | unsigned int num_fds = 20; |
| 210 | int readyfds[2], wakefds[2]; |
| 211 | char dummy; |
| 212 | |
| 213 | if (argv[1] && strcmp(argv[1], "-pipe") == 0) { |
| 214 | use_pipes = 1; |
| 215 | argc--; |
| 216 | argv++; |
| 217 | } |
| 218 | |
| 219 | if (argc != 2 || (num_groups = atoi(argv[1])) == 0) |
| 220 | barf("Usage: hackbench [-pipe] <num groups>\n"); |
| 221 | |
| 222 | fdpair(readyfds); |
| 223 | fdpair(wakefds); |
| 224 | |
| 225 | total_children = 0; |
| 226 | for (i = 0; i < num_groups; i++) |
| 227 | total_children += group(num_fds, readyfds[1], wakefds[0]); |
| 228 | |
| 229 | /* Wait for everyone to be ready */ |
| 230 | for (i = 0; i < total_children; i++) |
| 231 | if (read(readyfds[0], &dummy, 1) != 1) |
| 232 | barf("Reading for readyfds"); |
| 233 | |
| 234 | gettimeofday(&start, NULL); |
| 235 | |
| 236 | /* Kick them off */ |
| 237 | if (write(wakefds[1], &dummy, 1) != 1) |
| 238 | barf("Writing to start them"); |
| 239 | |
| 240 | /* Reap them all */ |
| 241 | for (i = 0; i < total_children; i++) { |
| 242 | int status; |
| 243 | wait(&status); |
| 244 | if (!WIFEXITED(status)) |
| 245 | exit(1); |
| 246 | } |
| 247 | |
| 248 | gettimeofday(&stop, NULL); |
| 249 | |
| 250 | /* Print time... */ |
| 251 | timersub(&stop, &start, &diff); |
| 252 | printf("Time: %lu.%03lu\n", diff.tv_sec, diff.tv_usec/1000); |
| 253 | exit(0); |
| 254 | } |
| 255 | - |
| 256 | To unsubscribe from this list: send the line "unsubscribe linux-kernel" in |
| 257 | the body of a message to majordomo@vger.kernel.org |
| 258 | More majordomo info at http://vger.kernel.org/majordomo-info.html |
| 259 | Please read the FAQ at http://www.tux.org/lkml/ |
| 260 | |
| 261 | |