]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/rasterbench.c
Update svn:keyword properties.
[thirdparty/cups.git] / filter / rasterbench.c
1 /*
2 * "$Id$"
3 *
4 * Raster benchmark program for CUPS.
5 *
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * main() - Benchmark the raster read/write functions.
20 * compute_median() - Compute the median time for a test.
21 * read_test() - Benchmark the raster read functions.
22 * write_test() - Benchmark the raster write functions.
23 */
24
25 /*
26 * Include necessary headers...
27 */
28
29 #include <config.h>
30 #include <cups/raster.h>
31 #include <stdlib.h>
32 #include <sys/time.h>
33 #include <signal.h>
34 #include <unistd.h>
35 #include <sys/wait.h>
36
37
38 /*
39 * Constants...
40 */
41
42 #define TEST_WIDTH 1024
43 #define TEST_HEIGHT 1024
44 #define TEST_PAGES 16
45 #define TEST_PASSES 20
46
47
48 /*
49 * Local functions...
50 */
51
52 static double compute_median(double *secs);
53 static double get_time(void);
54 static void read_test(int fd);
55 static int run_read_test(void);
56 static void write_test(int fd, cups_mode_t mode);
57
58
59 /*
60 * 'main()' - Benchmark the raster read/write functions.
61 */
62
63 int /* O - Exit status */
64 main(int argc, /* I - Number of command-line args */
65 char *argv[]) /* I - Command-line arguments */
66 {
67 int i; /* Looping var */
68 int ras_fd, /* File descriptor for read process */
69 status; /* Exit status of read process */
70 double start_secs, /* Start time */
71 write_secs, /* Write time */
72 read_secs, /* Read time */
73 pass_secs[TEST_PASSES]; /* Total test times */
74 cups_mode_t mode; /* Write mode */
75
76
77 /*
78 * See if we have anything on the command-line...
79 */
80
81 if (argc > 2 || (argc == 2 && strcmp(argv[1], "-z")))
82 {
83 puts("Usage: rasterbench [-z]");
84 return (1);
85 }
86
87 mode = argc > 1 ? CUPS_RASTER_WRITE_COMPRESSED : CUPS_RASTER_WRITE;
88
89 /*
90 * Ignore SIGPIPE...
91 */
92
93 signal(SIGPIPE, SIG_IGN);
94
95 /*
96 * Run the tests several times to get a good average...
97 */
98
99 printf("Test read/write speed of %d pages, %dx%d pixels...\n\n",
100 TEST_PAGES, TEST_WIDTH, TEST_HEIGHT);
101 for (i = 0; i < TEST_PASSES; i ++)
102 {
103 printf("PASS %2d: ", i + 1);
104 fflush(stdout);
105
106 ras_fd = run_read_test();
107 start_secs = get_time();
108
109 write_test(ras_fd, mode);
110
111 write_secs = get_time();
112 printf(" %.3f write,", write_secs - start_secs);
113 fflush(stdout);
114
115 close(ras_fd);
116 wait(&status);
117
118 read_secs = get_time();
119 pass_secs[i] = read_secs - start_secs;
120 printf(" %.3f read, %.3f total\n", read_secs - write_secs, pass_secs[i]);
121 }
122
123 printf("\nMedian Total Time: %.3f seconds per document\n",
124 compute_median(pass_secs));
125
126 return (0);
127 }
128
129
130 /*
131 * 'compute_median()' - Compute the median time for a test.
132 */
133
134 static double /* O - Median time in seconds */
135 compute_median(double *secs) /* I - Array of time samples */
136 {
137 int i, j; /* Looping vars */
138 double temp; /* Swap variable */
139
140
141 /*
142 * Sort the array into ascending order using a quicky bubble sort...
143 */
144
145 for (i = 0; i < (TEST_PASSES - 1); i ++)
146 for (j = i + 1; j < TEST_PASSES; j ++)
147 if (secs[i] > secs[j])
148 {
149 temp = secs[i];
150 secs[i] = secs[j];
151 secs[j] = temp;
152 }
153
154 /*
155 * Return the average of the middle two samples...
156 */
157
158 return (0.5 * (secs[TEST_PASSES / 2 - 1] + secs[TEST_PASSES / 2]));
159 }
160
161
162 /*
163 * 'get_time()' - Get the current time in seconds.
164 */
165
166 static double /* O - Time in seconds */
167 get_time(void)
168 {
169 struct timeval curtime; /* Current time */
170
171
172 gettimeofday(&curtime, NULL);
173 return (curtime.tv_sec + 0.000001 * curtime.tv_usec);
174 }
175
176
177 /*
178 * 'read_test()' - Benchmark the raster read functions.
179 */
180
181 static void
182 read_test(int fd) /* I - File descriptor to read from */
183 {
184 int y; /* Looping var */
185 cups_raster_t *r; /* Raster stream */
186 cups_page_header2_t header; /* Page header */
187 unsigned char buffer[8 * TEST_WIDTH];
188 /* Read buffer */
189
190
191 /*
192 * Test read speed...
193 */
194
195 if ((r = cupsRasterOpen(fd, CUPS_RASTER_READ)) == NULL)
196 {
197 perror("Unable to create raster input stream");
198 return;
199 }
200
201 while (cupsRasterReadHeader2(r, &header))
202 {
203 for (y = 0; y < header.cupsHeight; y ++)
204 cupsRasterReadPixels(r, buffer, header.cupsBytesPerLine);
205 }
206
207 cupsRasterClose(r);
208 }
209
210
211 /*
212 * 'run_read_test()' - Run the read test as a child process via pipes.
213 */
214
215 static int /* O - Standard input of child */
216 run_read_test(void)
217 {
218 int ras_pipes[2]; /* Raster data pipes */
219 int pid; /* Child process ID */
220
221
222 if (pipe(ras_pipes))
223 return (-1);
224
225 if ((pid = fork()) < 0)
226 {
227 /*
228 * Fork error - return -1 on error...
229 */
230
231 close(ras_pipes[0]);
232 close(ras_pipes[1]);
233
234 return (-1);
235 }
236 else if (pid == 0)
237 {
238 /*
239 * Child comes here - read data from the input pipe...
240 */
241
242 close(ras_pipes[1]);
243 read_test(ras_pipes[0]);
244 exit(0);
245 }
246 else
247 {
248 /*
249 * Parent comes here - return the output pipe...
250 */
251
252 close(ras_pipes[0]);
253 return (ras_pipes[1]);
254 }
255 }
256
257
258 /*
259 * 'write_test()' - Benchmark the raster write functions.
260 */
261
262 static void
263 write_test(int fd, /* I - File descriptor to write to */
264 cups_mode_t mode) /* I - Write mode */
265 {
266 int page, x, y; /* Looping vars */
267 int count; /* Number of bytes to set */
268 cups_raster_t *r; /* Raster stream */
269 cups_page_header2_t header; /* Page header */
270 unsigned char data[32][8 * TEST_WIDTH];
271 /* Raster data to write */
272
273
274 /*
275 * Create a combination of random data and repeated data to simulate
276 * text with some whitespace.
277 */
278
279 CUPS_SRAND(time(NULL));
280
281 memset(data, 0, sizeof(data));
282
283 for (y = 0; y < 28; y ++)
284 {
285 for (x = CUPS_RAND() & 127, count = (CUPS_RAND() & 15) + 1;
286 x < sizeof(data[0]);
287 x ++, count --)
288 {
289 if (count <= 0)
290 {
291 x += (CUPS_RAND() & 15) + 1;
292 count = (CUPS_RAND() & 15) + 1;
293
294 if (x >= sizeof(data[0]))
295 break;
296 }
297
298 data[y][x] = CUPS_RAND();
299 }
300 }
301
302 /*
303 * Test write speed...
304 */
305
306 if ((r = cupsRasterOpen(fd, mode)) == NULL)
307 {
308 perror("Unable to create raster output stream");
309 return;
310 }
311
312 for (page = 0; page < TEST_PAGES; page ++)
313 {
314 memset(&header, 0, sizeof(header));
315 header.cupsWidth = TEST_WIDTH;
316 header.cupsHeight = TEST_HEIGHT;
317 header.cupsBytesPerLine = TEST_WIDTH;
318
319 if (page & 1)
320 {
321 header.cupsBytesPerLine *= 4;
322 header.cupsColorSpace = CUPS_CSPACE_CMYK;
323 header.cupsColorOrder = CUPS_ORDER_CHUNKED;
324 }
325 else
326 {
327 header.cupsColorSpace = CUPS_CSPACE_K;
328 header.cupsColorOrder = CUPS_ORDER_BANDED;
329 }
330
331 if (page & 2)
332 {
333 header.cupsBytesPerLine *= 2;
334 header.cupsBitsPerColor = 16;
335 header.cupsBitsPerPixel = (page & 1) ? 64 : 16;
336 }
337 else
338 {
339 header.cupsBitsPerColor = 8;
340 header.cupsBitsPerPixel = (page & 1) ? 32 : 8;
341 }
342
343 cupsRasterWriteHeader2(r, &header);
344
345 for (y = 0; y < TEST_HEIGHT; y ++)
346 cupsRasterWritePixels(r, data[y & 31], header.cupsBytesPerLine);
347 }
348
349 cupsRasterClose(r);
350 }
351
352
353 /*
354 * End of "$Id$".
355 */