KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_group_save_perf.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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
37
38#include <algorithm>
39#include <cstddef>
40#include <filesystem>
41#include <limits>
42#include <memory>
43#include <string>
44#include <vector>
45
46#include <qa_utils/file_utils.h>
48
49#include <board.h>
50#include <core/profile.h>
51#include <lset.h>
52#include <pcb_group.h>
53#include <pcb_shape.h>
56
57
58namespace
59{
60
70std::unique_ptr<BOARD> buildBoardWithGroups( std::size_t aGroupCount, std::size_t aTotalShapes )
71{
72 auto board = std::make_unique<BOARD>();
73 board->SetEnabledLayers( LSET::AllCuMask() | LSET::AllTechMask() );
74
75 std::vector<PCB_GROUP*> groups;
76 groups.reserve( aGroupCount );
77
78 for( std::size_t g = 0; g < aGroupCount; ++g )
79 {
80 PCB_GROUP* group = new PCB_GROUP( board.get() );
81 group->SetName( wxString::Format( wxT( "G%zu" ), g ) );
82 board->Add( group );
83 groups.push_back( group );
84 }
85
86 for( std::size_t i = 0; i < aTotalShapes; ++i )
87 {
88 PCB_SHAPE* shape = new PCB_SHAPE( board.get(), SHAPE_T::SEGMENT );
89 int x = static_cast<int>( i );
90 shape->SetStart( VECTOR2I( x, 0 ) );
91 shape->SetEnd( VECTOR2I( x + pcbIUScale.mmToIU( 1 ), 0 ) );
92 shape->SetLayer( F_SilkS );
93 shape->SetStroke( STROKE_PARAMS( pcbIUScale.mmToIU( 0.1 ), LINE_STYLE::SOLID ) );
94 board->Add( shape );
95
96 if( !groups.empty() )
97 groups[i % groups.size()]->AddItem( shape );
98 }
99
100 return board;
101}
102
103
110double saveBoardSeconds( const std::filesystem::path& aDir, std::size_t aGroupCount,
111 std::size_t aTotalShapes )
112{
113 auto board = buildBoardWithGroups( aGroupCount, aTotalShapes );
114
115 const std::filesystem::path savePath =
116 aDir / ( "groups" + std::to_string( aGroupCount ) + ".kicad_pcb" );
117
118 PROF_TIMER timer;
119 KI_TEST::DumpBoardToFile( *board, savePath.string() );
120 timer.Stop();
121
122 return timer.msecs() / 1000.0;
123}
124
125} // namespace
126
127
128BOOST_AUTO_TEST_SUITE( GroupSavePerformance )
129
130
131
142BOOST_AUTO_TEST_CASE( SaveScalesLinearlyWithGroupCount )
143{
144 constexpr std::size_t kTotalShapes = 5000;
145
146 KI_TEST::SCOPED_TEMP_DIR tempDir( "group_save_perf" );
147
148 // Warm up the save path (allocators, formatter, disk cache) so the first
149 // measurement is not dominated by one-shot setup costs.
150 (void) saveBoardSeconds( tempDir.Path(), 10, 100 );
151
152 // Take the best of two runs per configuration so a scheduler stall during
153 // a single save cannot fail the test on a loaded CI machine.
154 auto bestSave =
155 [&]( std::size_t aGroupCount )
156 {
157 double best = std::numeric_limits<double>::infinity();
158
159 for( int run = 0; run < 2; ++run )
160 {
161 best = std::min( best, saveBoardSeconds( tempDir.Path(), aGroupCount,
162 kTotalShapes ) );
163 }
164
165 return best;
166 };
167
168 double t100 = bestSave( 100 );
169 double t5000 = bestSave( 5000 );
170
171 BOOST_TEST_MESSAGE( "Save time (s) 100 groups : " << t100 );
172 BOOST_TEST_MESSAGE( "Save time (s) 5000 groups : " << t5000 );
173
174 // Use a 5 ms floor so very fast runs do not produce huge ratios from
175 // measurement jitter.
176 const double floorSec = 0.005;
177 double ratio = t5000 / std::max( t100, floorSec );
178
179 BOOST_TEST_MESSAGE( "Ratio (5000 / 100): " << ratio );
180
181 // Linear scaling in the group count gives a small single-digit ratio here
182 // because the serialised output is dominated by the shared 5000 shapes.
183 // The unfixed O(Groups * BoardItems) code rescans the full item cache for
184 // each of the 5000 groups and lands far above this bound.
185 BOOST_CHECK_LT( ratio, 20.0 );
186}
187
188
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
General utilities for PCB file IO for QA programs.
const std::filesystem::path & Path() const
Get the path to the temporary directory as a std::filesystem::path.
Definition file_utils.h:59
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition lset.cpp:672
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:595
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:51
void SetEnd(const VECTOR2I &aEnd) override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
void SetStroke(const STROKE_PARAMS &aStroke) override
A small class to help profiling.
Definition profile.h:46
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition profile.h:86
double msecs(bool aSinceLast=false)
Definition profile.h:147
Simple container to manage line stroke parameters.
@ SEGMENT
Definition eda_shape.h:56
@ F_SilkS
Definition layer_ids.h:96
void DumpBoardToFile(BOARD &board, const std::filesystem::path &aFilename)
Utility function to simply write a Board out to a file.
Class to handle a set of BOARD_ITEMs.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683