Performance improvements.

Don't construct a wxString or a LSEQ when you don't
have to.  They're both more expensive than you might
think.
This commit is contained in:
Jeff Young 2024-06-12 11:05:56 +01:00
parent 63cd110720
commit 694a7db457
13 changed files with 181 additions and 132 deletions

View File

@ -83,8 +83,11 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
hash_combine( ret, via->TopLayer() ); hash_combine( ret, via->TopLayer() );
hash_combine( ret, via->BottomLayer() ); hash_combine( ret, via->BottomLayer() );
for( PCB_LAYER_ID layer : via->GetLayerSet().Seq() ) via->GetLayerSet().RunOnLayers(
hash_combine( ret, via->FlashLayer( layer ) ); [&]( PCB_LAYER_ID layer )
{
hash_combine( ret, via->FlashLayer( layer ) );
} );
break; break;
} }
@ -102,8 +105,11 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
hash_combine( ret, pad->GetDrillSizeX(), pad->GetDrillSizeY() ); hash_combine( ret, pad->GetDrillSizeX(), pad->GetDrillSizeY() );
hash_combine( ret, pad->GetDrillShape() ); hash_combine( ret, pad->GetDrillShape() );
for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() ) pad->GetLayerSet().RunOnLayers(
hash_combine( ret, pad->FlashLayer( layer ) ); [&]( PCB_LAYER_ID layer )
{
hash_combine( ret, pad->FlashLayer( layer ) );
} );
} }
hash_combine( ret, pad->GetSize().x, pad->GetSize().y ); hash_combine( ret, pad->GetSize().x, pad->GetSize().y );

View File

@ -815,6 +815,18 @@ public:
*/ */
LSEQ SeqStackupForPlotting() const; LSEQ SeqStackupForPlotting() const;
/**
* Execute a function on each layer of the LSET.
*/
void RunOnLayers( const std::function<void( PCB_LAYER_ID )>& aFunction ) const
{
for( size_t ii = 0; ii < size(); ++ii )
{
if( test( ii ) )
aFunction( PCB_LAYER_ID( ii ) );
}
}
/** /**
* Return a hex string showing contents of this LSEQ. * Return a hex string showing contents of this LSEQ.
*/ */

View File

