#include <config.h>
#include <cups/raster.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#define TEST_WIDTH 1024
#define TEST_HEIGHT 1024
#define TEST_PAGES 16
#define TEST_PASSES 20
static double compute_median(double *secs);
static double get_time(void);
static void read_test(int fd);
static int run_read_test(void);
static void write_test(int fd, cups_mode_t mode);
int
main(int argc,
char *argv[])
{
int i;
int ras_fd,
status;
double start_secs,
write_secs,
read_secs,
pass_secs[TEST_PASSES];
cups_mode_t mode;
if (argc > 2 || (argc == 2 && strcmp(argv[1], "-z")))
{
puts("Usage: rasterbench [-z]");
return (1);
}
mode = argc > 1 ? CUPS_RASTER_WRITE_COMPRESSED : CUPS_RASTER_WRITE;
signal(SIGPIPE, SIG_IGN);
printf("Test read/write speed of %d pages, %dx%d pixels...\n\n",
TEST_PAGES, TEST_WIDTH, TEST_HEIGHT);
for (i = 0; i < TEST_PASSES; i ++)
{
printf("PASS %2d: ", i + 1);
fflush(stdout);
ras_fd = run_read_test();
start_secs = get_time();
write_test(ras_fd, mode);
write_secs = get_time();
printf(" %.3f write,", write_secs - start_secs);
fflush(stdout);
close(ras_fd);
wait(&status);
read_secs = get_time();
pass_secs[i] = read_secs - start_secs;
printf(" %.3f read, %.3f total\n", read_secs - write_secs, pass_secs[i]);
}
printf("\nMedian Total Time: %.3f seconds per document\n",
compute_median(pass_secs));
return (0);
}
static double
compute_median(double *secs)
{
int i, j;
double temp;
for (i = 0; i < (TEST_PASSES - 1); i ++)
for (j = i + 1; j < TEST_PASSES; j ++)
if (secs[i] > secs[j])
{
temp = secs[i];
secs[i] = secs[j];
secs[j] = temp;
}
return (0.5 * (secs[TEST_PASSES / 2 - 1] + secs[TEST_PASSES / 2]));
}
static double
get_time(void)
{
struct timeval curtime;
gettimeofday(&curtime, NULL);
return (curtime.tv_sec + 0.000001 * curtime.tv_usec);
}
static void
read_test(int fd)
{
int y;
cups_raster_t *r;
cups_page_header2_t header;
unsigned char buffer[8 * TEST_WIDTH];
if ((r = cupsRasterOpen(fd, CUPS_RASTER_READ)) == NULL)
{
perror("Unable to create raster input stream");
return;
}
while (cupsRasterReadHeader2(r, &header))
{
for (y = 0; y < header.cupsHeight; y ++)
cupsRasterReadPixels(r, buffer, header.cupsBytesPerLine);
}
cupsRasterClose(r);
}
static int
run_read_test(void)
{
int ras_pipes[2];
int pid;
if (pipe(ras_pipes))
return (-1);
if ((pid = fork()) < 0)
{
close(ras_pipes[0]);
close(ras_pipes[1]);
return (-1);
}
else if (pid == 0)
{
close(ras_pipes[1]);
read_test(ras_pipes[0]);
exit(0);
}
else
{
close(ras_pipes[0]);
return (ras_pipes[1]);
}
}
static void
write_test(int fd,
cups_mode_t mode)
{
int page, x, y;
int count;
cups_raster_t *r;
cups_page_header2_t header;
unsigned char data[32][8 * TEST_WIDTH];
CUPS_SRAND(time(NULL));
memset(data, 0, sizeof(data));
for (y = 0; y < 28; y ++)
{
for (x = CUPS_RAND() & 127, count = (CUPS_RAND() & 15) + 1;
x < sizeof(data[0]);
x ++, count --)
{
if (count <= 0)
{
x += (CUPS_RAND() & 15) + 1;
count = (CUPS_RAND() & 15) + 1;
if (x >= sizeof(data[0]))
break;
}
data[y][x] = CUPS_RAND();
}
}
if ((r = cupsRasterOpen(fd, mode)) == NULL)
{
perror("Unable to create raster output stream");
return;
}
for (page = 0; page < TEST_PAGES; page ++)
{
memset(&header, 0, sizeof(header));
header.cupsWidth = TEST_WIDTH;
header.cupsHeight = TEST_HEIGHT;
header.cupsBytesPerLine = TEST_WIDTH;
if (page & 1)
{
header.cupsBytesPerLine *= 4;
header.cupsColorSpace = CUPS_CSPACE_CMYK;
header.cupsColorOrder = CUPS_ORDER_CHUNKED;
}
else
{
header.cupsColorSpace = CUPS_CSPACE_K;
header.cupsColorOrder = CUPS_ORDER_BANDED;
}
if (page & 2)
{
header.cupsBytesPerLine *= 2;
header.cupsBitsPerColor = 16;
header.cupsBitsPerPixel = (page & 1) ? 64 : 16;
}
else
{
header.cupsBitsPerColor = 8;
header.cupsBitsPerPixel = (page & 1) ? 32 : 8;
}
cupsRasterWriteHeader2(r, &header);
for (y = 0; y < TEST_HEIGHT; y ++)
cupsRasterWritePixels(r, data[y & 31], header.cupsBytesPerLine);
}
cupsRasterClose(r);
}