Add cache to SCH_IO_DATABASE to improve loading performance

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17031

(cherry picked from commit 991ddfe6be)
This commit is contained in:
Roberto Fernandez Bautista 2024-02-19 00:34:55 +01:00
parent a928299ae0
commit 9004f92689
2 changed files with 64 additions and 28 deletions

View File

@ -20,6 +20,7 @@
#include <iostream> #include <iostream>
#include <unordered_set> #include <unordered_set>
#include <wx/datetime.h>
#include <wx/log.h> #include <wx/log.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -38,6 +39,8 @@ SCH_IO_DATABASE::SCH_IO_DATABASE() : SCH_IO( wxS( "Database library" ) ),
m_settings(), m_settings(),
m_conn() m_conn()
{ {
m_cacheTimestamp = 0;
m_cacheModifyHash = 0;
} }
@ -65,6 +68,7 @@ void SCH_IO_DATABASE::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
wxCHECK_RET( m_libTable, "Database plugin missing library table handle!" ); wxCHECK_RET( m_libTable, "Database plugin missing library table handle!" );
ensureSettings( aLibraryPath ); ensureSettings( aLibraryPath );
ensureConnection(); ensureConnection();
cacheLib();
if( !m_conn ) if( !m_conn )
THROW_IO_ERROR( m_lastError ); THROW_IO_ERROR( m_lastError );
@ -73,36 +77,12 @@ void SCH_IO_DATABASE::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) !=
aProperties->end() ); aProperties->end() );
for( const DATABASE_LIB_TABLE& table : m_settings->m_Tables ) for( auto const& pair : m_nameToSymbolcache )
{ {
std::vector<DATABASE_CONNECTION::ROW> results; LIB_SYMBOL* symbol = pair.second;
if( !m_conn->SelectAll( table.table, table.key_col, results ) ) if( !powerSymbolsOnly || symbol->IsPower() )
{ aSymbolList.emplace_back( symbol );
if( !m_conn->GetLastError().empty() )
{
wxString msg = wxString::Format( _( "Error reading database table %s: %s" ),
table.table, m_conn->GetLastError() );
THROW_IO_ERROR( msg );
}
continue;
}
for( DATABASE_CONNECTION::ROW& result : results )
{
if( !result.count( table.key_col ) )
continue;
std::string prefix = table.name.empty() ? "" : fmt::format( "{}/", table.name );
wxString name( fmt::format( "{}{}", prefix,
std::any_cast<std::string>( result[table.key_col] ) ) );
LIB_SYMBOL* symbol = loadSymbolFromRow( name, table, result );
if( symbol && ( !powerSymbolsOnly || symbol->IsPower() ) )
aSymbolList.emplace_back( symbol );
}
} }
} }
@ -221,6 +201,52 @@ bool SCH_IO_DATABASE::TestConnection( wxString* aErrorMsg )
} }
void SCH_IO_DATABASE::cacheLib()
{
long long currentTimestampSeconds = wxDateTime::Now().GetValue().GetValue() / 1000;
if( m_libTable->GetModifyHash() == m_cacheModifyHash
&& ( currentTimestampSeconds - m_cacheTimestamp ) < m_settings->m_Cache.max_age )
{
return;
}
for( const DATABASE_LIB_TABLE& table : m_settings->m_Tables )
{
std::vector<DATABASE_CONNECTION::ROW> results;
if( !m_conn->SelectAll( table.table, table.key_col, results ) )
{
if( !m_conn->GetLastError().empty() )
{
wxString msg = wxString::Format( _( "Error reading database table %s: %s" ),
table.table, m_conn->GetLastError() );
THROW_IO_ERROR( msg );
}
continue;
}
for( DATABASE_CONNECTION::ROW& result : results )
{
if( !result.count( table.key_col ) )
continue;
std::string prefix = table.name.empty() ? "" : fmt::format( "{}/", table.name );
wxString name( fmt::format( "{}{}", prefix,
std::any_cast<std::string>( result[table.key_col] ) ) );
LIB_SYMBOL* symbol = loadSymbolFromRow( name, table, result );
if( symbol )
m_nameToSymbolcache.insert( { symbol->GetName(), symbol } );
}
}
m_cacheTimestamp = currentTimestampSeconds;
m_cacheModifyHash = m_libTable->GetModifyHash();
}
void SCH_IO_DATABASE::ensureSettings( const wxString& aSettingsPath ) void SCH_IO_DATABASE::ensureSettings( const wxString& aSettingsPath )
{ {
auto tryLoad = auto tryLoad =

View File

@ -85,6 +85,8 @@ public:
bool TestConnection( wxString* aErrorMsg = nullptr ); bool TestConnection( wxString* aErrorMsg = nullptr );
private: private:
void cacheLib();
void ensureSettings( const wxString& aSettingsPath ); void ensureSettings( const wxString& aSettingsPath );
void ensureConnection(); void ensureConnection();
@ -108,6 +110,14 @@ private:
std::set<wxString> m_defaultShownFields; std::set<wxString> m_defaultShownFields;
std::map<wxString, LIB_SYMBOL*> m_nameToSymbolcache;
long long m_cacheTimestamp;
int m_cacheModifyHash;
wxString m_lastError; wxString m_lastError;
}; };