diff --git a/ApplicationLibCode/Application/RiaMemoryCleanup.cpp b/ApplicationLibCode/Application/RiaMemoryCleanup.cpp index d5b65bb13b..266b08d684 100644 --- a/ApplicationLibCode/Application/RiaMemoryCleanup.cpp +++ b/ApplicationLibCode/Application/RiaMemoryCleanup.cpp @@ -34,6 +34,10 @@ #include "cafPdmUiPushButtonEditor.h" #include "cafPdmUiTreeSelectionEditor.h" +#include +#include +#include + //================================================================================================== /// /// @@ -55,6 +59,9 @@ RiaMemoryCleanup::RiaMemoryCleanup() CAF_PDM_InitFieldNoDefault( &m_performDelete, "ClearSelectedData", "" ); caf::PdmUiPushButtonEditor::configureEditorForField( &m_performDelete ); + + CAF_PDM_InitFieldNoDefault( &m_showMemoryReport, "ShowMemoryReport", "" ); + caf::PdmUiPushButtonEditor::configureEditorForField( &m_showMemoryReport ); } //-------------------------------------------------------------------------------------------------- @@ -107,6 +114,38 @@ void RiaMemoryCleanup::clearSelectedResultsFromMemory() m_geomResultAddresses.clear(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class TextDialog : public QDialog +{ +public: + TextDialog( const QString& text, QWidget* parent = nullptr ) + : QDialog( parent ) + { + auto textWidget = new QTextEdit( "", this ); + textWidget->setPlainText( text ); + auto layout = new QVBoxLayout( this ); + layout->addWidget( textWidget ); + setLayout( layout ); + } +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaMemoryCleanup::showMemoryReport() +{ + auto [summary, details] = createMemoryReport(); + + QString allText = summary + "\n\n" + details; + + auto dialog = new TextDialog( allText ); + dialog->setWindowTitle( "Memory Report" ); + dialog->setMinimumSize( 800, 600 ); + dialog->show(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -204,6 +243,12 @@ void RiaMemoryCleanup::fieldChangedByUi( const caf::PdmFieldHandle* changedField m_resultsToDelete.uiCapability()->updateConnectedEditors(); m_performDelete = false; } + else if ( changedField == &m_showMemoryReport ) + { + m_showMemoryReport = false; + + showMemoryReport(); + } } //-------------------------------------------------------------------------------------------------- @@ -310,10 +355,70 @@ void RiaMemoryCleanup::defineEditorAttribute( const caf::PdmFieldHandle* field, { if ( field == &m_performDelete ) { - caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast( attribute ); + auto attrib = dynamic_cast( attribute ); if ( attrib ) { attrib->m_buttonText = "Clear Checked Data From Memory"; } } + if ( field == &m_showMemoryReport ) + { + auto attrib = dynamic_cast( attribute ); + if ( attrib ) + { + attrib->m_buttonText = "Show Memory Report"; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RiaMemoryCleanup::createMemoryReport() +{ + QString details; + + auto allCases = RimProject::current()->allGridCases(); + + size_t totalMemory = 0; + for ( auto gridCase : allCases ) + { + if ( auto eclipseCase = dynamic_cast( gridCase ) ) + { + RigCaseCellResultsData* caseData = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + if ( caseData ) + { + size_t totalMemoryForCase = 0; + QString caseReport; + + auto memoryUse = caseData->resultValueCount(); + for ( const auto& [name, valueCount] : memoryUse ) + { + if ( valueCount > 0 ) + { + size_t memory = valueCount * sizeof( double ); + totalMemoryForCase += memory; + + caseReport += QString( " %1 MB\tValue count %2, %3\n" ) + .arg( memory / 1024.0 / 1024.0, 0, 'f', 2 ) + .arg( valueCount ) + .arg( QString::fromStdString( name ) ); + } + } + + totalMemory += totalMemoryForCase; + + if ( totalMemoryForCase > 0 ) + { + details += + QString( "%1 - %2 MB\n" ).arg( eclipseCase->caseUserDescription() ).arg( totalMemoryForCase / 1024.0 / 1024.0, 0, 'f', 2 ); + + details += caseReport; + } + } + } + } + + QString summary = QString( "Total memory used: %1 MB\n\n" ).arg( totalMemory / 1024.0 / 1024.0, 0, 'f', 2 ); + return std::make_pair( summary, details ); } diff --git a/ApplicationLibCode/Application/RiaMemoryCleanup.h b/ApplicationLibCode/Application/RiaMemoryCleanup.h index 15ee6d1538..cc154fb982 100644 --- a/ApplicationLibCode/Application/RiaMemoryCleanup.h +++ b/ApplicationLibCode/Application/RiaMemoryCleanup.h @@ -39,6 +39,8 @@ public: void setPropertiesFromView( Rim3dView* view ); void clearSelectedResultsFromMemory(); + static void showMemoryReport(); + protected: void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; @@ -52,10 +54,13 @@ private: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; + static std::pair createMemoryReport(); + private: caf::PdmPtrField m_case; caf::PdmField> m_resultsToDelete; std::vector m_geomResultAddresses; std::vector m_eclipseResultAddresses; caf::PdmField m_performDelete; + caf::PdmField m_showMemoryReport; }; diff --git a/ApplicationLibCode/Commands/ApplicationCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/ApplicationCommands/CMakeLists_files.cmake index 9a641063bc..83cdb817e6 100644 --- a/ApplicationLibCode/Commands/ApplicationCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/ApplicationCommands/CMakeLists_files.cmake @@ -20,6 +20,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicShowClassNamesFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicShowPlotDataCtxFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicOpenInTextEditorFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicShowMemoryReportFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -44,6 +45,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicShowClassNamesFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicShowPlotDataCtxFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicOpenInTextEditorFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicShowMemoryReportFeature.cpp ) list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/Commands/ApplicationCommands/RicShowMemoryReportFeature.cpp b/ApplicationLibCode/Commands/ApplicationCommands/RicShowMemoryReportFeature.cpp new file mode 100644 index 0000000000..6581677cb5 --- /dev/null +++ b/ApplicationLibCode/Commands/ApplicationCommands/RicShowMemoryReportFeature.cpp @@ -0,0 +1,41 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicShowMemoryReportFeature.h" + +#include "RiaMemoryCleanup.h" + +#include + +CAF_CMD_SOURCE_INIT( RicShowMemoryReportFeature, "RicShowMemoryReportFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicShowMemoryReportFeature::onActionTriggered( bool isChecked ) +{ + RiaMemoryCleanup::showMemoryReport(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicShowMemoryReportFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Memory Report" ); +} diff --git a/ApplicationLibCode/Commands/ApplicationCommands/RicShowMemoryReportFeature.h b/ApplicationLibCode/Commands/ApplicationCommands/RicShowMemoryReportFeature.h new file mode 100644 index 0000000000..e61b201cb5 --- /dev/null +++ b/ApplicationLibCode/Commands/ApplicationCommands/RicShowMemoryReportFeature.h @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicShowMemoryReportFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +private: + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 9f4ab991a0..2752a01fc9 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -216,6 +216,24 @@ void RigCaseCellResultsData::mobileVolumeWeightedMean( const RigEclipseResultAdd statistics( resVarAddr )->mobileVolumeWeightedMean( timeStepIndex, meanValue ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map RigCaseCellResultsData::resultValueCount() const +{ + std::map memoryUse; + + for ( size_t i = 0; i < m_cellScalarResults.size(); i++ ) + { + if ( allocatedValueCount( i ) > 0 ) + { + memoryUse[m_resultInfos[i].resultName().toStdString()] = allocatedValueCount( i ); + } + } + + return memoryUse; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2838,22 +2856,25 @@ RigAllanDiagramData* RigCaseCellResultsData::allanDiagramData() //-------------------------------------------------------------------------------------------------- bool RigCaseCellResultsData::isDataPresent( size_t scalarResultIndex ) const { - if ( scalarResultIndex >= resultCount() ) + return allocatedValueCount( scalarResultIndex ) > 0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RigCaseCellResultsData::allocatedValueCount( size_t scalarResultIndex ) const +{ + if ( scalarResultIndex >= resultCount() ) return 0; + + const std::vector>& valuesAllTimeSteps = m_cellScalarResults[scalarResultIndex]; + + size_t valueCount = 0; + for ( const auto& values : valuesAllTimeSteps ) { - return false; + valueCount += values.size(); } - const std::vector>& data = m_cellScalarResults[scalarResultIndex]; - - for ( size_t tsIdx = 0; tsIdx < data.size(); ++tsIdx ) - { - if ( !data[tsIdx].empty() ) - { - return true; - } - } - - return false; + return valueCount; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.h index d86abf5a26..227ea91534 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationLibCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -99,6 +99,9 @@ public: void mobileVolumeWeightedMean( const RigEclipseResultAddress& resVarAddr, double& meanValue ); void mobileVolumeWeightedMean( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex, double& meanValue ); + // Return the number of double values allocated for each result + std::map resultValueCount() const; + // Access meta-information about the results size_t timeStepCount( const RigEclipseResultAddress& resVarAddr ) const; @@ -199,7 +202,8 @@ private: void computeFaultDistance(); void computeNncsCells(); - bool isDataPresent( size_t scalarResultIndex ) const; + bool isDataPresent( size_t scalarResultIndex ) const; + size_t allocatedValueCount( size_t scalarResultIndex ) const; void assignValuesToTemporaryLgrs( const QString& resultName, std::vector& values ); diff --git a/ApplicationLibCode/UserInterface/RiuMainWindow.cpp b/ApplicationLibCode/UserInterface/RiuMainWindow.cpp index bd95f4d6a2..4775c2799d 100644 --- a/ApplicationLibCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationLibCode/UserInterface/RiuMainWindow.cpp @@ -672,6 +672,7 @@ void RiuMainWindow::createToolBars() toolbar->addAction( cmdFeatureMgr->action( "RicRunCommandFileFeature" ) ); toolbar->addAction( cmdFeatureMgr->action( "RicExecuteLastUsedScriptFeature" ) ); toolbar->addAction( cmdFeatureMgr->action( "RicExportCompletionsForVisibleWellPathsFeature" ) ); + toolbar->addAction( cmdFeatureMgr->action( "RicShowMemoryReportFeature" ) ); } // Create animation toolbar