Revert manifest to default one
[external/cups.git] / filter / rasterbench.c
1 /*
2  * "$Id: rasterbench.c 9771 2011-05-12 05:21:56Z mike $"
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: rasterbench.c 9771 2011-05-12 05:21:56Z mike $".
355  */