1 // file      : examples/performance/expat.cxx
2 // license   : not copyrighted - public domain
3 
4 #include <iostream>
5 #include <fstream>
6 
7 #include <expat.h>
8 
9 #include "time.hxx"
10 
11 using namespace std;
12 
13 const unsigned long iterations = 1000;
14 
15 unsigned long start_count;
16 unsigned long end_count;
17 
18 void XMLCALL
start_element(void * data,const XML_Char * ns_name,const XML_Char ** atts)19 start_element (void* data, const XML_Char* ns_name, const XML_Char** atts)
20 {
21   start_count++;
22 }
23 
24 void XMLCALL
end_element(void * data,const XML_Char * ns_name)25 end_element (void* data, const XML_Char* ns_name)
26 {
27   end_count++;
28 }
29 
30 void XMLCALL
characters(void * data,const XML_Char * s,int n)31 characters (void* data, const XML_Char* s, int n)
32 {
33 }
34 
35 int
main(int argc,char * argv[])36 main (int argc, char* argv[])
37 {
38   if (argc != 2)
39   {
40     cerr << "usage: " << argv[0] << " <xml-file>" << endl;
41     return 1;
42   }
43 
44   try
45   {
46     ifstream ifs;
47     ifs.exceptions (ios_base::failbit);
48     ifs.open (argv[1], ios::in | ios::ate);
49 
50     size_t size (ifs.tellg ());
51     ifs.seekg (0, ios::beg);
52 
53     char* buf = new char[size];
54     ifs.read (buf, size);
55 
56     cerr << "  document size:  " << size << " bytes" << endl;
57 
58     // Warmup.
59     //
60     bool failed (false);
61     for (unsigned long i (0); !failed && i < 10; ++i)
62     {
63       start_count = 0;
64       end_count = 0;
65 
66       XML_Parser p (XML_ParserCreateNS (0, ' '));
67       XML_SetStartElementHandler (p, start_element);
68       XML_SetEndElementHandler (p, end_element);
69       XML_SetCharacterDataHandler (p, characters);
70       XML_Parse (p, buf, size, 1);
71       XML_ParserFree (p);
72 
73       if (start_count != end_count)
74         failed = true;
75     }
76 
77     if (failed)
78     {
79       cerr << "failed" << endl;
80       return 1;
81     }
82 
83     cerr << "  elements:       " << start_count << endl;
84 
85     os::time start;
86 
87     for (unsigned long i (0); !failed && i < 1000; ++i)
88     {
89       start_count = 0;
90       end_count = 0;
91 
92       XML_Parser p (XML_ParserCreateNS (0, ' '));
93       XML_SetStartElementHandler (p, start_element);
94       XML_SetEndElementHandler (p, end_element);
95       XML_SetCharacterDataHandler (p, characters);
96       XML_Parse (p, buf, size, 1);
97       XML_ParserFree (p);
98 
99       if (start_count != end_count)
100         failed = true;
101     }
102 
103     os::time end;
104     delete[] buf;
105 
106     if (failed)
107     {
108       cerr << "failed" << endl;
109       return 1;
110     }
111 
112     os::time time (end - start);
113     double ms (time.sec () * 1000000ULL + time.nsec () / 1000ULL);
114 
115     cerr << "  time:           " << time << " sec" << endl;
116 
117     // Calculate throughput in documents/sec.
118     //
119     double tpd ((iterations / ms) * 1000000);
120     cerr << "  throughput:     " << tpd << " documents/sec" << endl;
121 
122     // Calculate throughput in MBytes/sec.
123     //
124     double tpb (((size * iterations) / ms) * 1000000/(1024*1024));
125     cerr << "  throughput:     " << tpb << " MBytes/sec" << endl;
126   }
127   catch (ios_base::failure const&)
128   {
129     cerr << "io failure" << endl;
130     return 1;
131   }
132 }
133