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->BottomLayer() );
for( PCB_LAYER_ID layer : via->GetLayerSet().Seq() )
hash_combine( ret, via->FlashLayer( layer ) );
via->GetLayerSet().RunOnLayers(
[&]( PCB_LAYER_ID layer )
{
hash_combine( ret, via->FlashLayer( layer ) );
} );
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->GetDrillShape() );
for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() )
hash_combine( ret, pad->FlashLayer( layer ) );
pad->GetLayerSet().RunOnLayers(
[&]( PCB_LAYER_ID layer )
{
hash_combine( ret, pad->FlashLayer( layer ) );
} );
}
hash_combine( ret, pad->GetSize().x, pad->GetSize().y );

View File

@ -815,6 +815,18 @@ public:
*/
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.
*/

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 )
return wxString();
return emptyString;
if( const BOARD* board = GetBoard() )
{

View File

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

View File

@ -111,11 +111,11 @@ bool DRC_CACHE_GENERATOR::Run()
copperLayers = boardCopperLayers;
}
for( PCB_LAYER_ID layer : copperLayers.Seq() )
{
if( IsCopperLayer( layer ) )
m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance );
}
copperLayers.RunOnLayers(
[&]( PCB_LAYER_ID layer )
{
m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance );
} );
done.fetch_add( 1 );
return true;
@ -179,11 +179,12 @@ bool DRC_CACHE_GENERATOR::Run()
{
std::unique_ptr<DRC_RTREE> rtree = std::make_unique<DRC_RTREE>();
for( PCB_LAYER_ID layer : aZone->GetLayerSet().Seq() )
{
if( IsCopperLayer( layer ) )
rtree->Insert( aZone, layer );
}
aZone->GetLayerSet().RunOnLayers(
[&]( PCB_LAYER_ID layer )
{
if( IsCopperLayer( layer ) )
rtree->Insert( aZone, layer );
} );
{
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() )
{
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
m_board->m_ZoneIsolatedIslandsMap[ zone ][ layer ] = ISOLATED_ISLANDS();
zone->GetLayerSet().RunOnLayers(
[&]( 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 )
{
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;
break;
}
PCB_LAYER_ID layer = PCB_LAYER_ID( ii );
if( m_drcEngine->IsCancelled() )
return 0;
if( zoneRTree->QueryColliding( areaBBox, &areaPoly, layer ) )
{
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 );
DRC_RULE* rule = constraint.GetParentRule();
VECTOR2I pos = item->GetPosition();
PCB_LAYER_ID layer = UNDEFINED_LAYER;
PCB_LAYER_ID layer = item->GetLayerSet().ExtractLayer();
wxString msg;
msg.Printf( drcItem->GetErrorText() + wxS( " (%s)" ), constraint.GetName() );
@ -226,9 +231,6 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
drcItem->SetItems( item );
drcItem->SetViolatingRule( rule );
if( item->GetLayerSet().count() )
layer = item->GetLayerSet().Seq().front();
if( rule->m_Implicit )
{
// 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
// 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 ) )
return false;

View File

@ -908,20 +908,21 @@ void PCB_VIA::SetLayerSet( LSET aLayerSet )
{
bool first = true;
for( PCB_LAYER_ID layer : aLayerSet.Seq() )
{
// m_layer and m_bottomLayer are copper layers, so consider only copper layers in aLayerSet
if( !IsCopperLayer( layer ) )
continue;
aLayerSet.RunOnLayers(
[&]( PCB_LAYER_ID layer )
{
// m_layer and m_bottomLayer are copper layers, so consider only copper layers
if( IsCopperLayer( layer ) )
{
if( first )
{
Padstack().Drill().start = layer;
first = false;
}
if( first )
{
Padstack().Drill().start = layer;
first = false;
}
Padstack().Drill().end = layer;
}
Padstack().Drill().end = layer;
}
} );
}
@ -995,10 +996,15 @@ void PCB_VIA::SanitizeLayers()
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 ) )
return true;
if( aLayers.test( ii ) )
{
PCB_LAYER_ID layer = PCB_LAYER_ID( ii );
if( FlashLayer( layer ) )
return true;
}
}
return false;
@ -1116,18 +1122,16 @@ double PCB_TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
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 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 );

View File

@ -528,12 +528,17 @@ bool collidesWithArea( BOARD_ITEM* aItem, PCBEXPR_CONTEXT* aCtx, ZONE* aArea )
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 ) )
return true;
PCB_LAYER_ID layer = PCB_LAYER_ID( ii );
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
{
for( PCB_LAYER_ID layer : LSET::AllCuMask().Seq() )
{
if( aView->IsLayerVisible( layer ) )
visibleLayers.set( layer );
}
LSET::AllCuMask().RunOnLayers(
[&]( PCB_LAYER_ID layer )
{
if( aView->IsLayerVisible( layer ) )
visibleLayers.set( layer );
} );
}
auto adjustColor =

View File

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

View File

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