@ -132,16 +132,20 @@ wxString BOARD_CONNECTED_ITEM::GetNetnameMsg() const
} }
wxString BOARD_CONNECTED_ITEM::GetShortNetname() const const wxString& BOARD_CONNECTED_ITEM::GetShortNetname() const
{ {
return m_netinfo ? m_netinfo->GetShortNetname() : wxString(); static wxString emptyString;
return m_netinfo ? m_netinfo->GetShortNetname() : emptyString;
} }
wxString BOARD_CONNECTED_ITEM::GetDisplayNetname() const const wxString& BOARD_CONNECTED_ITEM::GetDisplayNetname() const
{ {
static wxString emptyString;
if( !m_netinfo ) if( !m_netinfo )
return wxString(); return emptyString;
if( const BOARD* board = GetBoard() ) if( const BOARD* board = GetBoard() )
{ {

View File

@ -124,12 +124,12 @@ public:
/** /**
* @return the short netname. * @return the short netname.
*/ */
wxString GetShortNetname() const; const wxString& GetShortNetname() const;
/** /**
* @return the unescaped short netname. * @return the unescaped short netname.
*/ */
wxString GetDisplayNetname() const; const wxString& GetDisplayNetname() const;
/** /**
* Return an item's "own" clearance in internal units. * Return an item's "own" clearance in internal units.

View File

@ -200,11 +200,12 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem )
BOARD* board = zone->GetBoard(); BOARD* board = zone->GetBoard();
LSET layerset = board->GetEnabledLayers() & zone->GetLayerSet(); LSET layerset = board->GetEnabledLayers() & zone->GetLayerSet();
for( PCB_LAYER_ID layer : layerset.Seq() ) layerset.RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
for( CN_ITEM* zitem : m_itemList.Add( zone, layer ) ) {
m_itemMap[zone].Link( zitem ); for( CN_ITEM* zitem : m_itemList.Add( zone, layer ) )
} m_itemMap[zone].Link( zitem );
} );
} }
break; break;
@ -456,11 +457,12 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
BOARD* board = zone->GetBoard(); BOARD* board = zone->GetBoard();
LSET layerset = board->GetEnabledLayers() & zone->GetLayerSet() & LSET::AllCuMask(); LSET layerset = board->GetEnabledLayers() & zone->GetLayerSet() & LSET::AllCuMask();
for( PCB_LAYER_ID layer : layerset.Seq() ) layerset.RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
for( int j = 0; j < zone->GetFilledPolysList( layer )->OutlineCount(); j++ ) {
zitems.push_back( new CN_ZONE_LAYER( zone, layer, j ) ); for( int j = 0; j < zone->GetFilledPolysList( layer )->OutlineCount(); j++ )
} zitems.push_back( new CN_ZONE_LAYER( zone, layer, j ) );
} );
} }
} }
@ -899,39 +901,43 @@ bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
LSET commonLayers = parentA->GetLayerSet() & parentB->GetLayerSet(); LSET commonLayers = parentA->GetLayerSet() & parentB->GetLayerSet();
for( PCB_LAYER_ID layer : commonLayers.Seq() ) for( size_t ii = 0; ii < commonLayers.size(); ++ii )
{ {
FLASHING flashingA = FLASHING::NEVER_FLASHED; if( commonLayers.test( ii ) )
FLASHING flashingB = FLASHING::NEVER_FLASHED; {
PCB_LAYER_ID layer = PCB_LAYER_ID( ii );
FLASHING flashingA = FLASHING::NEVER_FLASHED;
FLASHING flashingB = FLASHING::NEVER_FLASHED;
if( parentA->Type() == PCB_PAD_T ) if( parentA->Type() == PCB_PAD_T )
{ {
if( !static_cast<const PAD*>( parentA )->ConditionallyFlashed( layer ) ) if( !static_cast<const PAD*>( parentA )->ConditionallyFlashed( layer ) )
flashingA = FLASHING::ALWAYS_FLASHED; flashingA = FLASHING::ALWAYS_FLASHED;
} }
else if( parentA->Type() == PCB_VIA_T ) else if( parentA->Type() == PCB_VIA_T )
{ {
if( !static_cast<const PCB_VIA*>( parentA )->ConditionallyFlashed( layer ) ) if( !static_cast<const PCB_VIA*>( parentA )->ConditionallyFlashed( layer ) )
flashingA = FLASHING::ALWAYS_FLASHED; flashingA = FLASHING::ALWAYS_FLASHED;
} }
if( parentB->Type() == PCB_PAD_T ) if( parentB->Type() == PCB_PAD_T )
{ {
if( !static_cast<const PAD*>( parentB )->ConditionallyFlashed( layer ) ) if( !static_cast<const PAD*>( parentB )->ConditionallyFlashed( layer ) )
flashingB = FLASHING::ALWAYS_FLASHED; flashingB = FLASHING::ALWAYS_FLASHED;
} }
else if( parentB->Type() == PCB_VIA_T ) else if( parentB->Type() == PCB_VIA_T )
{ {
if( !static_cast<const PCB_VIA*>( parentB )->ConditionallyFlashed( layer ) ) if( !static_cast<const PCB_VIA*>( parentB )->ConditionallyFlashed( layer ) )
flashingB = FLASHING::ALWAYS_FLASHED; flashingB = FLASHING::ALWAYS_FLASHED;
} }
if( parentA->GetEffectiveShape( layer, flashingA )->Collide( if( parentA->GetEffectiveShape( layer, flashingA )->Collide(
parentB->GetEffectiveShape( layer, flashingB ).get() ) ) parentB->GetEffectiveShape( layer, flashingB ).get() ) )
{ {
m_item->Connect( aCandidate ); m_item->Connect( aCandidate );
aCandidate->Connect( m_item ); aCandidate->Connect( m_item );
return true; return true;
}
} }
} }

View File

@ -111,11 +111,11 @@ bool DRC_CACHE_GENERATOR::Run()
copperLayers = boardCopperLayers; copperLayers = boardCopperLayers;
} }
for( PCB_LAYER_ID layer : copperLayers.Seq() ) copperLayers.RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
if( IsCopperLayer( layer ) ) {
m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance ); m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance );
} } );
done.fetch_add( 1 ); done.fetch_add( 1 );
return true; return true;
@ -179,11 +179,12 @@ bool DRC_CACHE_GENERATOR::Run()
{ {
std::unique_ptr<DRC_RTREE> rtree = std::make_unique<DRC_RTREE>(); std::unique_ptr<DRC_RTREE> rtree = std::make_unique<DRC_RTREE>();
for( PCB_LAYER_ID layer : aZone->GetLayerSet().Seq() ) aZone->GetLayerSet().RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
if( IsCopperLayer( layer ) ) {
rtree->Insert( aZone, layer ); if( IsCopperLayer( layer ) )
} rtree->Insert( aZone, layer );
} );
{ {
std::unique_lock<std::shared_mutex> writeLock( m_board->m_CachesMutex ); std::unique_lock<std::shared_mutex> writeLock( m_board->m_CachesMutex );
@ -218,8 +219,11 @@ bool DRC_CACHE_GENERATOR::Run()
{ {
if( !zone->GetIsRuleArea() && !zone->IsTeardropArea() ) if( !zone->GetIsRuleArea() && !zone->IsTeardropArea() )
{ {
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() ) zone->GetLayerSet().RunOnLayers(
m_board->m_ZoneIsolatedIslandsMap[ zone ][ layer ] = ISOLATED_ISLANDS(); [&]( PCB_LAYER_ID layer )
{
m_board->m_ZoneIsolatedIslandsMap[ zone ][ layer ] = ISOLATED_ISLANDS();
} );
} }
} }

View File

@ -134,16 +134,21 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
if( zoneRTree ) if( zoneRTree )
{ {
for( PCB_LAYER_ID layer : ruleArea->GetLayerSet().Seq() ) for( size_t ii = 0; ii < ruleArea->GetLayerSet().size(); ++ii )
{ {
if( zoneRTree->QueryColliding( areaBBox, &areaPoly, layer ) ) if( ruleArea->GetLayerSet().test( ii ) )
{ {
isInside = true; PCB_LAYER_ID layer = PCB_LAYER_ID( ii );
break;
}
if( m_drcEngine->IsCancelled() ) if( zoneRTree->QueryColliding( areaBBox, &areaPoly, layer ) )
return 0; {
isInside = true;
break;
}
if( m_drcEngine->IsCancelled() )
return 0;
}
} }
} }
} }
@ -217,7 +222,7 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
DRC_RULE* rule = constraint.GetParentRule(); DRC_RULE* rule = constraint.GetParentRule();
VECTOR2I pos = item->GetPosition(); VECTOR2I pos = item->GetPosition();
PCB_LAYER_ID layer = UNDEFINED_LAYER; PCB_LAYER_ID layer = item->GetLayerSet().ExtractLayer();
wxString msg; wxString msg;
msg.Printf( drcItem->GetErrorText() + wxS( " (%s)" ), constraint.GetName() ); msg.Printf( drcItem->GetErrorText() + wxS( " (%s)" ), constraint.GetName() );
@ -226,9 +231,6 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
drcItem->SetItems( item ); drcItem->SetItems( item );
drcItem->SetViolatingRule( rule ); drcItem->SetViolatingRule( rule );
if( item->GetLayerSet().count() )
layer = item->GetLayerSet().Seq().front();
if( rule->m_Implicit ) if( rule->m_Implicit )
{ {
// Provide a better location for keepout area collisions. // Provide a better location for keepout area collisions.

View File

@ -572,7 +572,7 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
{ {
// For single-layer objects, exclude all layers including ancillary layers // For single-layer objects, exclude all layers including ancillary layers
// such as holes, netnames, etc. // such as holes, netnames, etc.
PCB_LAYER_ID singleLayer = item->GetLayerSet().Seq()[0]; PCB_LAYER_ID singleLayer = item->GetLayerSet().ExtractLayer();
if( parentFP->GetPrivateLayers().test( singleLayer ) ) if( parentFP->GetPrivateLayers().test( singleLayer ) )
return false; return false;

View File

@ -908,20 +908,21 @@ void PCB_VIA::SetLayerSet( LSET aLayerSet )
{ {
bool first = true; bool first = true;
for( PCB_LAYER_ID layer : aLayerSet.Seq() ) aLayerSet.RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
// m_layer and m_bottomLayer are copper layers, so consider only copper layers in aLayerSet {
if( !IsCopperLayer( layer ) ) // m_layer and m_bottomLayer are copper layers, so consider only copper layers
continue; if( IsCopperLayer( layer ) )
{
if( first )
{
Padstack().Drill().start = layer;
first = false;
}
if( first ) Padstack().Drill().end = layer;
{ }
Padstack().Drill().start = layer; } );
first = false;
}
Padstack().Drill().end = layer;
}
} }
@ -995,10 +996,15 @@ void PCB_VIA::SanitizeLayers()
bool PCB_VIA::FlashLayer( LSET aLayers ) const bool PCB_VIA::FlashLayer( LSET aLayers ) const
{ {
for( PCB_LAYER_ID layer : aLayers.Seq() ) for( size_t ii = 0; ii < aLayers.size(); ++ii )
{ {
if( FlashLayer( layer ) ) if( aLayers.test( ii ) )
return true; {
PCB_LAYER_ID layer = PCB_LAYER_ID( ii );
if( FlashLayer( layer ) )
return true;
}
} }
return false; return false;
@ -1116,18 +1122,16 @@ double PCB_TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
return HIDE; return HIDE;
} }
// Pick the approximate size of the netname (square chars)
wxString netName = GetDisplayNetname();
size_t num_chars = netName.size();
if( GetLength() < num_chars * GetWidth() )
return HIDE;
// When drawing netnames, clip the track to the viewport
VECTOR2I start( GetStart() ); VECTOR2I start( GetStart() );
VECTOR2I end( GetEnd() ); VECTOR2I end( GetEnd() );
BOX2D viewport = aView->GetViewport();
BOX2I clipBox = BOX2ISafe( viewport ); // Calc the approximate size of the netname (assume square chars)
SEG::ecoord nameSize = GetDisplayNetname().size() * GetWidth();
if( VECTOR2I( end - start ).SquaredEuclideanNorm() < nameSize * nameSize )
return HIDE;
BOX2I clipBox = BOX2ISafe( aView->GetViewport() );
ClipLine( &clipBox, start.x, start.y, end.x, end.y ); ClipLine( &clipBox, start.x, start.y, end.x, end.y );

View File

@ -528,12 +528,17 @@ bool collidesWithArea( BOARD_ITEM* aItem, PCBEXPR_CONTEXT* aCtx, ZONE* aArea )
if( zoneRTree ) if( zoneRTree )
{ {
for( PCB_LAYER_ID layer : aArea->GetLayerSet().Seq() ) for( size_t ii = 0; ii < aArea->GetLayerSet().size(); ++ii )
{ {
if( aCtx->GetLayer() == layer || aCtx->GetLayer() == UNDEFINED_LAYER ) if( aArea->GetLayerSet().test( ii ) )
{ {
if( zoneRTree->QueryColliding( areaBBox, &areaOutline, layer ) ) PCB_LAYER_ID layer = PCB_LAYER_ID( ii );
return true;
if( aCtx->GetLayer() == layer || aCtx->GetLayer() == UNDEFINED_LAYER )
{
if( zoneRTree->QueryColliding( areaBBox, &areaOutline, layer ) )
return true;
}
} }
} }
} }

View File

@ -102,11 +102,12 @@ void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
} }
else else
{ {
for( PCB_LAYER_ID layer : LSET::AllCuMask().Seq() ) LSET::AllCuMask().RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
if( aView->IsLayerVisible( layer ) ) {
visibleLayers.set( layer ); if( aView->IsLayerVisible( layer ) )
} visibleLayers.set( layer );
} );
} }
auto adjustColor = auto adjustColor =

View File

@ -246,8 +246,11 @@ int ZONE_FILLER_TOOL::ZoneFillDirty( const TOOL_EVENT& aEvent )
for( ZONE* zone : toFill ) for( ZONE* zone : toFill )
{ {
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() ) zone->GetLayerSet().RunOnLayers(
pts += zone->GetFilledPolysList( layer )->FullPointCount(); [&]( PCB_LAYER_ID layer )
{
pts += zone->GetFilledPolysList( layer )->FullPointCount();
} );
if( pts > 1000 ) if( pts > 1000 )
{ {

View File

@ -150,18 +150,19 @@ void ZONE::InitDataFromSrcInCopyCtor( const ZONE& aZone )
delete m_CornerSelection; delete m_CornerSelection;
m_CornerSelection = nullptr; m_CornerSelection = nullptr;
for( PCB_LAYER_ID layer : aZone.GetLayerSet().Seq() ) aZone.GetLayerSet().RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
std::shared_ptr<SHAPE_POLY_SET> fill = aZone.m_FilledPolysList.at( layer ); {
std::shared_ptr<SHAPE_POLY_SET> fill = aZone.m_FilledPolysList.at( layer );
if( fill ) if( fill )
m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>( *fill ); m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>( *fill );
else else
m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>(); m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
m_filledPolysHash[layer] = aZone.m_filledPolysHash.at( layer ); m_filledPolysHash[layer] = aZone.m_filledPolysHash.at( layer );
m_insulatedIslands[layer] = aZone.m_insulatedIslands.at( layer ); m_insulatedIslands[layer] = aZone.m_insulatedIslands.at( layer );
} } );
m_borderStyle = aZone.m_borderStyle; m_borderStyle = aZone.m_borderStyle;
m_borderHatchPitch = aZone.m_borderHatchPitch; m_borderHatchPitch = aZone.m_borderHatchPitch;
@ -279,12 +280,13 @@ void ZONE::SetLayerSet( LSET aLayerSet )
m_filledPolysHash.clear(); m_filledPolysHash.clear();
m_insulatedIslands.clear(); m_insulatedIslands.clear();
for( PCB_LAYER_ID layer : aLayerSet.Seq() ) aLayerSet.RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>(); {
m_filledPolysHash[layer] = {}; m_FilledPolysList[layer] = std::make_shared<SHAPE_POLY_SET>();
m_insulatedIslands[layer] = {}; m_filledPolysHash[layer] = {};
} m_insulatedIslands[layer] = {};
} );
} }
m_layerSet = aLayerSet; m_layerSet = aLayerSet;
@ -294,13 +296,13 @@ void ZONE::SetLayerSet( LSET aLayerSet )
void ZONE::ViewGetLayers( int aLayers[], int& aCount ) const void ZONE::ViewGetLayers( int aLayers[], int& aCount ) const
{ {
aCount = 0; aCount = 0;
LSEQ layers = m_layerSet.Seq();
for( PCB_LAYER_ID layer : m_layerSet.Seq() ) m_layerSet.RunOnLayers(
{ [&]( PCB_LAYER_ID layer )
aLayers[ aCount++ ] = layer; // For outline (always full opacity) {
aLayers[ aCount++ ] = layer + static_cast<int>( LAYER_ZONE_START ); // For fill (obeys global zone opacity) aLayers[ aCount++ ] = layer;
} aLayers[ aCount++ ] = layer + static_cast<int>( LAYER_ZONE_START );
} );
if( IsConflicting() ) if( IsConflicting() )
aLayers[ aCount++ ] = LAYER_CONFLICTS_SHADOW; aLayers[ aCount++ ] = LAYER_CONFLICTS_SHADOW;