]>
Commit | Line | Data |
---|---|---|
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 | ||
38 | static double compute_median(double *secs); | |
39 | static double get_time(void); | |
40 | static void read_test(int fd); | |
41 | static int run_read_test(void); | |
db0bd74a | 42 | static void write_test(int fd, cups_mode_t mode); |
ed486911 | 43 | |
44 | ||
45 | /* | |
46 | * 'main()' - Benchmark the raster read/write functions. | |
47 | */ | |
48 | ||
49 | int /* O - Exit status */ | |
db0bd74a MS |
50 | main(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 | ||
120 | static double /* O - Median time in seconds */ | |
121 | compute_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 | ||
152 | static double /* O - Time in seconds */ | |
153 | get_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 | ||
167 | static void | |
168 | read_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 | ||
201 | static int /* O - Standard input of child */ | |
202 | run_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 | ||
248 | static void | |
db0bd74a MS |
249 | write_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 | } |