xref: /openbsd-src/lib/libexpat/tests/benchmark/benchmark.c (revision bd8f1dc3b0e01803a74947836eef57849c13acb0)
12e724bc9Sbluhm /*
22e724bc9Sbluhm                             __  __            _
32e724bc9Sbluhm                          ___\ \/ /_ __   __ _| |_
42e724bc9Sbluhm                         / _ \\  /| '_ \ / _` | __|
52e724bc9Sbluhm                        |  __//  \| |_) | (_| | |_
62e724bc9Sbluhm                         \___/_/\_\ .__/ \__,_|\__|
72e724bc9Sbluhm                                  |_| XML parser
82e724bc9Sbluhm 
908819b41Sbluhm    Copyright (c) 2003-2006 Karl Waclawek <karl@waclawek.net>
10253fd6bfSbluhm    Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
11*bd8f1dc3Sbluhm    Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
1208819b41Sbluhm    Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
132e724bc9Sbluhm    Licensed under the MIT license:
142e724bc9Sbluhm 
152e724bc9Sbluhm    Permission is  hereby granted,  free of charge,  to any  person obtaining
162e724bc9Sbluhm    a  copy  of  this  software   and  associated  documentation  files  (the
172e724bc9Sbluhm    "Software"),  to  deal in  the  Software  without restriction,  including
182e724bc9Sbluhm    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
192e724bc9Sbluhm    distribute, sublicense, and/or sell copies of the Software, and to permit
202e724bc9Sbluhm    persons  to whom  the Software  is  furnished to  do so,  subject to  the
212e724bc9Sbluhm    following conditions:
222e724bc9Sbluhm 
232e724bc9Sbluhm    The above copyright  notice and this permission notice  shall be included
242e724bc9Sbluhm    in all copies or substantial portions of the Software.
252e724bc9Sbluhm 
262e724bc9Sbluhm    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
272e724bc9Sbluhm    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
282e724bc9Sbluhm    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
292e724bc9Sbluhm    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
302e724bc9Sbluhm    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
312e724bc9Sbluhm    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
322e724bc9Sbluhm    USE OR OTHER DEALINGS IN THE SOFTWARE.
332e724bc9Sbluhm */
342e724bc9Sbluhm 
3533ab7b2bSbluhm #include <sys/stat.h>
36*bd8f1dc3Sbluhm #include <assert.h>
37*bd8f1dc3Sbluhm #include <stddef.h> // ptrdiff_t
3833ab7b2bSbluhm #include <stdlib.h>
3933ab7b2bSbluhm #include <stdio.h>
4033ab7b2bSbluhm #include <time.h>
4133ab7b2bSbluhm #include "expat.h"
4233ab7b2bSbluhm 
4333ab7b2bSbluhm #ifdef XML_LARGE_SIZE
4433ab7b2bSbluhm #  define XML_FMT_INT_MOD "ll"
4533ab7b2bSbluhm #else
4633ab7b2bSbluhm #  define XML_FMT_INT_MOD "l"
4733ab7b2bSbluhm #endif
4833ab7b2bSbluhm 
499b8e2351Sbluhm #ifdef XML_UNICODE_WCHAR_T
509b8e2351Sbluhm #  define XML_FMT_STR "ls"
519b8e2351Sbluhm #else
529b8e2351Sbluhm #  define XML_FMT_STR "s"
539b8e2351Sbluhm #endif
549b8e2351Sbluhm 
5533ab7b2bSbluhm static void
usage(const char * prog,int rc)5628ce3119Sbluhm usage(const char *prog, int rc) {
5728ce3119Sbluhm   fprintf(stderr, "usage: %s [-n] filename bufferSize nr_of_loops\n", prog);
5833ab7b2bSbluhm   exit(rc);
5933ab7b2bSbluhm }
6033ab7b2bSbluhm 
6128ce3119Sbluhm int
main(int argc,char * argv[])6228ce3119Sbluhm main(int argc, char *argv[]) {
6333ab7b2bSbluhm   XML_Parser parser;
6433ab7b2bSbluhm   char *XMLBuf, *XMLBufEnd, *XMLBufPtr;
6533ab7b2bSbluhm   FILE *fd;
6633ab7b2bSbluhm   struct stat fileAttr;
67*bd8f1dc3Sbluhm   int nrOfLoops, bufferSize, i, isFinal;
68*bd8f1dc3Sbluhm   size_t fileSize;
6933ab7b2bSbluhm   int j = 0, ns = 0;
7033ab7b2bSbluhm   clock_t tstart, tend;
7133ab7b2bSbluhm   double cpuTime = 0.0;
7233ab7b2bSbluhm 
7333ab7b2bSbluhm   if (argc > 1) {
7433ab7b2bSbluhm     if (argv[1][0] == '-') {
7533ab7b2bSbluhm       if (argv[1][1] == 'n' && argv[1][2] == '\0') {
7633ab7b2bSbluhm         ns = 1;
7733ab7b2bSbluhm         j = 1;
7828ce3119Sbluhm       } else
7933ab7b2bSbluhm         usage(argv[0], 1);
8033ab7b2bSbluhm     }
8133ab7b2bSbluhm   }
8233ab7b2bSbluhm 
8333ab7b2bSbluhm   if (argc != j + 4)
8433ab7b2bSbluhm     usage(argv[0], 1);
8533ab7b2bSbluhm 
8633ab7b2bSbluhm   if (stat(argv[j + 1], &fileAttr) != 0) {
8733ab7b2bSbluhm     fprintf(stderr, "could not access file '%s'\n", argv[j + 1]);
8833ab7b2bSbluhm     return 2;
8933ab7b2bSbluhm   }
9033ab7b2bSbluhm 
9133ab7b2bSbluhm   fd = fopen(argv[j + 1], "r");
9233ab7b2bSbluhm   if (! fd) {
9333ab7b2bSbluhm     fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
9433ab7b2bSbluhm     exit(2);
9533ab7b2bSbluhm   }
9633ab7b2bSbluhm 
9733ab7b2bSbluhm   bufferSize = atoi(argv[j + 2]);
9833ab7b2bSbluhm   nrOfLoops = atoi(argv[j + 3]);
9933ab7b2bSbluhm   if (bufferSize <= 0 || nrOfLoops <= 0) {
10028ce3119Sbluhm     fprintf(stderr, "buffer size and nr of loops must be greater than zero.\n");
10133ab7b2bSbluhm     exit(3);
10233ab7b2bSbluhm   }
10333ab7b2bSbluhm 
10433ab7b2bSbluhm   XMLBuf = malloc(fileAttr.st_size);
10533ab7b2bSbluhm   fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, fd);
10633ab7b2bSbluhm   fclose(fd);
10733ab7b2bSbluhm 
10833ab7b2bSbluhm   if (ns)
10933ab7b2bSbluhm     parser = XML_ParserCreateNS(NULL, '!');
11033ab7b2bSbluhm   else
11133ab7b2bSbluhm     parser = XML_ParserCreate(NULL);
11233ab7b2bSbluhm 
11333ab7b2bSbluhm   i = 0;
11433ab7b2bSbluhm   XMLBufEnd = XMLBuf + fileSize;
11533ab7b2bSbluhm   while (i < nrOfLoops) {
11633ab7b2bSbluhm     XMLBufPtr = XMLBuf;
11733ab7b2bSbluhm     isFinal = 0;
11833ab7b2bSbluhm     tstart = clock();
11933ab7b2bSbluhm     do {
120*bd8f1dc3Sbluhm       ptrdiff_t parseBufferSize = XMLBufEnd - XMLBufPtr;
121*bd8f1dc3Sbluhm       if (parseBufferSize <= (ptrdiff_t)bufferSize)
12233ab7b2bSbluhm         isFinal = 1;
12333ab7b2bSbluhm       else
12433ab7b2bSbluhm         parseBufferSize = bufferSize;
125*bd8f1dc3Sbluhm       assert(parseBufferSize <= (ptrdiff_t)bufferSize);
126*bd8f1dc3Sbluhm       if (! XML_Parse(parser, XMLBufPtr, (int)parseBufferSize, isFinal)) {
1279b8e2351Sbluhm         fprintf(stderr,
12828ce3119Sbluhm                 "error '%" XML_FMT_STR "' at line %" XML_FMT_INT_MOD
12933ab7b2bSbluhm                 "u character %" XML_FMT_INT_MOD "u\n",
13033ab7b2bSbluhm                 XML_ErrorString(XML_GetErrorCode(parser)),
13133ab7b2bSbluhm                 XML_GetCurrentLineNumber(parser),
13233ab7b2bSbluhm                 XML_GetCurrentColumnNumber(parser));
13333ab7b2bSbluhm         free(XMLBuf);
13433ab7b2bSbluhm         XML_ParserFree(parser);
13533ab7b2bSbluhm         exit(4);
13633ab7b2bSbluhm       }
13733ab7b2bSbluhm       XMLBufPtr += bufferSize;
13833ab7b2bSbluhm     } while (! isFinal);
13933ab7b2bSbluhm     tend = clock();
14033ab7b2bSbluhm     cpuTime += ((double)(tend - tstart)) / CLOCKS_PER_SEC;
14133ab7b2bSbluhm     XML_ParserReset(parser, NULL);
14233ab7b2bSbluhm     i++;
14333ab7b2bSbluhm   }
14433ab7b2bSbluhm 
14533ab7b2bSbluhm   XML_ParserFree(parser);
14633ab7b2bSbluhm   free(XMLBuf);
14733ab7b2bSbluhm 
14833ab7b2bSbluhm   printf("%d loops, with buffer size %d. Average time per loop: %f\n",
14933ab7b2bSbluhm          nrOfLoops, bufferSize, cpuTime / (double)nrOfLoops);
15033ab7b2bSbluhm   return 0;
15133ab7b2bSbluhm }
152