Skip to content
Snippets Groups Projects
Commit c77b5704 authored by Felix Weiglhofer's avatar Felix Weiglhofer
Browse files

algo: Add MemoryLogger to log memory usage of process.

parent ec494a7b
No related branches found
No related tags found
1 merge request!1756online: Log memory usage of process.
Pipeline #28854 passed
...@@ -74,6 +74,8 @@ set(SRCS ...@@ -74,6 +74,8 @@ set(SRCS
base/Options.cxx base/Options.cxx
base/MainConfig.cxx base/MainConfig.cxx
base/RecoParams.cxx base/RecoParams.cxx
base/System.cxx
base/util/MemoryLogger.cxx
base/util/StlUtils.cxx base/util/StlUtils.cxx
base/util/EnumDict.cxx base/util/EnumDict.cxx
base/util/TimingsFormat.cxx base/util/TimingsFormat.cxx
...@@ -248,6 +250,7 @@ install( ...@@ -248,6 +250,7 @@ install(
base/Options.h base/Options.h
base/RecoParams.h base/RecoParams.h
base/SubChain.h base/SubChain.h
base/System.h
base/PartitionedVector.h base/PartitionedVector.h
base/PartitionedSpan.h base/PartitionedSpan.h
global/Reco.h global/Reco.h
......
/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#include "System.h"
#include <cstdio>
#ifdef __linux__
#include <sys/resource.h>
#include <unistd.h>
#endif
size_t cbm::algo::GetCurrentRSS()
{
// Implementation copied from https://stackoverflow.com/a/14927379
#ifndef __linux__
return 0;
#else
unsigned long rss = 0L;
FILE* fp = nullptr;
if ((fp = fopen("/proc/self/statm", "r")) == nullptr) {
return size_t(0L); /* Can't open? */
}
if (fscanf(fp, "%*s%lu", &rss) != 1) {
fclose(fp);
return size_t(0L); /* Can't read? */
}
fclose(fp);
return size_t(rss) * size_t(sysconf(_SC_PAGESIZE));
#endif
}
size_t cbm::algo::GetPeakRSS()
{
// Implementation copied from https://stackoverflow.com/a/14927379
#ifndef __linux__
return 0;
#else
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return size_t(rusage.ru_maxrss * 1024L);
#endif
}
/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#pragma once
#include <cstddef>
/**
* @file System.h
* @brief System functions
**/
namespace cbm::algo
{
/**
* @brief Get the current resident set size (pyhysical memory usage) of the process
* @return The current resident set size in bytes
* @note Returns zero if the value cannot be determined
**/
size_t GetCurrentRSS();
/**
* @brief Get the peak resident set size (pyhysical memory usage) of the process
* @return The peak resident set size in bytes
* @note Returns zero if the value cannot be determined
**/
size_t GetPeakRSS();
} // namespace cbm::algo
/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#include "MemoryLogger.h"
#include "System.h"
#include <log.hpp>
using namespace cbm::algo;
template<typename T>
T MemoryLogger::BytesToMB(T bytes) const
{
return bytes / (1024 * 1024);
}
void MemoryLogger::Log()
{
size_t currentRSS = GetCurrentRSS();
size_t peakRSS = GetPeakRSS();
ptrdiff_t deltaRSS = currentRSS - mLastRSS;
float deltaPercent = 100.0f * deltaRSS / currentRSS;
L_(debug) << "Current memory usage: " << BytesToMB(currentRSS) << "MB (delta " << BytesToMB(deltaRSS) << "MB / "
<< deltaPercent << "%)"
<< ", peak: " << BytesToMB(peakRSS) << "MB";
mLastRSS = currentRSS;
}
/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#pragma once
#include <cstddef>
/**
* @file MemoryLogger.h
* @brief Memory logging
**/
namespace cbm::algo
{
/**
* @brief Track the memory usage of the process and write it to the log
**/
class MemoryLogger {
public:
/**
* @brief Constructor
**/
MemoryLogger() = default;
/**
* @brief Destructor
**/
~MemoryLogger() = default;
/**
* @brief Log the current memory usage
**/
void Log();
private:
size_t mLastRSS = 0;
// Convert bytes to MB
// Template to allow for different integer types
template<typename T>
T BytesToMB(T bytes) const;
};
} // namespace cbm::algo
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
#include "Reco.h" #include "Reco.h"
#include "RecoResultsInputArchive.h" #include "RecoResultsInputArchive.h"
#include "RecoResultsOutputArchive.h" #include "RecoResultsOutputArchive.h"
#include "System.h"
#include "compat/OpenMP.h" #include "compat/OpenMP.h"
#include "gpu/DeviceImage.h" #include "gpu/DeviceImage.h"
#include "util/MemoryLogger.h"
#include <TimesliceAutoSource.hpp> #include <TimesliceAutoSource.hpp>
...@@ -160,6 +162,7 @@ int main(int argc, char** argv) ...@@ -160,6 +162,7 @@ int main(int argc, char** argv)
if (dumpArchive(opts)) return 0; if (dumpArchive(opts)) return 0;
Reco reco; Reco reco;
MemoryLogger memoryLogger;
auto startProcessing = std::chrono::high_resolution_clock::now(); auto startProcessing = std::chrono::high_resolution_clock::now();
reco.Init(opts); reco.Init(opts);
...@@ -198,6 +201,11 @@ int main(int argc, char** argv) ...@@ -198,6 +201,11 @@ int main(int argc, char** argv)
L_(error) << "Caught ProcessingError while processing timeslice " << tsIdx << ": " << e.what(); L_(error) << "Caught ProcessingError while processing timeslice " << tsIdx << ": " << e.what();
} }
// Release memory after each timeslice and log memory usage
// This is useful to detect memory leaks as the memory usage should be constant between timeslices
ts.reset();
memoryLogger.Log();
tsIdx++; tsIdx++;
if (num_ts > 0 && tsIdx >= num_ts) break; if (num_ts > 0 && tsIdx >= num_ts) break;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment