kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #38216
[PATCH] In-memory string io_benchmark and some docs
Hi,
Just a couple of tweaks to the io_benchmark, including a baseline
in-memory string-based streams, and some other dev-doc stuff that was
conflicting with the fuzzing docs.
Cheers,
John
From 68955bbcb90c5fc12e4f3a61b6d7df8a2541c64b Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Mon, 8 Oct 2018 19:11:46 +0100
Subject: [PATCH 1/3] Add an in-memory STREAM_LINE_READER benchmark
This adds an io-benchmark case of the STRING_LINE_READER
class, which reads a file into a std::string, *then*
reads it line by line.
As expected, due to it all being in memory, this is very fast.
Also fixes an issue in io_benchmark where the input file
must be in the current dir.
---
qa/qa_utils/stdstream_line_reader.cpp | 4 +-
tools/io_benchmark/io_benchmark.cpp | 75 ++++++++++++++++++++++-----
2 files changed, 64 insertions(+), 15 deletions(-)
diff --git a/qa/qa_utils/stdstream_line_reader.cpp b/qa/qa_utils/stdstream_line_reader.cpp
index 3f6596fdb..d473f3442 100644
--- a/qa/qa_utils/stdstream_line_reader.cpp
+++ b/qa/qa_utils/stdstream_line_reader.cpp
@@ -68,7 +68,7 @@ void STDISTREAM_LINE_READER::SetStream( std::istream& aStream )
IFSTREAM_LINE_READER::IFSTREAM_LINE_READER( const wxFileName& aFileName ) :
- m_fStream( aFileName.GetFullName().ToUTF8() )
+ m_fStream( aFileName.GetFullPath().ToUTF8() )
{
if( !m_fStream.is_open() )
{
@@ -79,7 +79,7 @@ IFSTREAM_LINE_READER::IFSTREAM_LINE_READER( const wxFileName& aFileName ) :
SetStream( m_fStream );
- m_source = aFileName.GetFullName();
+ m_source = aFileName.GetFullPath();
}
diff --git a/tools/io_benchmark/io_benchmark.cpp b/tools/io_benchmark/io_benchmark.cpp
index 9442d9317..7236884d6 100644
--- a/tools/io_benchmark/io_benchmark.cpp
+++ b/tools/io_benchmark/io_benchmark.cpp
@@ -123,7 +123,7 @@ static void bench_line_reader( const wxFileName& aFile, int aReps, BENCH_REPORT&
{
for( int i = 0; i < aReps; ++i)
{
- LR fstr( aFile.GetFullName() );
+ LR fstr( aFile.GetFullPath() );
while( fstr.ReadLine() )
{
report.linesRead++;
@@ -140,7 +140,7 @@ static void bench_line_reader( const wxFileName& aFile, int aReps, BENCH_REPORT&
template<typename LR>
static void bench_line_reader_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
{
- LR fstr( aFile.GetFullName() );
+ LR fstr( aFile.GetFullPath() );
for( int i = 0; i < aReps; ++i)
{
@@ -155,6 +155,53 @@ static void bench_line_reader_reuse( const wxFileName& aFile, int aReps, BENCH_R
}
+/**
+ * Benchmark using STRING_LINE_READER on string data read into memory from a file
+ * using std::ifstream, but read the data fresh from the file each time
+ */
+static void bench_string_lr( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
+{
+ for( int i = 0; i < aReps; ++i)
+ {
+ std::ifstream ifs( aFile.GetFullPath() );
+ std::string content((std::istreambuf_iterator<char>(ifs)),
+ std::istreambuf_iterator<char>());
+
+ STRING_LINE_READER fstr( content, aFile.GetFullPath() );
+ while( fstr.ReadLine() )
+ {
+ report.linesRead++;
+ report.charAcc += (unsigned char) fstr.Line()[0];
+ }
+ }
+}
+
+
+/**
+ * Benchmark using STRING_LINE_READER on string data read into memory from a file
+ * using std::ifstream
+ *
+ * The STRING_LINE_READER is not reused (it cannot be rewound),
+ * but the file is read only once
+ */
+static void bench_string_lr_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
+{
+ std::ifstream ifs( aFile.GetFullPath() );
+ std::string content((std::istreambuf_iterator<char>(ifs)),
+ std::istreambuf_iterator<char>());
+
+ for( int i = 0; i < aReps; ++i)
+ {
+ STRING_LINE_READER fstr( content, aFile.GetFullPath() );
+ while( fstr.ReadLine() )
+ {
+ report.linesRead++;
+ report.charAcc += (unsigned char) fstr.Line()[0];
+ }
+ }
+}
+
+
/**
* Benchmark using an INPUTSTREAM_LINE_READER with a given
* wxInputStream implementation.
@@ -163,11 +210,11 @@ static void bench_line_reader_reuse( const wxFileName& aFile, int aReps, BENCH_R
template<typename S>
static void bench_wxis( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
{
- S fileStream( aFile.GetFullName() );
+ S fileStream( aFile.GetFullPath() );
for( int i = 0; i < aReps; ++i)
{
- INPUTSTREAM_LINE_READER istr( &fileStream, aFile.GetFullName() );
+ INPUTSTREAM_LINE_READER istr( &fileStream, aFile.GetFullPath() );
while( istr.ReadLine() )
{
@@ -188,8 +235,8 @@ static void bench_wxis( const wxFileName& aFile, int aReps, BENCH_REPORT& report
template<typename S>
static void bench_wxis_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
{
- S fileStream( aFile.GetFullName() );
- INPUTSTREAM_LINE_READER istr( &fileStream, aFile.GetFullName() );
+ S fileStream( aFile.GetFullPath() );
+ INPUTSTREAM_LINE_READER istr( &fileStream, aFile.GetFullPath() );
for( int i = 0; i < aReps; ++i)
{
@@ -212,12 +259,12 @@ static void bench_wxis_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT&
template<typename WXIS>
static void bench_wxbis( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
{
- WXIS fileStream( aFile.GetFullName() );
+ WXIS fileStream( aFile.GetFullPath() );
wxBufferedInputStream bufferedStream( fileStream );
for( int i = 0; i < aReps; ++i)
{
- INPUTSTREAM_LINE_READER istr( &bufferedStream, aFile.GetFullName() );
+ INPUTSTREAM_LINE_READER istr( &bufferedStream, aFile.GetFullPath() );
while( istr.ReadLine() )
{
@@ -238,10 +285,10 @@ static void bench_wxbis( const wxFileName& aFile, int aReps, BENCH_REPORT& repor
template<typename WXIS>
static void bench_wxbis_reuse( const wxFileName& aFile, int aReps, BENCH_REPORT& report )
{
- WXIS fileStream( aFile.GetFullName() );
+ WXIS fileStream( aFile.GetFullPath() );
wxBufferedInputStream bufferedStream( fileStream );
- INPUTSTREAM_LINE_READER istr( &bufferedStream, aFile.GetFullName() );
+ INPUTSTREAM_LINE_READER istr( &bufferedStream, aFile.GetFullPath() );
for( int i = 0; i < aReps; ++i)
{
@@ -262,10 +309,12 @@ static std::vector<BENCHMARK> benchmarkList =
{
{ 'f', bench_fstream, "std::fstream" },
{ 'F', bench_fstream_reuse, "std::fstream, reused" },
- { 'r', bench_line_reader<FILE_LINE_READER>, "RICHIO" },
- { 'R', bench_line_reader_reuse<FILE_LINE_READER>, "RICHIO, reused" },
+ { 'r', bench_line_reader<FILE_LINE_READER>, "RichIO FILE_L_R" },
+ { 'R', bench_line_reader_reuse<FILE_LINE_READER>, "RichIO FILE_L_R, reused" },
{ 'n', bench_line_reader<IFSTREAM_LINE_READER>, "std::ifstream L_R" },
{ 'N', bench_line_reader_reuse<IFSTREAM_LINE_READER>, "std::ifstream L_R, reused" },
+ { 's', bench_string_lr, "RichIO STRING_L_R"},
+ { 'S', bench_string_lr_reuse, "RichIO STRING_L_R, reused"},
{ 'w', bench_wxis<wxFileInputStream>, "wxFileIStream" },
{ 'W', bench_wxis<wxFileInputStream>, "wxFileIStream, reused" },
{ 'g', bench_wxis<wxFFileInputStream>, "wxFFileIStream" },
@@ -358,7 +407,7 @@ int main( int argc, char* argv[] )
os << "IO Bench Mark Util" << std::endl;
- os << " Benchmark file: " << inFile.GetFullName() << std::endl;
+ os << " Benchmark file: " << inFile.GetFullPath() << std::endl;
os << " Repetitions: " << (int) reps << std::endl;
os << std::endl;
--
2.19.1
From d972c69795d17f287923cb93bb5f6543b91dc2d5 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Mon, 29 Oct 2018 13:48:12 +0000
Subject: [PATCH 2/3] Docs: printing and trace
Add a quick outline of some of the ways you can dump debug during
debugging. Also include a list of known trace mask strings.
---
Documentation/development/testing.md | 69 ++++++++++++++++++++++++++--
1 file changed, 66 insertions(+), 3 deletions(-)
diff --git a/Documentation/development/testing.md b/Documentation/development/testing.md
index cf0d4c129..9abfbfaea 100644
--- a/Documentation/development/testing.md
+++ b/Documentation/development/testing.md
@@ -112,9 +112,9 @@ testing tool to the function under test.
For example, to use the [AFL fuzzing tool][], you will need:
* A test executable that can:
-** Receive input from `stdin` to be run by `afl-fuzz`.
-** Optional: process input from a filename to allow `afl-tmin` to minimise the
- input files.
+ * Receive input from `stdin` to be run by `afl-fuzz`.
+ * Optional: process input from a filename to allow `afl-tmin` to minimise the
+ input files.
* To compile this executable with an AFL compiler, to enable the instrumentation
that allows the fuzzer to detect the fuzzing state.
@@ -147,6 +147,69 @@ where:
The AFL TUI will then display the fuzzing progress, and you can use the hang- or
crash-provoking inputs to debug code as needed.
+# Run-time debugging #
+
+KiCad can be debugged at run-time, either under a full debugger
+such as GDB, or using simple methods like logging debug to the
+console.
+
+## Printing debug ##
+
+If you are compiling KiCad yourself, you can simply add debugging statements to
+relevant places in the code, for example:
+
+ wxLogDebug( "Value of variable: %d", my_int );
+
+This produces debug output that can only be seen when compiling
+in Debug mode.
+
+You can also use `std::cout` and `printf`.
+
+Ensure you do not leave this kind of debugging in place when
+submitting code.
+
+## Printing trace ##
+
+Some parts of the code have "trace" that can be enabled selectively according to
+a "mask", for example:
+
+ wxLogTrace( "TRACEMASK", "My trace, value: %d", my_int );
+
+This will not be printed by default. To show it, set the `WXTRACE` environment
+variable when you run KiCad to include the masks you wish to enable:
+
+ $ WXTRACE="TRACEKEY,OTHERKEY" kicad
+
+When printed, the debug will be prefixed with a timestamp and the trace mask:
+
+ 11:22:33: Trace: (KICAD_FIND_ITEM) item Symbol GNDPWR, #PWR020
+
+Some available masks:
+
+* Core KiCad functions:
+ * `KICAD_KEY_EVENTS`
+ * `KicadScrollSettings`
+ * `KICAD_FIND_ITEM`
+ * `KICAD_FIND_REPLACE`
+ * `KICAD_NGSPICE`
+ * `KICAD_PLUGINLOADER`
+ * `GAL_PROFILE`
+ * `GAL_CACHED_CONTAINER`
+ * `PNS`
+ * `CN`
+* Plugin-specific (including "standard" KiCad formats):
+ * `3D_CACHE`
+ * `3D_SG`
+ * `3D_RESOLVER`
+ * `3D_PLUGIN_MANAGER`
+ * `KI_TRACE_CCAMERA`
+ * `PLUGIN_IDF`
+ * `PLUGIN_VRML`
+ * `KICAD_SCH_LEGACY_PLUGIN`
+ * `KICAD_GEDA_PLUGIN`
+ * `KICAD_PCB_PLUGIN`
+
+
[CTest]: https://cmake.org/cmake/help/latest/module/CTest.html
[Boost Unit Test framework]: https://www.boost.org/doc/libs/1_68_0/libs/test/doc/html/index.html
[boost-test-functions]: https://www.boost.org/doc/libs/1_68_0/libs/test/doc/html/boost_test/utf_reference/testing_tool_ref.html
--
2.19.1
From 86ed3746a5560f48081b6f145f634d280daa0915 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Mon, 29 Oct 2018 13:52:44 +0000
Subject: [PATCH 3/3] Dev docs: Add TOC to testing markdown
---
Documentation/development/testing.md | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/Documentation/development/testing.md b/Documentation/development/testing.md
index 9abfbfaea..0b47d13a1 100644
--- a/Documentation/development/testing.md
+++ b/Documentation/development/testing.md
@@ -1,6 +1,8 @@
# Testing KiCad #
-# Unit tests #
+[TOC]
+
+# Unit tests {#unit-tests}
KiCad has a limited number of unit tests, which can be used to
check that certain functionality works.
@@ -13,13 +15,13 @@ required to add a test to the testing suite.
The test CMake targets generally start with `qa_`, the names of the tests
within CTest are the same but without the `qa_` prefix.
-## Running tests ##
+## Running tests {#running-tests}
You can run all tests after building with `make test` or `ctest`. The latter
option allows many CTest options which can be useful, especially in automated
or CI environments.
-### Running specific tests ##
+### Running specific tests {#running-specific-tests}
To run a specific test executable, you can just run with `ctest` or run
the executable directly. Running directly is often the simplest way when
@@ -42,7 +44,7 @@ Common useful patterns:
You can rebuild just a specific test with CMake to avoid rebuilding
everything when working on a small area, e.g. `make qa_common`.
-### Writing Boost tests ###
+## Writing Boost tests {#writing-boost-tests}
Boost unit tests are straightforward to write. Individual test cases can be
registered with:
@@ -68,7 +70,7 @@ messages inside tested functions (i.e. where you don't have access to the Boost
unit test headers). These will always be printed, so take care
to remove them before committing, or they'll show up when KiCad runs normally!
-## Python modules ##
+## Python modules {#python-tests}
The Pcbnew Python modules have some test programs in the `qa` directory.
You must have the `KICAD_SCRIPTING_MODULES` option on in CMake to
@@ -87,7 +89,7 @@ from the source tree:
cd /path/to/kicad/source/qa
python2 testcase/test_001_pcb_load.py
-### Diagnosing segfaults ###
+### Diagnosing segfaults {#python-segfaults}
Although the module is Python, it links against a C++ library
(the same one used by KiCad Pcbnew), so it can segfault if the library
@@ -103,7 +105,7 @@ You can run the tests in GDB to trace this:
If the test segfaults, you will get a familiar backtrace, just like
if you were running pcbnew under GDB.
-## Fuzz testing ##
+# Fuzz testing {#fuzz-testing}
It is possible to run fuzz testing on some parts of KiCad. To do this for a
generic function, you need to be able to pass some kind of input from the fuzz
@@ -147,13 +149,13 @@ where:
The AFL TUI will then display the fuzzing progress, and you can use the hang- or
crash-provoking inputs to debug code as needed.
-# Run-time debugging #
+# Run-time debugging {#run-time}
KiCad can be debugged at run-time, either under a full debugger
such as GDB, or using simple methods like logging debug to the
console.
-## Printing debug ##
+## Printing debug {#print-debug}
If you are compiling KiCad yourself, you can simply add debugging statements to
relevant places in the code, for example:
@@ -168,7 +170,7 @@ You can also use `std::cout` and `printf`.
Ensure you do not leave this kind of debugging in place when
submitting code.
-## Printing trace ##
+## Printing trace {#trace-debug}
Some parts of the code have "trace" that can be enabled selectively according to
a "mask", for example:
--
2.19.1
Follow ups