KiCad PCB EDA Suite
Loading...
Searching...
No Matches
io_benchmark.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <wx/wx.h>
21#include <richio.h>
22
23#include <chrono>
24#include <ios>
25#include <functional>
26#include <iostream>
27
28#include <fstream>
29
30#include <wx/wfstream.h>
31#include <wx/filename.h>
32
35
36
37using CLOCK = std::chrono::steady_clock;
38using TIME_PT = std::chrono::time_point<CLOCK>;
39
40
42{
43 unsigned linesRead;
44
50 unsigned charAcc;
51
52 std::chrono::milliseconds benchDurMs;
53};
54
55
56using BENCH_FUNC = std::function<void(const wxFileName&, int, BENCH_REPORT&)>;
57
58
60{
63 wxString name;
64};
65
66
71static void bench_fstream( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
72{
73 std::string line;
74
75 for( int i = 0; i < aReps; ++i)
76 {
77 std::ifstream fstr( aFile.GetFullPath().fn_str() );
78
79 while( getline( fstr, line ) )
80 {
81 report.linesRead++;
82 report.charAcc += (unsigned char) line[0];
83 }
84
85 fstr.close();
86 }
87}
88
89
94static void bench_fstream_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
95{
96 std::string line;
97 std::ifstream fstr( aFile.GetFullPath().fn_str() );
98
99 for( int i = 0; i < aReps; ++i)
100 {
101 while( getline( fstr, line ) )
102 {
103 report.linesRead++;
104 report.charAcc += (unsigned char) line[0];
105 }
106 fstr.clear() ;
107 fstr.seekg(0, std::ios::beg) ;
108 }
109
110 fstr.close();
111}
112
113
118template<typename LR>
119static void bench_line_reader( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
120{
121 for( int i = 0; i < aReps; ++i)
122 {
123 LR fstr( aFile.GetFullPath() );
124 while( fstr.ReadLine() )
125 {
126 report.linesRead++;
127 report.charAcc += (unsigned char) fstr.Line()[0];
128 }
129 }
130}
131
132
137template<typename LR>
138static void bench_line_reader_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
139{
140 LR fstr( aFile.GetFullPath() );
141 for( int i = 0; i < aReps; ++i)
142 {
143
144 while( fstr.ReadLine() )
145 {
146 report.linesRead++;
147 report.charAcc += (unsigned char) fstr.Line()[0];
148 }
149
150 fstr.Rewind();
151 }
152}
153
154
159static void bench_string_lr( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
160{
161 for( int i = 0; i < aReps; ++i)
162 {
163 std::ifstream ifs( aFile.GetFullPath().ToStdString() );
164 std::string content((std::istreambuf_iterator<char>(ifs)),
165 std::istreambuf_iterator<char>());
166
167 STRING_LINE_READER fstr( content, aFile.GetFullPath() );
168 while( fstr.ReadLine() )
169 {
170 report.linesRead++;
171 report.charAcc += (unsigned char) fstr.Line()[0];
172 }
173 }
174}
175
176
184static void bench_string_lr_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
185{
186 std::ifstream ifs( aFile.GetFullPath().ToStdString() );
187 std::string content((std::istreambuf_iterator<char>(ifs)),
188 std::istreambuf_iterator<char>());
189
190 for( int i = 0; i < aReps; ++i)
191 {
192 STRING_LINE_READER fstr( content, aFile.GetFullPath() );
193 while( fstr.ReadLine() )
194 {
195 report.linesRead++;
196 report.charAcc += (unsigned char) fstr.Line()[0];
197 }
198 }
199}
200
201
207template<typename S>
208static void bench_wxis( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
209{
210 S fileStream( aFile.GetFullPath() );
211
212 for( int i = 0; i < aReps; ++i)
213 {
214 INPUTSTREAM_LINE_READER istr( &fileStream, aFile.GetFullPath() );
215
216 while( istr.ReadLine() )
217 {
218 report.linesRead++;
219 report.charAcc += (unsigned char) istr.Line()[0];
220 }
221
222 fileStream.SeekI( 0 );
223 }
224}
225
226
232template<typename S>
233static void bench_wxis_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
234{
235 S fileStream( aFile.GetFullPath() );
236 INPUTSTREAM_LINE_READER istr( &fileStream, aFile.GetFullPath() );
237
238 for( int i = 0; i < aReps; ++i)
239 {
240 while( istr.ReadLine() )
241 {
242 report.linesRead++;
243 report.charAcc += (unsigned char) istr.Line()[0];
244 }
245
246 fileStream.SeekI( 0 );
247 }
248}
249
250
256template<typename WXIS>
257static void bench_wxbis( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
258{
259 WXIS fileStream( aFile.GetFullPath() );
260 wxBufferedInputStream bufferedStream( fileStream );
261
262 for( int i = 0; i < aReps; ++i)
263 {
264 INPUTSTREAM_LINE_READER istr( &bufferedStream, aFile.GetFullPath() );
265
266 while( istr.ReadLine() )
267 {
268 report.linesRead++;
269 report.charAcc += (unsigned char) istr.Line()[0];
270 }
271
272 fileStream.SeekI( 0 );
273 }
274}
275
276
282template<typename WXIS>
283static void bench_wxbis_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
284{
285 WXIS fileStream( aFile.GetFullPath() );
286 wxBufferedInputStream bufferedStream( fileStream );
287
288 INPUTSTREAM_LINE_READER istr( &bufferedStream, aFile.GetFullPath() );
289
290 for( int i = 0; i < aReps; ++i)
291 {
292 while( istr.ReadLine() )
293 {
294 report.linesRead++;
295 report.charAcc += (unsigned char) istr.Line()[0];
296 }
297
298 fileStream.SeekI( 0 );
299 }
300}
301
305static std::vector<BENCHMARK> benchmarkList =
306{
307 { 'f', bench_fstream, "std::fstream" },
308 { 'F', bench_fstream_reuse, "std::fstream, reused" },
309 { 'r', bench_line_reader<FILE_LINE_READER>, "RichIO FILE_L_R" },
310 { 'R', bench_line_reader_reuse<FILE_LINE_READER>, "RichIO FILE_L_R, reused" },
311 { 'n', bench_line_reader<IFSTREAM_LINE_READER>, "std::ifstream L_R" },
312 { 'N', bench_line_reader_reuse<IFSTREAM_LINE_READER>, "std::ifstream L_R, reused" },
313 { 's', bench_string_lr, "RichIO STRING_L_R"},
314 { 'S', bench_string_lr_reuse, "RichIO STRING_L_R, reused"},
315 { 'w', bench_wxis<wxFileInputStream>, "wxFileIStream" },
316 { 'W', bench_wxis<wxFileInputStream>, "wxFileIStream, reused" },
317 { 'g', bench_wxis<wxFFileInputStream>, "wxFFileIStream" },
318 { 'G', bench_wxis_reuse<wxFFileInputStream>, "wxFFileIStream, reused" },
319 { 'b', bench_wxbis<wxFileInputStream>, "wxFileIStream. buf'd" },
320 { 'B', bench_wxbis_reuse<wxFileInputStream>, "wxFileIStream, buf'd, reused" },
321 { 'c', bench_wxbis<wxFFileInputStream>, "wxFFileIStream. buf'd" },
322 { 'C', bench_wxbis_reuse<wxFFileInputStream>, "wxFFileIStream, buf'd, reused" },
323};
324
325
330static wxString getBenchFlags()
331{
332 wxString flags;
333
334 for( auto& bmark : benchmarkList )
335 {
336 flags << bmark.triggerChar;
337 }
338
339 return flags;
340}
341
342
346static wxString getBenchDescriptions()
347{
348 wxString desc;
349
350 for( auto& bmark : benchmarkList )
351 {
352 desc << " " << bmark.triggerChar << ": " << bmark.name << "\n";
353 }
354
355 return desc;
356}
357
358
359BENCH_REPORT executeBenchMark( const BENCHMARK& aBenchmark, int aReps,
360 const wxFileName& aFilename )
361{
362 BENCH_REPORT report = {};
363
364 TIME_PT start = CLOCK::now();
365 aBenchmark.func( aFilename, aReps, report );
366 TIME_PT end = CLOCK::now();
367
368 using std::chrono::milliseconds;
369 using std::chrono::duration_cast;
370
371 report.benchDurMs = duration_cast<milliseconds>( end - start );
372
373 return report;
374}
375
376
377int io_benchmark_func( int argc, char* argv[] )
378{
379 auto& os = std::cout;
380
381 if (argc < 3)
382 {
383 os << "Usage: " << argv[0] << " <FILE> <REPS> [" << getBenchFlags() << "]\n\n";
384 os << "Benchmarks:\n";
385 os << getBenchDescriptions();
387 }
388
389 wxFileName inFile( argv[1] );
390
391 long reps = 0;
392 wxString( argv[2] ).ToLong( &reps );
393
394 // get the benchmark to do, or all of them if nothing given
395 wxString bench;
396 if ( argc == 4 )
397 bench = argv[3];
398
399 os << "IO Bench Mark Util" << std::endl;
400
401 os << " Benchmark file: " << inFile.GetFullPath() << std::endl;
402 os << " Repetitions: " << (int) reps << std::endl;
403 os << std::endl;
404
405 for( auto& bmark : benchmarkList )
406 {
407 if( bench.size() && !bench.Contains( bmark.triggerChar ) )
408 continue;
409
410 BENCH_REPORT report = executeBenchMark( bmark, reps, inFile );
411
412 os << wxString::Format( "%-30s %u lines, acc: %u in %u ms",
413 bmark.name, report.linesRead, report.charAcc, (int) report.benchDurMs.count() )
414 << std::endl;;
415 }
416
418}
419
420
422 "io_benchmark",
423 "Benchmark various kinds of IO methods",
425} );
A LINE_READER that reads from a wxInputStream object.
Definition richio.h:256
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
Definition richio.cpp:306
char * Line() const
Return a pointer to the last line that was read in.
Definition richio.h:98
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:222
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
Definition richio.cpp:265
static bool Register(const KI_TEST::UTILITY_PROGRAM &aProgInfo)
Register a utility program factory function against an ID string.
static bool registered
static void bench_fstream_reuse(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using a raw std::ifstream, with no LINE_READER wrapper.
int io_benchmark_func(int argc, char *argv[])
static void bench_line_reader(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using a given LINE_READER implementation.
static wxString getBenchFlags()
Construct string of all flags used for specifying benchmarks on the command line.
BENCH_REPORT executeBenchMark(const BENCHMARK &aBenchmark, int aReps, const wxFileName &aFilename)
static void bench_wxis_reuse(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using an INPUTSTREAM_LINE_READER with a given wxInputStream implementation.
static void bench_line_reader_reuse(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using a given LINE_READER implementation.
std::function< void(const wxFileName &, int, BENCH_REPORT &)> BENCH_FUNC
static void bench_wxbis(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using a INPUTSTREAM_LINE_READER with a given wxInputStream implementation,...
static void bench_string_lr_reuse(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using STRING_LINE_READER on string data read into memory from a file using std::ifstream.
static void bench_wxbis_reuse(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using a INPUTSTREAM_LINE_READER with a given wxInputStream implementation,...
std::chrono::time_point< CLOCK > TIME_PT
static void bench_string_lr(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using STRING_LINE_READER on string data read into memory from a file using std::ifstream,...
std::chrono::steady_clock CLOCK
static void bench_fstream(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using a raw std::ifstream, with no LINE_READER wrapper.
static std::vector< BENCHMARK > benchmarkList
List of available benchmarks.
static void bench_wxis(const wxFileName &aFile, int aReps, BENCH_REPORT &report)
Benchmark using an INPUTSTREAM_LINE_READER with a given wxInputStream implementation.
static wxString getBenchDescriptions()
Usage description of a benchmakr spec.
@ S
Solder (HASL/SMOBC)
@ OK
Tool exited OK.
@ BAD_CMDLINE
The command line was not correct for the tool.
BENCH_FUNC func
wxString name
unsigned charAcc
Char accumulator, used to prevent compilers optimising away otherwise unused line buffers,...
std::chrono::milliseconds benchDurMs
unsigned linesRead
VECTOR2I end