From ae7e3f725b3b9a4f48acf0650794ac247c7bf43b Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Thu, 9 Mar 2017 18:13:03 +0100 Subject: [PATCH] Speed up project rescue calculations, by optimizing the number of searches in libs. --- eeschema/project_rescue.cpp | 59 +++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/eeschema/project_rescue.cpp b/eeschema/project_rescue.cpp index 6ff55ba08f..22fa0d437f 100644 --- a/eeschema/project_rescue.cpp +++ b/eeschema/project_rescue.cpp @@ -145,22 +145,36 @@ static bool insert_library( PROJECT *aProject, PART_LIB *aLibrary, size_t aIndex /** * Function get_components * Fills a vector with all of the project's components, to ease iterating over them. + * The list is sorted by lib id, therefore components using the same library + * symbol are grouped, allowing later faster calculations (one library search by group + * of symbols) * * @param aComponents - a vector that will take the components */ +// Helper sort function, used in get_components, to sort a component list by lib_id +static bool sort_by_libid( const SCH_COMPONENT* ref, SCH_COMPONENT* cmp ) +{ + return ref->GetLibId() < cmp->GetLibId(); +} + static void get_components( std::vector& aComponents ) { SCH_SCREENS screens; + + // Get the full list for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) { for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() ) { if( item->Type() != SCH_COMPONENT_T ) continue; - SCH_COMPONENT* component = dynamic_cast( item ); + SCH_COMPONENT* component = static_cast( item ); aComponents.push_back( component ); } } + + // sort aComponents by lib part. Components will be grouped by same lib part. + std::sort( aComponents.begin(), aComponents.end(), sort_by_libid ); } @@ -241,13 +255,29 @@ public: typedef std::map candidate_map_t; candidate_map_t candidate_map; + // Remember the list of components is sorted by part name. + // So a search in libraries is made only once by group + LIB_ALIAS* case_sensitive_match = nullptr; + std::vector case_insensitive_matches; + + wxString last_part_name; + for( SCH_COMPONENT* each_component : *( aRescuer.GetComponents() ) ) { wxString part_name( each_component->GetLibId().GetLibItemName() ); - LIB_ID id( wxEmptyString, part_name ); - LIB_ALIAS* case_sensitive_match = aRescuer.GetLibs()->FindLibraryAlias( id ); - std::vector case_insensitive_matches; - aRescuer.GetLibs()->FindLibraryNearEntries( case_insensitive_matches, part_name ); + + if( last_part_name != part_name ) + { + // A new part name is found (a new group starts here). + // Search the symbol names candidates only once for this group: + last_part_name = part_name; + case_insensitive_matches.clear(); + + LIB_ID id( wxEmptyString, part_name ); + + case_sensitive_match = aRescuer.GetLibs()->FindLibraryAlias( id ); + aRescuer.GetLibs()->FindLibraryNearEntries( case_insensitive_matches, part_name ); + } if( case_sensitive_match || !( case_insensitive_matches.size() ) ) continue; @@ -329,16 +359,27 @@ public: typedef std::map candidate_map_t; candidate_map_t candidate_map; + // Remember the list of components is sorted by part name. + // So a search in libraries is made only once by group + LIB_PART* cache_match = nullptr; + LIB_PART* lib_match = nullptr; + wxString old_part_name; + wxString part_name_suffix = aRescuer.GetPartNameSuffix(); for( SCH_COMPONENT* each_component : *( aRescuer.GetComponents() ) ) { wxString part_name( each_component->GetLibId().GetLibItemName() ); - LIB_PART* cache_match = find_component( part_name, - aRescuer.GetLibs(), /* aCached */ true ); - LIB_ID id( wxEmptyString, part_name ); - LIB_PART* lib_match = aRescuer.GetLibs()->FindLibPart( id ); + if( old_part_name != part_name ) + { + // A new part name is found (a new group starts here). + // Search the symbol names candidates only once for this group: + old_part_name = part_name; + cache_match = find_component( part_name, aRescuer.GetLibs(), /* aCached */ true ); + LIB_ID id( wxEmptyString, part_name ); + lib_match = aRescuer.GetLibs()->FindLibPart( id ); + } // Test whether there is a conflict if( !cache_match || !lib_match )