From 70538f421e4c53f2fd46af5484c5aef09f7f183b Mon Sep 17 00:00:00 2001 From: Alexander Hirsch Date: Fri, 15 Jun 2018 14:24:40 +0200 Subject: [PATCH] Optimize filteredItemsCache_ filling by passing in a guess for the index. --- src/data/logfiltereddata.cpp | 72 +++++++++++++++++++++++++++--------- src/data/logfiltereddata.h | 8 ++++ src/marks.cpp | 4 +- src/marks.h | 4 +- 4 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/data/logfiltereddata.cpp b/src/data/logfiltereddata.cpp index 4d5de5935..cc231ef15 100644 --- a/src/data/logfiltereddata.cpp +++ b/src/data/logfiltereddata.cpp @@ -177,10 +177,10 @@ LogFilteredData::FilteredLineType void LogFilteredData::addMark( qint64 line, QChar mark ) { if ( ( line >= 0 ) && ( line < sourceLogData_->getNbLine() ) ) { - marks_.addMark( line, mark ); + int index = marks_.addMark( line, mark ); maxLengthMarks_ = qMax( maxLengthMarks_, sourceLogData_->getLineLength( line ) ); - insertIntoFilteredItemsCache( FilteredItem{ static_cast( line ), Mark } ); + insertIntoFilteredItemsCache( index, FilteredItem{ static_cast( line ), Mark } ); } else LOG(logERROR) << "LogFilteredData::addMark\ @@ -237,15 +237,15 @@ void LogFilteredData::deleteMark( QChar mark ) } updateMaxLengthMarks( line ); - removeFromFilteredItemsCache( FilteredItem{ static_cast( line ), Mark } ); + removeFromFilteredItemsCache( index, FilteredItem{ static_cast( line ), Mark } ); } void LogFilteredData::deleteMark( qint64 line ) { - marks_.deleteMark( line ); + int index = marks_.deleteMark( line ); updateMaxLengthMarks( line ); - removeFromFilteredItemsCache( FilteredItem{ static_cast( line ), Mark } ); + removeFromFilteredItemsCache( index, FilteredItem{ static_cast( line ), Mark } ); } void LogFilteredData::updateMaxLengthMarks( qint64 removed_line ) @@ -300,14 +300,7 @@ void LogFilteredData::handleSearchProgressed( int nbMatches, int progress, qint6 workerThread_.updateSearchResult( &maxLength_, &matching_lines_, &nbLinesProcessed_ ); - assert( matching_lines_.size() >= start_index ); - - filteredItemsCache_.reserve( matching_lines_.size() + marks_.size() ); - // (it's an overestimate but probably not by much so it's fine) - - for ( auto it = next( begin( matching_lines_ ), start_index ); it != end( matching_lines_ ); ++it ) { - insertIntoFilteredItemsCache( FilteredItem{ it->lineNumber(), Match } ); - } + insertMatchesIntoFilteredItemsCache( start_index ); emit searchProgressed( nbMatches, progress, initial_position ); } @@ -492,20 +485,21 @@ void LogFilteredData::regenerateFilteredItemsCache() const LOG(logDEBUG) << "finished regenerateFilteredItemsCache"; } -void LogFilteredData::insertIntoFilteredItemsCache( FilteredItem item ) +void LogFilteredData::insertIntoFilteredItemsCache( size_t insert_index, FilteredItem item ) { using std::begin; using std::end; + using std::next; if ( visibility_ != MarksAndMatches ) { // this is invalidated and will be regenerated when we need it filteredItemsCache_.clear(); LOG(logDEBUG) << "cache is invalidated"; - return; } // Search for the corresponding index. - auto found = std::lower_bound( begin( filteredItemsCache_ ), end( filteredItemsCache_ ), item ); + // We can start the search from insert_index, since lineNumber >= index is always true. + auto found = std::lower_bound( next( begin( filteredItemsCache_ ), insert_index ), end( filteredItemsCache_ ), item ); if ( found == end( filteredItemsCache_ ) || found->lineNumber() > item.lineNumber() ) { filteredItemsCache_.insert( found, item ); } else { @@ -514,11 +508,52 @@ void LogFilteredData::insertIntoFilteredItemsCache( FilteredItem item ) } } -void LogFilteredData::removeFromFilteredItemsCache( FilteredItem item ) +void LogFilteredData::insertIntoFilteredItemsCache( FilteredItem item ) +{ + insertIntoFilteredItemsCache( 0, item ); +} + +void LogFilteredData::insertMatchesIntoFilteredItemsCache( size_t start_index ) +{ + using std::begin; + using std::end; + using std::next; + + assert( start_index <= matching_lines_.size() ); + + if ( visibility_ != MarksAndMatches ) { + // this is invalidated and will be regenerated when we need it + filteredItemsCache_.clear(); + LOG(logDEBUG) << "cache is invalidated"; + return; + } + + assert( start_index <= filteredItemsCache_.size() ); + + filteredItemsCache_.reserve( matching_lines_.size() + marks_.size() ); + // (it's an overestimate but probably not by much so it's fine) + + // Search for the corresponding index. + // We can start the search from insert_index, since lineNumber >= index is always true. + auto filteredIt = next( begin( filteredItemsCache_ ), start_index ); + for ( auto matchesIt = next( begin( matching_lines_ ), start_index ); matchesIt != end( matching_lines_ ); ++matchesIt ) { + FilteredItem item{ matchesIt->lineNumber(), Match }; + filteredIt = std::lower_bound( filteredIt, end( filteredItemsCache_ ), item ); + if ( filteredIt == end( filteredItemsCache_ ) || filteredIt->lineNumber() > item.lineNumber() ) { + filteredIt = filteredItemsCache_.insert( filteredIt, item ); + } else { + assert( filteredIt->lineNumber() == matchesIt->lineNumber() ); + filteredIt->add( item.type() ); + } + } +} + +void LogFilteredData::removeFromFilteredItemsCache( size_t remove_index, FilteredItem item ) { using std::begin; using std::distance; using std::end; + using std::next; if ( visibility_ != MarksAndMatches ) { // this is invalidated and will be regenerated when we need it @@ -528,7 +563,8 @@ void LogFilteredData::removeFromFilteredItemsCache( FilteredItem item ) } // Search for the corresponding index. - auto found = std::equal_range( begin( filteredItemsCache_ ), end( filteredItemsCache_ ), item ); + // We can start the search from remove_index, since lineNumber >= index is always true. + auto found = std::equal_range( next( begin( filteredItemsCache_ ), remove_index ), end( filteredItemsCache_ ), item ); if( found.first == end( filteredItemsCache_ ) ) { LOG(logERROR) << "Attempt to remove line " << item.lineNumber() << " from filteredItemsCache_ failed, since it was not found"; return; diff --git a/src/data/logfiltereddata.h b/src/data/logfiltereddata.h index 48136aed5..7eca098f4 100644 --- a/src/data/logfiltereddata.h +++ b/src/data/logfiltereddata.h @@ -165,7 +165,15 @@ class LogFilteredData : public AbstractLogData { LineNumber findFilteredLine( LineNumber lineNum ) const; void regenerateFilteredItemsCache() const; + // start_index can be passed in as an optimization when finding the item. + // It refers to the index of the singular arrays (Marks or SearchResultArray) where the item was inserted. + void insertIntoFilteredItemsCache( size_t start_index, FilteredItem item ); void insertIntoFilteredItemsCache( FilteredItem item ); + // Insert entries from matching_lines_ into filteredItemsCache_ starting by start_index. + void insertMatchesIntoFilteredItemsCache( size_t start_index ); + // remove_index can be passed in as an optimization when finding the item. + // It refers to the index of the singular arrays (Marks or SearchResultArray) where the item was removed. + void removeFromFilteredItemsCache( size_t remove_index, FilteredItem item ); void removeFromFilteredItemsCache( FilteredItem item ); void removeAllFromFilteredItemsCache( FilteredLineType type ); diff --git a/src/marks.cpp b/src/marks.cpp index 9201331c7..d3f4d2036 100644 --- a/src/marks.cpp +++ b/src/marks.cpp @@ -32,7 +32,7 @@ Marks::Marks() : marks_() { } -void Marks::addMark( qint64 line, QChar mark ) +int Marks::addMark( qint64 line, QChar mark ) { // Look for the index immediately before int index; @@ -50,6 +50,8 @@ void Marks::addMark( qint64 line, QChar mark ) // 'mark' is not used yet mark = mark; + + return index; } qint64 Marks::getMark( QChar mark ) const diff --git a/src/marks.h b/src/marks.h index e55ac6376..3a935ff42 100644 --- a/src/marks.h +++ b/src/marks.h @@ -49,7 +49,9 @@ class Marks { // Add a mark at the given line, optionally identified by the given char // If a mark for this char already exist, the previous one is replaced. // It will happily add marks anywhere, even at stupid indexes. - void addMark( qint64 line, QChar mark = QChar() ); + // Returns the index at which the mark was inserted, + // such that getLineMarkedByIndex( addMark( line ) ) == line. + int addMark( qint64 line, QChar mark = QChar() ); // Get the (unique) mark identified by the passed char. qint64 getMark( QChar mark ) const; // Returns wheither the passed line has a mark on it.