diff --git a/dltmessageanalyzerplugin/src/CMakeLists.txt b/dltmessageanalyzerplugin/src/CMakeLists.txt index 1178109b..816c268d 100644 --- a/dltmessageanalyzerplugin/src/CMakeLists.txt +++ b/dltmessageanalyzerplugin/src/CMakeLists.txt @@ -3,6 +3,31 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) ################### CPP ( END ) ########################### +########## OPTIONS ############ +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + option(DMA_TC_MALLOC_OPTIMIZATION "[ + This option enables tcmalloc RAM usage optimization. + You will need to link dlt-viewer against tcmalloc to use this feature. + ]" OFF) + option(DMA_TC_MALLOC_PROFILING "[ + This option enables tcmalloc profiling. Adds 'dump-memory-stats' command to the console view. + You will need to link dlt-viewer against tcmalloc to use this feature. + ]" OFF) + + if(DMA_TC_MALLOC_OPTIMIZATION) + add_compile_definitions(DMA_TC_MALLOC_OPTIMIZATION_ENABLED) + message(STATUS "DMA_TC_MALLOC_OPTIMIZATION enabled") + else() + add_compile_definitions(DMA_GLIBC_MALLOC_OPTIMIZATION_ENABLED) + endif() + + if(DMA_TC_MALLOC_PROFILING) + add_compile_definitions(DMA_TC_MALLOC_PROFILING_ENABLED) + message(STATUS "DMA_TC_MALLOC_PROFILING enabled") + endif() +endif() +########## OPTIONS ( END ) #### + ################### QT_SPECIFIC ########################### if(${QT_PREFIX}Core_VERSION VERSION_LESS "5.15.0") message("DMA_QT5_COMPATIBILITY_MODE is set") diff --git a/dltmessageanalyzerplugin/src/common/CMakeLists.txt b/dltmessageanalyzerplugin/src/common/CMakeLists.txt index 6aed044d..c42b88d7 100644 --- a/dltmessageanalyzerplugin/src/common/CMakeLists.txt +++ b/dltmessageanalyzerplugin/src/common/CMakeLists.txt @@ -11,5 +11,9 @@ add_library(DMA_common STATIC add_subdirectory(PCRE) ################### QT #################################### -target_link_libraries(DMA_common qdlt ${QT_PREFIX}::Widgets ) +target_link_libraries(DMA_common PUBLIC qdlt ${QT_PREFIX}::Widgets ) ################### QT ( END ) ############################ + +if(DMA_TC_MALLOC_OPTIMIZATION OR DMA_TC_MALLOC_PROFILING) + target_link_libraries(DMA_common PRIVATE tcmalloc) +endif() diff --git a/dltmessageanalyzerplugin/src/common/Definitions.cpp b/dltmessageanalyzerplugin/src/common/Definitions.cpp index 8eaa7a62..98bc59f7 100644 --- a/dltmessageanalyzerplugin/src/common/Definitions.cpp +++ b/dltmessageanalyzerplugin/src/common/Definitions.cpp @@ -11,6 +11,12 @@ #include #include +#ifdef DMA_TC_MALLOC_OPTIMIZATION_ENABLED +#include +#elif DMA_GLIBC_MALLOC_OPTIMIZATION_ENABLED +#include +#endif + #include #include @@ -471,56 +477,6 @@ bool tHighlightingRange::operator< ( const tHighlightingRange& rVal ) const return bResult; } -/////////////////////////////tIntRangePtrWrapper///////////////////////////// -bool tIntRangePtrWrapper::operator< ( const tIntRangePtrWrapper& rVal ) const -{ - bool bResult = false; - - if(pRange == nullptr && rVal.pRange != nullptr) - bResult = true; - else if(pRange != nullptr && rVal.pRange == nullptr) - bResult = false; - else if(pRange == nullptr && rVal.pRange == nullptr) - bResult = true; - else - { - if( pRange->from < rVal.pRange->from ) - { - bResult = true; - } - else if( pRange->from > rVal.pRange->from ) - { - bResult = false; - } - else // if from == rVal.from - { - if( pRange->to < rVal.pRange->to ) - { - bResult = true; - } - else - { - bResult = false; - } - } - } - - return bResult; -} - -bool tIntRangePtrWrapper::operator== ( const tIntRangePtrWrapper& rVal ) const -{ - if(pRange == nullptr && rVal.pRange != nullptr) - return false; - else if(pRange != nullptr && rVal.pRange == nullptr) - return false; - else if(pRange == nullptr && rVal.pRange == nullptr) - return true; - - return ( pRange->from == rVal.pRange->from && pRange->to == rVal.pRange->to ); -} -////////////////////////////////////////////////////////////////////////// - /////////////////////////////tQStringPtrWrapper/////////////////////////// tQStringPtrWrapper::tQStringPtrWrapper(): pString(nullptr) {} @@ -664,9 +620,8 @@ tTreeItemSharedPtr getMatchesTree( const tFoundMatches& foundMatches ) assert(false == data.empty()); - tIntRangePtrWrapper rangePtrWrapper; - rangePtrWrapper.pRange = &match.range; - tDataItem rangeVariant( rangePtrWrapper ); + tIntRange range = match.range; + tDataItem rangeVariant( range ); auto* pAddedChild = pCurrentItem->appendChild(rangeVariant, data); pCurrentItem = pAddedChild; @@ -756,7 +711,7 @@ tCalcRangesCoverageMulticolorResult calcRangesCoverageMulticolor( const tTreeIte // .arg(match.idx) // .arg(match.range.from) // .arg(match.range.to) - // .arg(*match.pMatchStr)); + // .arg(match.matchStr)); if( ( match.range.from < inputRange.from && match.range.to < inputRange.from ) || ( match.range.from > inputRange.to && match.range.to > inputRange.to ) ) @@ -1024,7 +979,7 @@ tTreeItemSharedPtr tItemMetadata::updateHighlightingInfo( const tFoundMatches& f for(const auto& match : sortedMatches) { - if(nullptr != match.second->pMatchStr && false == match.second->pMatchStr->isEmpty()) + if(false == match.second->matchStr.isEmpty()) { result.insert(std::make_pair( match.second->idx, gradientColorsCounter % maxGradientColorsSize )); ++gradientColorsCounter; @@ -1336,16 +1291,17 @@ tItemMetadata::updatePlotViewInfo(const tFoundMatches& foundMatches, } //tFoundMatch + tFoundMatch::tFoundMatch(): -pMatchStr(std::make_shared()), +matchStr(), range(0,0), idx(0) {} -tFoundMatch::tFoundMatch( const tQStringPtr& pMatchStr_, +tFoundMatch::tFoundMatch( const QString& matchStr_, const tIntRange& range_, const int& idx_): -pMatchStr((nullptr!=pMatchStr_)?pMatchStr_:std::make_shared()), +matchStr(matchStr_), range(range_), idx(idx_) {} @@ -1380,7 +1336,7 @@ tFoundMatchesPackItem::tFoundMatchesPackItem() tFoundMatchesPackItem::tFoundMatchesPackItem( tItemMetadata&& itemMetadata_, tFoundMatches&& foundMatches_ ): mItemMetadata(std::move(itemMetadata_)), - mFoundMatches(foundMatches_) + mFoundMatches(std::move(foundMatches_)) { } @@ -2730,9 +2686,9 @@ QVariant toQVariant(const tDataItem& item) { result.setValue(item.get()); } - else if(item.index() == tDataItem::index_of()) + else if(item.index() == tDataItem::index_of()) { - result.setValue(item.get()); + result.setValue(item.get()); } else if(item.index() == tDataItem::index_of()) { @@ -3677,6 +3633,43 @@ QColor getChartColor() return sColors[sColorsCounter++ % sColorsSize]; } +void releaseMemoryToOS() +{ +#ifdef DMA_TC_MALLOC_OPTIMIZATION_ENABLED + MallocExtension::instance()->ReleaseFreeMemory(); +#elif DMA_GLIBC_MALLOC_OPTIMIZATION_ENABLED + malloc_trim(0); +#endif +} + +#ifdef DMA_TC_MALLOC_PROFILING_ENABLED +void dumpMemoryStatistics() +{ + SEND_MSG(""); + SEND_MSG("----------------------------------------------------|"); + SEND_MSG("---------------TC_MALLOC_OUTPUT_START---------------|"); + SEND_MSG("----------------------------------------------------|"); + SEND_MSG(""); + + const int bufferSize = 100000; + char stats[bufferSize]; + MallocExtension::instance()->GetStats(stats, bufferSize); + QString str(stats); + auto strVec = str.split("\n"); + + for(const auto& str : strVec) + { + SEND_MSG(QString("%1").arg(str)); + } + + SEND_MSG(""); + SEND_MSG("----------------------------------------------------|"); + SEND_MSG("----------------TC_MALLOC_OUTPUT_END----------------|"); + SEND_MSG("----------------------------------------------------|"); + SEND_MSG(""); +} +#endif + PUML_PACKAGE_BEGIN(Qt) PUML_CLASS_BEGIN(QThread) PUML_CLASS_END() diff --git a/dltmessageanalyzerplugin/src/common/Definitions.hpp b/dltmessageanalyzerplugin/src/common/Definitions.hpp index 0af84c2b..5ea231d7 100644 --- a/dltmessageanalyzerplugin/src/common/Definitions.hpp +++ b/dltmessageanalyzerplugin/src/common/Definitions.hpp @@ -155,18 +155,9 @@ struct tRange tRangeItem to; }; -typedef tRange tIntRange; +typedef tRange tIntRange; Q_DECLARE_METATYPE(tIntRange) -struct tIntRangePtrWrapper -{ - bool operator== ( const tIntRangePtrWrapper& rVal ) const; - bool operator< ( const tIntRangePtrWrapper& rVal ) const; - const tIntRange* pRange = nullptr; -}; - -Q_DECLARE_METATYPE(tIntRangePtrWrapper) - typedef QVector tIntRangeList; typedef std::set tIntRangeSet; @@ -340,7 +331,7 @@ typedef QMap tFieldRanges; struct tFoundMatch { tFoundMatch(); - tFoundMatch( const tQStringPtr& pMatchStr_, + tFoundMatch( const QString& matchStr_, const tIntRange& range_, const int& idx_ ); @@ -352,7 +343,7 @@ struct tFoundMatch */ bool operator< (const tFoundMatch& rhs) const; - tQStringPtr pMatchStr; + QString matchStr; tIntRange range; int idx; }; @@ -377,10 +368,9 @@ typedef nonstd::variant tTreeDataItem; typedef tTreeDataItem tDataItem; // just to refactor less code QVariant toQVariant(const tDataItem& item); @@ -829,4 +819,50 @@ enum class eTabIndexes CONSOLE_VIEW = 6 }; +/** + * @brief Releases unused memory back to the operating system. + * + * This function ensures that unused memory managed by the allocator is returned + * to the operating system to free up resources. It supports different memory + * management systems: + * + * - If `DMA_TC_MALLOC_OPTIMIZATION_ENABLED` is defined, it uses TCMalloc's + * `ReleaseFreeMemory` method to release unused memory. + * - If `DMA_GLIBC_MALLOC_OPTIMIZATION_ENABLED` is defined, it uses glibc's + * `malloc_trim(0)` function to achieve the same effect. + * + * Use this function after memory-intensive operations to optimize memory usage. + */ +void releaseMemoryToOS(); + +#ifdef DMA_TC_MALLOC_PROFILING_ENABLED +/** + * @brief Dumps detailed memory allocation statistics. + * + * This function retrieves and outputs memory usage statistics when TCMalloc + * profiling is enabled (`DMA_TC_MALLOC_PROFILING_ENABLED`). The statistics + * provide insights into memory allocation patterns, freelist usage, and + * overall memory consumption managed by TCMalloc. + * + * The output includes a formatted summary of TCMalloc's memory state, + * surrounded by clearly marked start and end tags for easier parsing or + * debugging. + * + * **Example Output:** + * ``` + * ----------------------------------------------------| + * ---------------TC_MALLOC_OUTPUT_START---------------| + * ----------------------------------------------------| + * MALLOC:
+ * ----------------------------------------------------| + * ----------------TC_MALLOC_OUTPUT_END----------------| + * ----------------------------------------------------| + * ``` + * + * This method is useful for debugging and profiling memory usage in + * applications relying on TCMalloc. + */ +void dumpMemoryStatistics(); +#endif + #endif // DEFINITIONS_HPP diff --git a/dltmessageanalyzerplugin/src/components/analyzer/src/CDLTRegexAnalyzerWorker.cpp b/dltmessageanalyzerplugin/src/components/analyzer/src/CDLTRegexAnalyzerWorker.cpp index 0037b255..35ddb6a5 100644 --- a/dltmessageanalyzerplugin/src/components/analyzer/src/CDLTRegexAnalyzerWorker.cpp +++ b/dltmessageanalyzerplugin/src/components/analyzer/src/CDLTRegexAnalyzerWorker.cpp @@ -128,7 +128,7 @@ void CDLTRegexAnalyzerWorker::analyzePortion( const tAnalyzePortionData& analyz if(0 != match.capturedLength(i)) { const auto& matchItem = match.captured(i); - foundMatches.foundMatchesVec.push_back( tFoundMatch( std::make_shared(matchItem), + foundMatches.foundMatchesVec.emplace_back( tFoundMatch( matchItem, tIntRange( match.capturedStart(i), match.capturedEnd(i) - 1 ), i) ); } diff --git a/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersModel.cpp b/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersModel.cpp index ab159562..ecd8d015 100644 --- a/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersModel.cpp +++ b/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersModel.cpp @@ -750,7 +750,7 @@ void CFiltersModel::addCompletionData( const tFoundMatches& foundMatches ) if(foundVarGroup != mVarGroupsMap.end()) { - mCompletionCache[foundMatch.idx].insert( tQStringPtrWrapper( foundMatch.pMatchStr ) ); + mCompletionCache[foundMatch.idx].insert( foundMatch.matchStr ); } } } @@ -784,16 +784,16 @@ QStringList CFiltersModel::getCompletionData( const int& groupIndex, if(false == getSettingsManager()->getFiltersCompletion_SearchPolicy()) { - bStringFound = completionItem.pString->startsWith(input, caseSensitiveOption); + bStringFound = completionItem.startsWith(input, caseSensitiveOption); } else { - bStringFound = completionItem.pString->contains(input, caseSensitiveOption); + bStringFound = completionItem.contains(input, caseSensitiveOption); } - if(completionItem.pString && bStringFound) + if(bStringFound) { - result.push_back(completionItem.pString->mid(0, maxLengthOfSuggestions)); + result.push_back(completionItem.mid(0, maxLengthOfSuggestions)); ++numberOfSuggestions; } diff --git a/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersModel.hpp b/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersModel.hpp index 7dcf4ff6..2bc1233d 100644 --- a/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersModel.hpp +++ b/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersModel.hpp @@ -67,8 +67,8 @@ class CFiltersModel : public IFiltersModel, CTreeItem::tSortingFunction mSortingHandler; QString mFilter; - typedef std::set tStringPtrWrapperSet; - typedef std::map tCompletionCache; + typedef std::set tStringSet; + typedef std::map tCompletionCache; tCompletionCache mCompletionCache; typedef std::set tVarGroupsMap; diff --git a/dltmessageanalyzerplugin/src/components/groupedView/src/CGroupedViewModel.cpp b/dltmessageanalyzerplugin/src/components/groupedView/src/CGroupedViewModel.cpp index 2abcbbc0..6501d3e6 100644 --- a/dltmessageanalyzerplugin/src/components/groupedView/src/CGroupedViewModel.cpp +++ b/dltmessageanalyzerplugin/src/components/groupedView/src/CGroupedViewModel.cpp @@ -494,7 +494,7 @@ void CGroupedViewModel::addMatches( const tGroupedViewIndices& groupedViewIndice { CTreeItem::tData data; data.reserve(9); - data.push_back( tQStringPtrWrapper(match.pMatchStr) ); /*SubString*/ + data.push_back(match.matchStr); /*SubString*/ data.push_back(tDataItem(1)); /*Messages*/ data.push_back(tDataItem(0)); /*MessagesPercantage*/ data.push_back(tDataItem(0)); /*MessagesPerSecond*/ diff --git a/dltmessageanalyzerplugin/src/components/log/src/CConsoleCtrl.cpp b/dltmessageanalyzerplugin/src/components/log/src/CConsoleCtrl.cpp index 88356239..b4f52f28 100644 --- a/dltmessageanalyzerplugin/src/components/log/src/CConsoleCtrl.cpp +++ b/dltmessageanalyzerplugin/src/components/log/src/CConsoleCtrl.cpp @@ -146,7 +146,9 @@ void CConsoleCtrl::sendMessage( const QString& message, CConsoleCtrl::CConsoleCtrl( const tConsoleConfig& consoleConfig ): mConsoleConfig(consoleConfig), mMessageCounters(), -mCountedMessageType(eMessageType::eMsg) +mCountedMessageType(eMessageType::eMsg), +mBufferedMessages(), +mFlushBufferedMessagsTimer() { if(nullptr != mConsoleConfig.pConsoleTextEdit) { @@ -187,6 +189,37 @@ mCountedMessageType(eMessageType::eMsg) }); } } + + connect(&mFlushBufferedMessagsTimer, &QTimer::timeout, this, [this]() + { + if(mConsoleConfig.pConsoleTextEdit) + { + if(!mBufferedMessages.empty()) + { + QString finalMessage; + + auto sizeCounter = 0; + + for(const auto& message : mBufferedMessages) + { + sizeCounter += message.size(); + } + + finalMessage.reserve(sizeCounter); + + for(const auto& message : mBufferedMessages) + { + finalMessage.push_back(message); + } + + mConsoleConfig.pConsoleTextEdit->appendHtml(finalMessage); + + mBufferedMessages.clear(); + } + } + + mFlushBufferedMessagsTimer.stop(); + }); } void CConsoleCtrl::addMessage( const QString& message, const tMessageSettings& messageSettings ) @@ -256,7 +289,8 @@ void CConsoleCtrl::addMessage( const QString& message, const tMessageSettings& m HTMLMessage.append(""); - mConsoleConfig.pConsoleTextEdit->appendHtml(HTMLMessage); + mBufferedMessages.push_back(HTMLMessage); + mFlushBufferedMessagsTimer.start(100); } if(nullptr != mConsoleConfig.pTabWidget && nullptr != mConsoleConfig.pConsoleTab) diff --git a/dltmessageanalyzerplugin/src/components/log/src/CConsoleCtrl.hpp b/dltmessageanalyzerplugin/src/components/log/src/CConsoleCtrl.hpp index dbed0157..100a75d3 100644 --- a/dltmessageanalyzerplugin/src/components/log/src/CConsoleCtrl.hpp +++ b/dltmessageanalyzerplugin/src/components/log/src/CConsoleCtrl.hpp @@ -4,6 +4,7 @@ #include "QPlainTextEdit" #include "QTabWidget" +#include "QTimer" namespace NDLTMessageAnalyzer { @@ -105,6 +106,8 @@ private slots: typedef QMap tMessageCounters; tMessageCounters mMessageCounters; eMessageType mCountedMessageType; + QStringList mBufferedMessages; + QTimer mFlushBufferedMessagsTimer; }; } } diff --git a/dltmessageanalyzerplugin/src/components/log/src/CConsoleInputProcessor.cpp b/dltmessageanalyzerplugin/src/components/log/src/CConsoleInputProcessor.cpp index fe1b3e68..fb1461d6 100644 --- a/dltmessageanalyzerplugin/src/components/log/src/CConsoleInputProcessor.cpp +++ b/dltmessageanalyzerplugin/src/components/log/src/CConsoleInputProcessor.cpp @@ -675,6 +675,11 @@ CConsoleInputProcessor::tScenariosMap CConsoleInputProcessor::createScenariosMap "[-tf= // mandatory! Target file, into which we should save the content]" "[-v= // optional! Version of the dlt protocol. Supported values are 'v1' and 'v2'. Default value is 'v2']"); +#ifdef DMA_TC_MALLOC_PROFILING_ENABLED + result["dump-memory-stats"] = CConsoleInputProcessor::tScenarioData([](const CConsoleInputProcessor::tParamMap&){dumpMemoryStatistics();} + , "- prints tcmalloc memory stats"); +#endif + return result; } @@ -718,13 +723,13 @@ bool CConsoleInputProcessor::eventFilter(QObject* pObj, QEvent* pEvent) } else { - if(mCurrentHistoryItem < static_cast(mHistory.size() - 1)) + if(mCurrentHistoryItem > 0) { QString text = mpTargetLineEdit->text(); if(false == text.isEmpty()) { - ++mCurrentHistoryItem; + --mCurrentHistoryItem; } mpTargetLineEdit->setText(mHistory[static_cast(mCurrentHistoryItem)]); @@ -754,13 +759,13 @@ bool CConsoleInputProcessor::eventFilter(QObject* pObj, QEvent* pEvent) } else { - if(mCurrentHistoryItem > 0) + if(mCurrentHistoryItem < static_cast(mHistory.size() - 1)) { QString text = mpTargetLineEdit->text(); if(false == text.isEmpty()) { - --mCurrentHistoryItem; + ++mCurrentHistoryItem; } mpTargetLineEdit->setText(mHistory[static_cast(mCurrentHistoryItem)]); @@ -844,7 +849,7 @@ bool CConsoleInputProcessor::eventFilter(QObject* pObj, QEvent* pEvent) if(foundHistoryItem == mHistory.end()) { - mHistory.push_front(text); + mHistory.push_back(text); if(mHistory.size() == 1) { @@ -855,7 +860,7 @@ bool CConsoleInputProcessor::eventFilter(QObject* pObj, QEvent* pEvent) mbBorderReached = eHistoryBorderStatus::Not_Near_Border; } - if(mCurrentHistoryItem > sMaxCommandsHistorySize) + if(mHistory.size() > sMaxCommandsHistorySize) { mHistory.resize(sMaxCommandsHistorySize); } @@ -863,11 +868,12 @@ bool CConsoleInputProcessor::eventFilter(QObject* pObj, QEvent* pEvent) else { mHistory.erase(foundHistoryItem); - mHistory.push_front(text); + mHistory.push_back(text); } } - mCurrentHistoryItem = 0; + mCurrentHistoryItem = mHistory.size() - 1; + mbBorderReached = eHistoryBorderStatus::Reached_Last; mpTargetLineEdit->clear(); diff --git a/dltmessageanalyzerplugin/src/components/logsWrapper/src/CDLTFileWrapper.cpp b/dltmessageanalyzerplugin/src/components/logsWrapper/src/CDLTFileWrapper.cpp index 13a87c0b..dbe1d69f 100644 --- a/dltmessageanalyzerplugin/src/components/logsWrapper/src/CDLTFileWrapper.cpp +++ b/dltmessageanalyzerplugin/src/components/logsWrapper/src/CDLTFileWrapper.cpp @@ -391,6 +391,8 @@ void CDLTFileWrapper::resetCache() loadChanged(0); handleCacheFull(false); + + releaseMemoryToOS(); } void CDLTFileWrapper::setMessageDecoder( const tMsgDecoderPtr& pMessageDecoder ) diff --git a/dltmessageanalyzerplugin/src/components/searchView/src/CSearchResultModel.cpp b/dltmessageanalyzerplugin/src/components/searchView/src/CSearchResultModel.cpp index 78300802..3edd4468 100644 --- a/dltmessageanalyzerplugin/src/components/searchView/src/CSearchResultModel.cpp +++ b/dltmessageanalyzerplugin/src/components/searchView/src/CSearchResultModel.cpp @@ -36,7 +36,7 @@ void CSearchResultModel::updateView(const int& fromRow) void CSearchResultModel::resetData() { beginResetModel(); - mFoundMatchesPack.matchedItemVec.clear(); + tFoundMatchesPackItemVec().swap(mFoundMatchesPack.matchedItemVec); mHighlightMessages.clear(); endResetModel(); updateView(); @@ -57,8 +57,8 @@ const tFoundMatchesPackItem& CSearchResultModel::getFoundMatchesItemPack( const if ( ( modelIndex.row() < 0 || modelIndex.row() >= static_cast(mFoundMatchesPack.matchedItemVec.size()) ) || ( modelIndex.column() < 0 || modelIndex.column() >= static_cast(eSearchResultColumn::Last) ) ) { - static const tFoundMatchesPackItemPtr spDummyValue = std::make_shared(); - return *spDummyValue; + static const tFoundMatchesPackItem sDummyValue; + return sDummyValue; } return *mFoundMatchesPack.matchedItemVec[ static_cast(modelIndex.row()) ]; diff --git a/dltmessageanalyzerplugin/src/plugin/src/CDLTMessageAnalyzer.cpp b/dltmessageanalyzerplugin/src/plugin/src/CDLTMessageAnalyzer.cpp index 34fc3895..3f233873 100644 --- a/dltmessageanalyzerplugin/src/plugin/src/CDLTMessageAnalyzer.cpp +++ b/dltmessageanalyzerplugin/src/plugin/src/CDLTMessageAnalyzer.cpp @@ -129,7 +129,6 @@ CDLTMessageAnalyzer::CDLTMessageAnalyzer(const std::weak_ptr("tIntRangePtrWrapper"); qRegisterMetaType("tQStringPtrWrapper"); qRegisterMetaType("tIntRange"); qRegisterMetaType("const tFoundMatch*"); @@ -1678,6 +1677,8 @@ bool CDLTMessageAnalyzer::analyze(const QStringList* pSelectedAliases) nullptr != pSelectedAliases ? *pSelectedAliases : QStringList() ); + releaseMemoryToOS(); + auto requestId = requestAnalyze( requestParameters, getSettingsManager()->getUML_FeatureActive(), getSettingsManager()->getPlotViewFeatureActive(), @@ -1742,6 +1743,8 @@ void CDLTMessageAnalyzer::cancel() updateStatusLabel(sDefaultStatusText, false); tryStop(); + + releaseMemoryToOS(); } void CDLTMessageAnalyzer::setReuqestId( const tRequestId& val ) @@ -1913,6 +1916,8 @@ void CDLTMessageAnalyzer::progressNotification(const tProgressNotificationData& .arg(progressNotificationData.requestId) .arg(QLocale().toString(mMeasurementRequestTimer.elapsed()), 4)); + releaseMemoryToOS(); + mMeasurementRequestTimer.restart(); } } @@ -1962,6 +1967,8 @@ void CDLTMessageAnalyzer::progressNotification(const tProgressNotificationData& SEND_MSG(QString("CDLTMessageAnalyzer::progressNotification: request id - %1; overall processing took - %2 ms") .arg(progressNotificationData.requestId) .arg(QLocale().toString(mMeasurementRequestTimer.elapsed()), 4)); + + releaseMemoryToOS(); } break; diff --git a/md/debug_console/debug_console.md b/md/debug_console/debug_console.md index daf0c36d..29f85349 100644 --- a/md/debug_console/debug_console.md +++ b/md/debug_console/debug_console.md @@ -42,6 +42,7 @@ The current set of the supported commands contains: | clear | No params | clear debug view | | color-aliases | No params | prints all supported color aliases | | convert-txt-to-dlt-file | [-sf= // mandatory! Source file which we should convert to the dlt format][-tf= // mandatory! Target file, into which we should save the content][-v= // optional! Version of the dlt protocol. Supported values are 'v1' and 'v2'. Default value is 'v2'] | converts specified file with '\n' separated set of strings to the dlt format +| dump-memory-stats | No params | Prints tcmalloc memory stats. Available only if the 'DMA_TC_MALLOC_PROFILING' feature is activated. | | help | [-c=<command-name>] | show this help. If no "c" parameter is provided - help regarding all available commands will be dumped. Be aware, that [<command-name> <help>] syntax can also be used to get the help output regarding a single command. Such syntax is easier to use, considering the limited auto-complete functionality of this console. E.g. "help -help" (ha-ha). | | plantuml-settings | No params | prints information about the currently used plantuml settings | | styles | No params | prints information about QT styles supported on target OS | @@ -53,6 +54,8 @@ The current set of the supported commands contains: | version | No params | prints version of the plugin | | web-link | No params | prints URL with the location of the plugin on the Git hub | +**Note!** The set of available commands might differ depending on the selected CMake options. + ---- > **Note!** diff --git a/md/troubleshooting/troubleshooting.md b/md/troubleshooting/troubleshooting.md index fd2cd66c..44e00f95 100644 --- a/md/troubleshooting/troubleshooting.md +++ b/md/troubleshooting/troubleshooting.md @@ -2,6 +2,15 @@ ---- +# Table of Contents + +1. [Instance of dlt-viewer has an old-fashion styling](#instance-of-dlt-viewer-has-an-old-fashion-styling) +2. [When I try to perform a search within the DLT-Message-Analyzer plugin, I get the "Initial enabling error!" message](#when-i-try-to-perform-a-search-within-the-dlt-message-analyzer-plugin-i-get-the-initial-enabling-error-message) +3. [Settings collisions during simultaneous usage of the multiple plugin's instances](#settings-collisions-during-simultaneous-usage-of-the-multiple-plugins-instances) +4. [High level of the memory consumption](#high-level-of-the-memory-consumption) + +---- + # Troubleshooting ## Instance of dlt-viewer has an old-fashion styling @@ -25,7 +34,7 @@ You can select one of the available styles using the "-style" command-line optio In case if "windowsvista" style is missing in the above list, you can add it to the final deployment of the dlt-viewer in the following way: > Take it from: "<Qt_ROOT>\\<Qt_version>\\<Qt_toolchain>\plugins\styles\qwindowsvistastyle.dll" // or *.so, depending on the used OS. > -> Place it to: ".\dlt-viewer\styles\qwindowsvistastyle.dll" // or *.so, depending on the used OS. +> Place it to: ".\dlt-viewer\styles\qwindowsvistastyle.dll" // or \*.so, depending on the used OS. Then reboot the dlt-viewer. The additional style should become available.
@@ -63,7 +72,7 @@ Another proof of that would be an empty "Files view" of the plugin: ---- -#### 1. You have disabled "Plugins enabled" option on dlt-viewer's "Filter" tab and restarted the dlt-viewer: +1. You have disabled "Plugins enabled" option on dlt-viewer's "Filter" tab and restarted the dlt-viewer: ![Screenshot of the "plugins enabled" dlt-viewer's option](./troubleshooting_plugins_enabled_option.png) @@ -73,7 +82,7 @@ The possible measures of avoidance in this case are: ---- -#### 2. You have compiled a newer version of the dlt-viewer, which has a settings format incompatible with the previously used version. +2. You have compiled a newer version of the dlt-viewer, which has a settings format incompatible with the previously used version. There are possible measures of avoidance for this issue. @@ -133,7 +142,65 @@ Once again, sooner or later such inconsistent behavior will be eliminated. But u ---- -If the above instructions didn't help you - create a new issue [here](https://github.com/svlad-90/DLT-Message-Analyzer/issues) +## High level of the memory consumption + +
+ +Click for more details! + +The plugin's functionality is related to: + +- frequent reallocation within the internal collections related to the data that is fetched as search results +- long living usage session of the plugin within the dlt-viewer +- work with the big data sets. E.g., 6000000 of results is a normal thing +- usage of many nested structures, such as a vector of maps of maps, etc. +- metadata collection with the amount of collected metadata depending on the search query ( controlled by the user ) + +Depending on the search query, all this can cause a high level of memory consumption. + +E.g., the query "(F)requency:" which finds 6000000 search results can add ~1.5 Gb of RAM consumption. And the query "(F)(r)(e)(q)(u)(e)(n)(c)(y)(:)" can add 6-7 GB. + +The issue is not even the high RAM consumption. However, returning RAM to the OS after releasing the plugin's resources is way too relaxed for the Linux OS. The plugin still occupies released memory for an infinite amount of time while no leaks are found. + +In version v.1.0.30, the optimization was added for Linux OS to release the memory back to the OS in the following cases: + +- the start of the search +- the finish of the search +- the cancellation of the search +- the clearance of the dlt file cache + +That makes RAM consumption more predictable with no constant high consumption level. + +**In cases that are not enough for your case, the DMA_TC_MALLOC_OPTIMIZATION CMake option was added.** + +By default, it is turned off. If enabled, this option switches the allocator to tcmalloc. That will allow you to: + +- Minimize RAM consumption. For the above case with "(F)(r)(e)(q)(u)(e)(n)(c)(y)(:)" request RAM consumption with tcmalloc is ~3-4 Gb less +- Minimize search processing time. E.g., for the "(F)requency:" query with 6000000 messages, the processing time with tcmalloc was ~9 seconds without the tcmalloc but ~6 seconds with the tcmalloc. + +To use this feature, you will need to: + +- install tcmalloc on your machine: + ``` + sudo apt-get install google-perftools + ``` +- turn on the feature: + ``` + option(DMA_TC_MALLOC_OPTIMIZATION "[ + This option enables tcmalloc RAM usage optimization. + You will need to link dlt-viewer against tcmalloc to use this feature. + ]" ON) + ``` +- link dlt-viewer against tcmalloc to use this feature. Add the following line at the end of the root CMakeLists.txt of the dlt-viewer project: + ``` + target_link_libraries(dlt-viewer tcmalloc) + ``` +- Clean build the dlt-viewer to ensure that changes in CMake settings were considered +
+ +---- + +If the above instructions didn't help you - create a new issue [here](https://github.com/svlad-90/DLT-Message-Analyzer/issues). ----