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