]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/testspeed.c
License change: Apache License, Version 2.0.
[thirdparty/cups.git] / scheduler / testspeed.c
CommitLineData
ef416fc2 1/*
7e86f2f6 2 * Scheduler speed test for CUPS.
ef416fc2 3 *
7e86f2f6
MS
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2005 by Easy Software Products.
ef416fc2 6 *
e3101897 7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
ef416fc2 8 */
9
10/*
11 * Include necessary headers...
12 */
13
71e16022 14#include <cups/string-private.h>
ef416fc2 15#include <cups/cups.h>
16#include <cups/language.h>
71e16022 17#include <cups/debug-private.h>
75bd9771
MS
18#include <sys/types.h>
19#include <sys/time.h>
20#include <sys/wait.h>
ef416fc2 21
22
23/*
24 * Local functions...
25 */
26
dd1abb6b
MS
27static int do_test(const char *server, int port,
28 http_encryption_t encryption, int requests,
23ef1cac 29 const char *opstring, int verbose);
85dda01c 30static void usage(void) __attribute__((noreturn));
ef416fc2 31
32
33/*
34 * 'main()' - Send multiple IPP requests and report on the average response
35 * time.
36 */
37
38int
39main(int argc, /* I - Number of command-line arguments */
40 char *argv[]) /* I - Command-line arguments */
41{
42 int i; /* Looping var */
dd1abb6b
MS
43 char *server, /* Server to use */
44 *ptr; /* Pointer to port in server */
45 int port; /* Port to use */
ef416fc2 46 http_encryption_t encryption; /* Encryption to use */
47 int requests; /* Number of requests to send */
48 int children; /* Number of children to fork */
dd1abb6b 49 int good_children; /* Number of children that exited normally */
ef416fc2 50 int pid; /* Child PID */
51 int status; /* Child status */
52 time_t start, /* Start time */
53 end; /* End time */
54 double elapsed; /* Elapsed time */
55 int verbose; /* Verbosity */
23ef1cac 56 const char *opstring; /* Operation name */
ef416fc2 57
58
59 /*
60 * Parse command-line options...
61 */
62
63 requests = 100;
64 children = 5;
dd1abb6b
MS
65 server = (char *)cupsServer();
66 port = ippPort();
ef416fc2 67 encryption = HTTP_ENCRYPT_IF_REQUESTED;
68 verbose = 0;
23ef1cac 69 opstring = NULL;
ef416fc2 70
71 for (i = 1; i < argc; i ++)
dd1abb6b 72 if (argv[i][0] == '-')
ef416fc2 73 {
dd1abb6b
MS
74 for (ptr = argv[i] + 1; *ptr; ptr ++)
75 switch (*ptr)
76 {
23ef1cac
MS
77 case 'E' : /* Enable encryption */
78 encryption = HTTP_ENCRYPT_REQUIRED;
79 break;
80
dd1abb6b
MS
81 case 'c' : /* Number of children */
82 i ++;
83 if (i >= argc)
84 usage();
85
86 children = atoi(argv[i]);
87 break;
88
23ef1cac 89 case 'o' : /* Operation */
dd1abb6b
MS
90 i ++;
91 if (i >= argc)
92 usage();
93
23ef1cac 94 opstring = argv[i];
dd1abb6b
MS
95 break;
96
23ef1cac
MS
97 case 'r' : /* Number of requests */
98 i ++;
99 if (i >= argc)
100 usage();
101
102 requests = atoi(argv[i]);
dd1abb6b
MS
103 break;
104
105 case 'v' : /* Verbose logging */
106 verbose ++;
107 break;
108
109 default :
110 usage();
111 break;
112 }
ef416fc2 113 }
dd1abb6b 114 else
ef416fc2 115 {
dd1abb6b 116 server = argv[i];
ef416fc2 117
dd1abb6b
MS
118 if (server[0] != '/' && (ptr = strrchr(server, ':')) != NULL)
119 {
120 *ptr++ = '\0';
121 port = atoi(ptr);
122 }
ef416fc2 123 }
ef416fc2 124
125 /*
126 * Then create child processes to act as clients...
127 */
128
dd1abb6b
MS
129 if (children > 0)
130 {
131 printf("testspeed: Simulating %d clients with %d requests to %s with "
132 "%sencryption...\n", children, requests, server,
133 encryption == HTTP_ENCRYPT_IF_REQUESTED ? "no " : "");
134 }
ef416fc2 135
136 start = time(NULL);
137
dd1abb6b 138 if (children < 1)
23ef1cac 139 return (do_test(server, port, encryption, requests, opstring, verbose));
dd1abb6b 140 else if (children == 1)
23ef1cac
MS
141 good_children = do_test(server, port, encryption, requests, opstring,
142 verbose) ? 0 : 1;
ef416fc2 143 else
144 {
dd1abb6b
MS
145 char options[255], /* Command-line options for child */
146 reqstr[255], /* Requests string for child */
147 serverstr[255]; /* Server:port string for child */
148
149
150 snprintf(reqstr, sizeof(reqstr), "%d", requests);
151
152 if (port == 631 || server[0] == '/')
153 strlcpy(serverstr, server, sizeof(serverstr));
154 else
155 snprintf(serverstr, sizeof(serverstr), "%s:%d", server, port);
156
157 strlcpy(options, "-cr", sizeof(options));
158
159 if (encryption == HTTP_ENCRYPT_REQUIRED)
160 strlcat(options, "E", sizeof(options));
161
162 if (verbose)
163 strlcat(options, "v", sizeof(options));
164
ef416fc2 165 for (i = 0; i < children; i ++)
dd1abb6b
MS
166 {
167 fflush(stdout);
168
ef416fc2 169 if ((pid = fork()) == 0)
170 {
171 /*
172 * Child goes here...
173 */
174
23ef1cac
MS
175 if (opstring)
176 execlp(argv[0], argv[0], options, "0", reqstr, "-o", opstring,
177 serverstr, (char *)NULL);
178 else
179 execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL);
180
dd1abb6b 181 exit(errno);
ef416fc2 182 }
183 else if (pid < 0)
184 {
dd1abb6b 185 printf("testspeed: Fork failed: %s\n", strerror(errno));
ef416fc2 186 break;
187 }
188 else
dd1abb6b
MS
189 printf("testspeed: Started child %d...\n", pid);
190 }
ef416fc2 191
192 /*
193 * Wait for children to finish...
194 */
195
dd1abb6b
MS
196 puts("testspeed: Waiting for children to finish...");
197
198 for (good_children = 0;;)
ef416fc2 199 {
200 pid = wait(&status);
201
202 if (pid < 0 && errno != EINTR)
203 break;
204
dd1abb6b
MS
205 printf("testspeed: Ended child %d (%d)...\n", pid, status / 256);
206
207 if (!status)
208 good_children ++;
ef416fc2 209 }
210 }
211
212 /*
213 * Compute the total run time...
214 */
215
dd1abb6b
MS
216 if (good_children > 0)
217 {
218 end = time(NULL);
219 elapsed = end - start;
220 i = good_children * requests;
ef416fc2 221
dd1abb6b
MS
222 printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
223 good_children, requests, i, elapsed, elapsed / i, i / elapsed);
224 }
ef416fc2 225
226 /*
227 * Exit with no errors...
228 */
229
91c84a35 230 return (0);
ef416fc2 231}
232
233
234/*
235 * 'do_test()' - Run a test on a specific host...
236 */
237
e1d6a774 238static int /* O - Exit status */
ef416fc2 239do_test(const char *server, /* I - Server to use */
dd1abb6b 240 int port, /* I - Port number to use */
ef416fc2 241 http_encryption_t encryption, /* I - Encryption to use */
242 int requests, /* I - Number of requests to send */
23ef1cac 243 const char *opstring, /* I - Operation string */
ef416fc2 244 int verbose) /* I - Verbose output? */
245{
246 int i; /* Looping var */
247 http_t *http; /* Connection to server */
dd1abb6b 248 ipp_t *request; /* IPP Request */
ef416fc2 249 struct timeval start, /* Start time */
250 end; /* End time */
dd1abb6b
MS
251 double reqtime, /* Time for this request */
252 elapsed; /* Elapsed time */
253 int op; /* Current operation */
23ef1cac 254 static ipp_op_t ops[5] = /* Operations to test... */
ef416fc2 255 {
256 IPP_PRINT_JOB,
23ef1cac 257 CUPS_GET_DEFAULT,
ef416fc2 258 CUPS_GET_PRINTERS,
259 CUPS_GET_CLASSES,
260 IPP_GET_JOBS
261 };
262
263
264 /*
265 * Connect to the server...
266 */
267
dd1abb6b 268 if ((http = httpConnectEncrypt(server, port, encryption)) == NULL)
ef416fc2 269 {
dd1abb6b
MS
270 printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(),
271 strerror(errno));
ef416fc2 272 return (1);
273 }
274
ef416fc2 275 /*
276 * Do multiple requests...
277 */
278
279 for (elapsed = 0.0, i = 0; i < requests; i ++)
280 {
ef416fc2 281 /*
282 * Build a request which requires the following attributes:
283 *
284 * attributes-charset
285 * attributes-natural-language
286 *
287 * In addition, IPP_GET_JOBS needs a printer-uri attribute.
288 */
289
23ef1cac
MS
290 if (opstring)
291 op = ippOpValue(opstring);
292 else
7e86f2f6 293 op = ops[i % (int)(sizeof(ops) / sizeof(ops[0]))];
23ef1cac 294
dd1abb6b 295 request = ippNewRequest(op);
ef416fc2 296
297 gettimeofday(&start, NULL);
298
dd1abb6b
MS
299 if (verbose)
300 printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed,
301 ippOpString(op));
302
303 switch (op)
ef416fc2 304 {
305 case IPP_GET_JOBS :
306 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
307 NULL, "ipp://localhost/printers/");
308
309 default :
dd1abb6b 310 ippDelete(cupsDoRequest(http, request, "/"));
ef416fc2 311 break;
312
313 case IPP_PRINT_JOB :
314 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
315 NULL, "ipp://localhost/printers/test");
dd1abb6b
MS
316 ippDelete(cupsDoFileRequest(http, request, "/printers/test",
317 "../data/testprint.ps"));
ef416fc2 318 break;
319 }
320
321 gettimeofday(&end, NULL);
322
dd1abb6b
MS
323 reqtime = (end.tv_sec - start.tv_sec) +
324 0.000001 * (end.tv_usec - start.tv_usec);
325 elapsed += reqtime;
326
327 switch (cupsLastError())
328 {
329 case IPP_OK :
330 case IPP_NOT_FOUND :
331 if (verbose)
332 {
333 printf("succeeded: %s (%.6f)\n", cupsLastErrorString(), reqtime);
334 fflush(stdout);
335 }
336 break;
ef416fc2 337
dd1abb6b
MS
338 default :
339 if (!verbose)
340 printf("testspeed(%d): %s ", (int)getpid(),
341 ippOpString(ops[i & 3]));
342
343 printf("failed: %s\n", cupsLastErrorString());
344 httpClose(http);
345 return (1);
346 }
ef416fc2 347 }
348
ef416fc2 349 httpClose(http);
350
351 printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
352 (int)getpid(), i, elapsed, elapsed / i, i / elapsed);
353
354 return (0);
355}
356
357
358/*
359 * 'usage()' - Show program usage...
360 */
361
e1d6a774 362static void
ef416fc2 363usage(void)
364{
23ef1cac
MS
365 puts("Usage: testspeed [-c children] [-h] [-o operation] [-r requests] [-v] "
366 "[-E] hostname[:port]");
ef416fc2 367 exit(0);
368}