Fix routing perf regression from clearance cache

The clearance cache added in b0d0dd57ef invalidates on every
SetLayer() and SetNetCode() call. The router's rule resolver
calls SetLayer() on dummy board items for every clearance
evaluation during routing. Each call acquires an exclusive
lock and linearly scans the entire cache, but dummy items
never exist in the cache, so this is pure waste.

Skip cache invalidation for items flagged ROUTER_TRANSIENT.
The flag is already set on all dummy items in the rule
resolver.

Also replace the O(n) linear scan in InvalidateClearanceCache
with targeted O(1) hash erasure per copper layer.
This commit is contained in:
Seth Hillbrand
2026-02-20 15:05:37 -08:00
parent 5c4b646405
commit 80bfe4472c
4 changed files with 49 additions and 28 deletions
+7 -5
View File
@@ -53,9 +53,11 @@ void BOARD_CONNECTED_ITEM::SetLayer( PCB_LAYER_ID aLayer )
{
BOARD_ITEM::SetLayer( aLayer );
// Invalidate clearance cache since layer can affect clearance rules
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
if( !( GetFlags() & ROUTER_TRANSIENT ) )
{
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
}
}
@@ -103,10 +105,10 @@ bool BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode, bool aNoAssert )
if( !aNoAssert )
wxASSERT( m_netinfo );
// Invalidate clearance cache since net can affect clearance rules
if( board )
{
board->InvalidateClearanceCache( m_Uuid );
if( !( GetFlags() & ROUTER_TRANSIENT ) )
board->InvalidateClearanceCache( m_Uuid );
std::unique_lock<std::shared_mutex> writeLock( board->m_CachesMutex );
board->m_ItemNetclassCache.erase( this );
+17 -8
View File
@@ -2553,15 +2553,24 @@ void DRC_ENGINE::InvalidateClearanceCache( const KIID& aUuid )
{
std::unique_lock<std::shared_mutex> writeLock( m_clearanceCacheMutex );
// Remove all entries for this item (across all layers)
auto it = m_ownClearanceCache.begin();
while( it != m_ownClearanceCache.end() )
if( m_board )
{
if( it->first.m_uuid == aUuid )
it = m_ownClearanceCache.erase( it );
else
++it;
LSET copperLayers = m_board->GetEnabledLayers() & LSET::AllCuMask();
for( PCB_LAYER_ID layer : copperLayers.Seq() )
m_ownClearanceCache.erase( DRC_OWN_CLEARANCE_CACHE_KEY{ aUuid, layer } );
}
else
{
auto it = m_ownClearanceCache.begin();
while( it != m_ownClearanceCache.end() )
{
if( it->first.m_uuid == aUuid )
it = m_ownClearanceCache.erase( it );
else
++it;
}
}
}
+10 -6
View File
@@ -1388,9 +1388,11 @@ void PAD::SetAttribute( PAD_ATTRIB aAttribute )
break;
}
// Invalidate clearance cache since pad type affects constraint evaluation
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
if( !( GetFlags() & ROUTER_TRANSIENT ) )
{
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
}
}
SetDirty();
@@ -1619,9 +1621,11 @@ void PAD::SetLayerSet( const LSET& aLayers )
m_padStack.SetLayerSet( aLayers );
SetDirty();
// Invalidate clearance cache since layer set can affect clearance rules
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
if( !( GetFlags() & ROUTER_TRANSIENT ) )
{
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
}
}
+15 -9
View File
@@ -1643,9 +1643,11 @@ void PCB_VIA::SetLayerPair( PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer )
Padstack().Drill().end = aBottomLayer;
SanitizeLayers();
// Invalidate clearance cache since layer can affect clearance rules
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
if( !( GetFlags() & ROUTER_TRANSIENT ) )
{
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
}
}
@@ -1658,9 +1660,11 @@ void PCB_VIA::SetTopLayer( PCB_LAYER_ID aLayer )
Padstack().Drill().start = aLayer;
SanitizeLayers();
// Invalidate clearance cache since layer can affect clearance rules
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
if( !( GetFlags() & ROUTER_TRANSIENT ) )
{
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
}
}
@@ -1673,9 +1677,11 @@ void PCB_VIA::SetBottomLayer( PCB_LAYER_ID aLayer )
Padstack().Drill().end = aLayer;
SanitizeLayers();
// Invalidate clearance cache since layer can affect clearance rules
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
if( !( GetFlags() & ROUTER_TRANSIENT ) )
{
if( BOARD* board = GetBoard() )
board->InvalidateClearanceCache( m_Uuid );
}
}