Connectivity optimizations

Cache names of potential driving items
Change a few data structures based on profiling
This commit is contained in:
Jon Evans 2020-07-09 18:14:27 -04:00
parent fc92fb076e
commit 66bdd37637
2 changed files with 61 additions and 75 deletions

View File

@ -43,6 +43,13 @@
#include <advanced_config.h> // for realtime connectivity switch #include <advanced_config.h> // for realtime connectivity switch
/*
* Flag to enable connectivity profiling
* @ingroup trace_env_vars
*/
static const wxChar ConnProfileMask[] = wxT( "CONN_PROFILE" );
bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers ) bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
{ {
PRIORITY highest_priority = PRIORITY::INVALID; PRIORITY highest_priority = PRIORITY::INVALID;
@ -227,16 +234,17 @@ std::vector<SCH_ITEM*> CONNECTION_SUBGRAPH::GetBusLabels() const
} }
wxString CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem ) const const wxString& CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem )
{ {
wxString name; if( m_driver_name_cache.count( aItem ) )
return m_driver_name_cache.at( aItem );
switch( aItem->Type() ) switch( aItem->Type() )
{ {
case SCH_PIN_T: case SCH_PIN_T:
{ {
SCH_PIN* pin = static_cast<SCH_PIN*>( aItem ); SCH_PIN* pin = static_cast<SCH_PIN*>( aItem );
name = pin->GetDefaultNetName( m_sheet ); m_driver_name_cache[aItem] = pin->GetDefaultNetName( m_sheet );
break; break;
} }
@ -245,15 +253,17 @@ wxString CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem ) const
case SCH_HIER_LABEL_T: case SCH_HIER_LABEL_T:
case SCH_SHEET_PIN_T: case SCH_SHEET_PIN_T:
{ {
name = EscapeString( static_cast<SCH_TEXT*>( aItem )->GetShownText(), CTX_NETNAME ); m_driver_name_cache[aItem] = EscapeString( static_cast<SCH_TEXT*>( aItem )->GetShownText(),
CTX_NETNAME );
break; break;
} }
default: default:
wxFAIL_MSG( "Unhandled item type in GetNameForDriver" );
break; break;
} }
return name; return m_driver_name_cache.at( aItem );
} }
@ -376,40 +386,45 @@ void CONNECTION_GRAPH::Reset()
void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnconditional ) void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnconditional )
{ {
PROF_COUNTER recalc_time; PROF_COUNTER recalc_time( "CONNECTION_GRAPH::Recalculate" );
PROF_COUNTER update_items;
if( aUnconditional ) if( aUnconditional )
Reset(); Reset();
PROF_COUNTER update_items( "updateItemConnectivity" );
for( const SCH_SHEET_PATH& sheet : aSheetList ) for( const SCH_SHEET_PATH& sheet : aSheetList )
{ {
std::vector<SCH_ITEM*> items; std::vector<SCH_ITEM*> items;
for( auto item : sheet.LastScreen()->Items() ) for( SCH_ITEM* item : sheet.LastScreen()->Items() )
{ {
if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) ) if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
items.push_back( item ); items.push_back( item );
} }
m_items.reserve( m_items.size() + items.size() );
updateItemConnectivity( sheet, items ); updateItemConnectivity( sheet, items );
// UpdateDanglingState() also adds connected items for SCH_TEXT // UpdateDanglingState() also adds connected items for SCH_TEXT
sheet.LastScreen()->TestDanglingEnds( &sheet ); sheet.LastScreen()->TestDanglingEnds( &sheet );
} }
update_items.Stop(); if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
wxLogTrace( "CONN_PROFILE", "UpdateItemConnectivity() %0.4f ms", update_items.msecs() ); update_items.Show();
PROF_COUNTER build_graph; PROF_COUNTER build_graph( "buildConnectionGraph" );
buildConnectionGraph(); buildConnectionGraph();
build_graph.Stop(); if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
wxLogTrace( "CONN_PROFILE", "BuildConnectionGraph() %0.4f ms", build_graph.msecs() ); build_graph.Show();
recalc_time.Stop(); recalc_time.Stop();
wxLogTrace( "CONN_PROFILE", "Recalculate time %0.4f ms", recalc_time.msecs() );
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
recalc_time.Show();
#ifndef DEBUG #ifndef DEBUG
// Pressure relief valve for release builds // Pressure relief valve for release builds
@ -427,7 +442,7 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet, void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
const std::vector<SCH_ITEM*>& aItemList ) const std::vector<SCH_ITEM*>& aItemList )
{ {
std::unordered_map< wxPoint, std::vector<SCH_ITEM*> > connection_map; std::map< wxPoint, std::vector<SCH_ITEM*> > connection_map;
for( SCH_ITEM* item : aItemList ) for( SCH_ITEM* item : aItemList )
{ {
@ -446,7 +461,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
pin->Connection( aSheet )->Reset(); pin->Connection( aSheet )->Reset();
connection_map[ pin->GetTextPos() ].push_back( pin ); connection_map[ pin->GetTextPos() ].push_back( pin );
m_items.insert( pin ); m_items.emplace_back( pin );
} }
} }
else if( item->Type() == SCH_COMPONENT_T ) else if( item->Type() == SCH_COMPONENT_T )
@ -476,12 +491,12 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
m_invisible_power_pins.emplace_back( std::make_pair( aSheet, pin ) ); m_invisible_power_pins.emplace_back( std::make_pair( aSheet, pin ) );
connection_map[ pos ].push_back( pin ); connection_map[ pos ].push_back( pin );
m_items.insert( pin ); m_items.emplace_back( pin );
} }
} }
else else
{ {
m_items.insert( item ); m_items.emplace_back( item );
auto conn = item->InitializeConnection( aSheet, this ); auto conn = item->InitializeConnection( aSheet, this );
// Set bus/net property here so that the propagation code uses it // Set bus/net property here so that the propagation code uses it
@ -803,37 +818,7 @@ void CONNECTION_GRAPH::buildConnectionGraph()
SCH_SHEET_PATH sheet = subgraph->m_sheet; SCH_SHEET_PATH sheet = subgraph->m_sheet;
SCH_CONNECTION* connection = driver->Connection( sheet ); SCH_CONNECTION* connection = driver->Connection( sheet );
// TODO(JE) This should live in SCH_CONNECTION probably connection->ConfigureFromLabel( subgraph->GetNameForDriver( driver ) );
switch( driver->Type() )
{
case SCH_LABEL_T:
case SCH_GLOBAL_LABEL_T:
case SCH_HIER_LABEL_T:
{
auto text = static_cast<SCH_TEXT*>( driver );
connection->ConfigureFromLabel( EscapeString( text->GetShownText(), CTX_NETNAME ) );
break;
}
case SCH_SHEET_PIN_T:
{
auto pin = static_cast<SCH_SHEET_PIN*>( driver );
connection->ConfigureFromLabel( EscapeString( pin->GetShownText(), CTX_NETNAME ) );
break;
}
case SCH_PIN_T:
{
auto pin = static_cast<SCH_PIN*>( driver );
// NOTE(JE) GetDefaultNetName is not thread-safe.
connection->ConfigureFromLabel( pin->GetDefaultNetName( sheet ) );
break;
}
default:
wxLogTrace( "CONN", "Driver type unsupported: %s",
driver->GetSelectMenuText( EDA_UNITS::MILLIMETRES ) );
break;
}
connection->SetDriver( driver ); connection->SetDriver( driver );
connection->ClearDirty(); connection->ClearDirty();
@ -1139,7 +1124,7 @@ void CONNECTION_GRAPH::buildConnectionGraph()
if( possible_driver == aSubgraph->m_driver ) if( possible_driver == aSubgraph->m_driver )
continue; continue;
auto c = getDefaultConnection( possible_driver, aSubgraph->m_sheet ); auto c = getDefaultConnection( possible_driver, aSubgraph );
if( c ) if( c )
{ {
@ -1215,9 +1200,7 @@ void CONNECTION_GRAPH::buildConnectionGraph()
driver->Type() == SCH_GLOBAL_LABEL_T || driver->Type() == SCH_GLOBAL_LABEL_T ||
driver->Type() == SCH_HIER_LABEL_T ); driver->Type() == SCH_HIER_LABEL_T );
auto text = static_cast<SCH_TEXT*>( driver ); if( subgraph->GetNameForDriver( driver ) == test_name )
if( EscapeString( text->GetShownText(), CTX_NETNAME ) == test_name )
{ {
match = true; match = true;
break; break;
@ -1551,7 +1534,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
if( !m_sheet_to_subgraphs_map.count( path ) ) if( !m_sheet_to_subgraphs_map.count( path ) )
continue; continue;
for( auto candidate : m_sheet_to_subgraphs_map.at( path ) ) for( CONNECTION_SUBGRAPH* candidate : m_sheet_to_subgraphs_map.at( path ) )
{ {
if( !candidate->m_strong_driver || if( !candidate->m_strong_driver ||
candidate->m_hier_ports.empty() || candidate->m_hier_ports.empty() ||
@ -1560,7 +1543,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
for( SCH_HIERLABEL* label : candidate->m_hier_ports ) for( SCH_HIERLABEL* label : candidate->m_hier_ports )
{ {
if( label->GetShownText() == pin->GetShownText() ) if( candidate->GetNameForDriver( label ) == aParent->GetNameForDriver( pin ) )
{ {
wxLogTrace( "CONN", "%lu: found child %lu (%s)", aParent->m_code, wxLogTrace( "CONN", "%lu: found child %lu (%s)", aParent->m_code,
candidate->m_code, candidate->m_driver_connection->Name() ); candidate->m_code, candidate->m_driver_connection->Name() );
@ -1582,7 +1565,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
if( !m_sheet_to_subgraphs_map.count( path ) ) if( !m_sheet_to_subgraphs_map.count( path ) )
continue; continue;
for( auto candidate : m_sheet_to_subgraphs_map.at( path ) ) for( CONNECTION_SUBGRAPH* candidate : m_sheet_to_subgraphs_map.at( path ) )
{ {
if( candidate->m_hier_pins.empty() || if( candidate->m_hier_pins.empty() ||
visited.count( candidate ) || visited.count( candidate ) ||
@ -1598,7 +1581,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
if( pin_path != aParent->m_sheet ) if( pin_path != aParent->m_sheet )
continue; continue;
if( label->GetShownText() == pin->GetShownText() ) if( aParent->GetNameForDriver( label ) == candidate->GetNameForDriver( pin ) )
{ {
wxLogTrace( "CONN", "%lu: found additional parent %lu (%s)", wxLogTrace( "CONN", "%lu: found additional parent %lu (%s)",
aParent->m_code, candidate->m_code, aParent->m_code, candidate->m_code,
@ -1639,7 +1622,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
for( SCH_ITEM* driver : sg->m_drivers ) for( SCH_ITEM* driver : sg->m_drivers )
{ {
auto c = getDefaultConnection( driver, sheet ); auto c = getDefaultConnection( driver, sg );
member = matchBusMember( parent, c.get() ); member = matchBusMember( parent, c.get() );
if( member ) if( member )
@ -1807,8 +1790,8 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
} }
std::shared_ptr<SCH_CONNECTION> std::shared_ptr<SCH_CONNECTION> CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem,
CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem, const SCH_SHEET_PATH& aSheet ) CONNECTION_SUBGRAPH* aSubgraph )
{ {
auto c = std::shared_ptr<SCH_CONNECTION>( nullptr ); auto c = std::shared_ptr<SCH_CONNECTION>( nullptr );
@ -1819,11 +1802,8 @@ CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem, const SCH_SHEET_PATH& a
auto pin = static_cast<SCH_PIN*>( aItem ); auto pin = static_cast<SCH_PIN*>( aItem );
if( pin->IsPowerConnection() ) if( pin->IsPowerConnection() )
{ c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->m_sheet );
c = std::make_shared<SCH_CONNECTION>( aItem, aSheet );
c->SetGraph( this );
c->ConfigureFromLabel( pin->GetName() );
}
break; break;
} }
@ -1831,11 +1811,7 @@ CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem, const SCH_SHEET_PATH& a
case SCH_HIER_LABEL_T: case SCH_HIER_LABEL_T:
case SCH_LABEL_T: case SCH_LABEL_T:
{ {
auto text = static_cast<SCH_TEXT*>( aItem ); c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->m_sheet );
c = std::make_shared<SCH_CONNECTION>( aItem, aSheet );
c->SetGraph( this );
c->ConfigureFromLabel( EscapeString( text->GetShownText(), CTX_NETNAME ) );
break; break;
} }
@ -1843,6 +1819,12 @@ CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem, const SCH_SHEET_PATH& a
break; break;
} }
if( c )
{
c->SetGraph( this );
c->ConfigureFromLabel( aSubgraph->GetNameForDriver( aItem ) );
}
return c; return c;
} }
@ -1899,8 +1881,8 @@ SCH_CONNECTION* CONNECTION_GRAPH::matchBusMember( SCH_CONNECTION* aBusConnection
} }
void CONNECTION_GRAPH::recacheSubgraphName( void CONNECTION_GRAPH::recacheSubgraphName( CONNECTION_SUBGRAPH* aSubgraph,
CONNECTION_SUBGRAPH* aSubgraph, const wxString& aOldName ) const wxString& aOldName )
{ {
if( m_net_name_to_subgraphs_map.count( aOldName ) ) if( m_net_name_to_subgraphs_map.count( aOldName ) )
{ {

View File

@ -110,7 +110,7 @@ public:
std::vector<SCH_ITEM*> GetBusLabels() const; std::vector<SCH_ITEM*> GetBusLabels() const;
/// Returns the candidate net name for a driver /// Returns the candidate net name for a driver
wxString GetNameForDriver( SCH_ITEM* aItem ) const; const wxString& GetNameForDriver( SCH_ITEM* aItem );
/// Combines another subgraph on the same sheet into this one. /// Combines another subgraph on the same sheet into this one.
void Absorb( CONNECTION_SUBGRAPH* aOther ); void Absorb( CONNECTION_SUBGRAPH* aOther );
@ -206,6 +206,9 @@ public:
// If not null, this indicates the subgraph on a higher level sheet that is linked to this one // If not null, this indicates the subgraph on a higher level sheet that is linked to this one
CONNECTION_SUBGRAPH* m_hier_parent; CONNECTION_SUBGRAPH* m_hier_parent;
/// A cache of escaped netnames from schematic items
std::unordered_map<SCH_ITEM*, wxString> m_driver_name_cache;
}; };
/// Associates a net code with the final name of a net /// Associates a net code with the final name of a net
@ -299,7 +302,7 @@ public:
private: private:
std::unordered_set<SCH_ITEM*> m_items; std::vector<SCH_ITEM*> m_items;
// The owner of all CONNECTION_SUBGRAPH objects // The owner of all CONNECTION_SUBGRAPH objects
std::vector<CONNECTION_SUBGRAPH*> m_subgraphs; std::vector<CONNECTION_SUBGRAPH*> m_subgraphs;
@ -423,10 +426,11 @@ private:
* Handles strong drivers (power pins and labels) only * Handles strong drivers (power pins and labels) only
* *
* @param aItem is an item that can generate a connection name * @param aItem is an item that can generate a connection name
* @param aSubgraph is used to determine the sheet to use and retrieve the cached name
* @return a connection generated from the item, or nullptr if item is not valid * @return a connection generated from the item, or nullptr if item is not valid
*/ */
std::shared_ptr<SCH_CONNECTION> getDefaultConnection( SCH_ITEM* aItem, std::shared_ptr<SCH_CONNECTION> getDefaultConnection( SCH_ITEM* aItem,
const SCH_SHEET_PATH& aSheet ); CONNECTION_SUBGRAPH* aSubgraph );
void recacheSubgraphName( CONNECTION_SUBGRAPH* aSubgraph, const wxString& aOldName ); void recacheSubgraphName( CONNECTION_SUBGRAPH* aSubgraph, const wxString& aOldName );