Skip to content

Commit 7c32f33

Browse files
jmyrchaJulian Myrcha
andauthored
o2-eve: fix memory leak in screenshots (#9463)
* o2-eve: fix memory leak in screenshots * software version updated, added log messages Co-authored-by: Julian Myrcha <jmyrcha@cern.ch>
1 parent f2d6a89 commit 7c32f33

6 files changed

Lines changed: 73 additions & 15 deletions

File tree

EventVisualisation/Base/include/EventVisualisationBase/ConfigurationManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace o2
2424
namespace event_visualisation
2525
{
2626
/// Version of the software
27-
const static std::string o2_eve_version = "1.36";
27+
const static std::string o2_eve_version = "1.37";
2828

2929
/// Configuration Manager allows an easy access to the config file.
3030
///

EventVisualisation/Base/include/EventVisualisationBase/DirectoryLoader.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,14 @@ namespace event_visualisation
2626

2727
class DirectoryLoader
2828
{
29+
private:
30+
static int getNumberOfFiles(std::string& path, std::string& ext);
31+
static std::string getLatestFile(std::string& path, std::string& ext);
32+
2933
public:
3034
static std::deque<std::string> load(const std::string& path, const std::string& marker, const std::string& ext);
3135
static void reduceNumberOfFiles(const std::string& path, const std::deque<std::string>& files, std::size_t filesInFolder);
36+
static void removeOldestFiles(std::string& path, std::string ext, int remaining);
3237
};
3338

3439
} // namespace event_visualisation

EventVisualisation/Base/src/DirectoryLoader.cxx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "EventVisualisationBase/DirectoryLoader.h"
1717
#include <filesystem>
1818
#include <algorithm>
19+
#include <climits>
20+
#include <FairLogger.h>
1921

2022
using namespace std;
2123
using namespace o2::event_visualisation;
@@ -47,3 +49,46 @@ void DirectoryLoader::reduceNumberOfFiles(const std::string& path, const std::de
4749
std::remove((path + "/" + files[i]).c_str()); // delete file
4850
}
4951
}
52+
53+
template <typename TP>
54+
std::time_t to_time_t(TP tp)
55+
{
56+
using namespace std::chrono;
57+
auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now() + system_clock::now());
58+
return system_clock::to_time_t(sctp);
59+
}
60+
61+
int DirectoryLoader::getNumberOfFiles(std::string& path, std::string& ext)
62+
{
63+
int res = 0;
64+
for (const auto& entry : std::filesystem::directory_iterator(path)) {
65+
if (entry.path().extension() == ext) {
66+
res++;
67+
}
68+
}
69+
return res;
70+
}
71+
std::string DirectoryLoader::getLatestFile(std::string& path, std::string& ext)
72+
{
73+
std::string oldest_file_name = "";
74+
std::time_t oldest_file_time = LONG_MAX;
75+
for (const auto& entry : std::filesystem::directory_iterator(path)) {
76+
if (entry.path().extension() == ext) {
77+
auto file_time = entry.last_write_time();
78+
std::time_t tt = to_time_t(file_time);
79+
if (tt < oldest_file_time) {
80+
oldest_file_time = tt;
81+
oldest_file_name = entry.path().filename();
82+
}
83+
}
84+
}
85+
return oldest_file_name;
86+
}
87+
88+
void DirectoryLoader::removeOldestFiles(std::string& path, std::string ext, int remaining)
89+
{
90+
while (getNumberOfFiles(path, ext) > remaining) {
91+
LOG(info) << "removing oldest file in folder: " << path << " : " << getLatestFile(path, ext);
92+
filesystem::remove(path + "/" + getLatestFile(path, ext));
93+
}
94+
}

EventVisualisation/View/include/EventVisualisationView/EventManagerFrame.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class EventManagerFrame : public TGMainFrame
5555
TTimer* mTimer; // Timer for automatic event loading
5656
bool mTimerRunning;
5757
bool inTick = false;
58+
long memoryUsedInfo = 0L; // used to track memory leaks
5859
DisplayMode mDisplayMode = EventManagerFrame::OnlineMode;
5960
bool setInTick(); // try set inTick, return true if set, false if already set
6061
void clearInTick(); // safely clears inTick

EventVisualisation/View/src/EventManagerFrame.cxx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ void EventManagerFrame::checkMemory()
301301
fclose(f);
302302
if (success == 1) { // properly readed
303303
size = 4 * size / 1024; // in MB
304+
this->memoryUsedInfo = size;
304305
LOG(info) << "Memory used: " << size << " memory allowed: " << memoryLimit;
305306
if (size > memoryLimit) {
306307
LOG(error) << "Memory used: " << size << " exceeds memory allowed: "
@@ -325,11 +326,12 @@ void EventManagerFrame::createOutreachScreenshot()
325326
}
326327
fileName = imageFolder + "/" + fileName.substr(0, fileName.find_last_of('.')) + ".png";
327328
if (!std::filesystem::is_regular_file(fileName)) {
329+
DirectoryLoader::removeOldestFiles(imageFolder, ".png", 10);
330+
LOG(info) << "Outreach screenshot: " << fileName;
328331
Screenshot::perform(fileName, this->mEventManager->getDataSource()->getDetectorsMask(),
329332
this->mEventManager->getDataSource()->getRunNumber(),
330333
this->mEventManager->getDataSource()->getFirstTForbit(),
331334
this->mEventManager->getDataSource()->getCollisionTime());
332-
DirectoryLoader::reduceNumberOfFiles(imageFolder, DirectoryLoader::load(imageFolder, "_", ".png"), 10);
333335
}
334336
// LOG(info) << mEventManager->getInstance().getDataSource()->getEventName();
335337
}

EventVisualisation/View/src/Screenshot.cxx

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,9 @@ void Screenshot::perform(std::string fileName, o2::detectors::DetID::mask_t dete
151151
std::ostringstream filepath;
152152
filepath << outDirectory << "/Screenshot_" << time_str << ".png";
153153

154-
TASImage image(width, height);
155-
image.FillRectangle(backgroundColorHex.c_str(), 0, 0, width, height);
154+
TASImage* image = new TASImage(width, height);
155+
156+
image->FillRectangle(backgroundColorHex.c_str(), 0, 0, width, height);
156157

157158
const auto annotationStateTop = MultiView::getInstance()->getAnnotationTop()->GetState();
158159
const auto annotationStateBottom = MultiView::getInstance()->getAnnotationBottom()->GetState();
@@ -165,22 +166,25 @@ void Screenshot::perform(std::string fileName, o2::detectors::DetID::mask_t dete
165166
MultiView::getInstance()->getAnnotationBottom()->SetState(annotationStateBottom);
166167

167168
scaledImage = ScaleImage((TASImage*)view3dImage, width * 0.65, height * 0.95, backgroundColorHex);
169+
delete view3dImage;
168170
if (scaledImage) {
169-
CopyImage(&image, scaledImage, width * 0.015, height * 0.025, 0, 0, scaledImage->GetWidth(), scaledImage->GetHeight());
171+
CopyImage(image, scaledImage, width * 0.015, height * 0.025, 0, 0, scaledImage->GetWidth(), scaledImage->GetHeight());
170172
delete scaledImage;
171173
}
172174

173175
TImage* viewRphiImage = MultiView::getInstance()->getView(MultiView::EViews::ViewRphi)->GetGLViewer()->GetPictureUsingBB();
174176
scaledImage = ScaleImage((TASImage*)viewRphiImage, width * 0.3, height * 0.45, backgroundColorHex);
177+
delete viewRphiImage;
175178
if (scaledImage) {
176-
CopyImage(&image, scaledImage, width * 0.68, height * 0.025, 0, 0, scaledImage->GetWidth(), scaledImage->GetHeight());
179+
CopyImage(image, scaledImage, width * 0.68, height * 0.025, 0, 0, scaledImage->GetWidth(), scaledImage->GetHeight());
177180
delete scaledImage;
178181
}
179182

180183
TImage* viewZYImage = MultiView::getInstance()->getView(MultiView::EViews::ViewZY)->GetGLViewer()->GetPictureUsingBB();
181184
scaledImage = ScaleImage((TASImage*)viewZYImage, width * 0.3, height * 0.45, backgroundColorHex);
185+
delete viewZYImage;
182186
if (scaledImage) {
183-
CopyImage(&image, scaledImage, width * 0.68, height * 0.525, 0, 0, scaledImage->GetWidth(), scaledImage->GetHeight());
187+
CopyImage(image, scaledImage, width * 0.68, height * 0.525, 0, 0, scaledImage->GetWidth(), scaledImage->GetHeight());
184188
delete scaledImage;
185189
}
186190

@@ -190,9 +194,9 @@ void Screenshot::perform(std::string fileName, o2::detectors::DetID::mask_t dete
190194
if (aliceLogo->IsValid()) {
191195
double ratio = 1434. / 1939.;
192196
aliceLogo->Scale(0.08 * width, 0.08 * width / ratio);
193-
image.Merge(aliceLogo, "alphablend", 20, 20);
194-
delete aliceLogo;
197+
image->Merge(aliceLogo, "alphablend", 20, 20);
195198
}
199+
delete aliceLogo;
196200
}
197201

198202
int fontSize = 0.015 * height;
@@ -208,14 +212,14 @@ void Screenshot::perform(std::string fileName, o2::detectors::DetID::mask_t dete
208212
int o2LogoY = 0.01 * width;
209213
int o2LogoSize = 0.04 * width;
210214
o2Logo->Scale(o2LogoSize, o2LogoSize / ratio);
211-
image.Merge(o2Logo, "alphablend", o2LogoX, height - o2LogoSize / ratio - o2LogoY);
215+
image->Merge(o2Logo, "alphablend", o2LogoX, height - o2LogoSize / ratio - o2LogoY);
212216
textX = o2LogoX + o2LogoSize + o2LogoX;
213217
textY = height - o2LogoSize / ratio - o2LogoY;
214-
delete o2Logo;
215218
} else {
216219
textX = 229;
217220
textY = 1926;
218221
}
222+
delete o2Logo;
219223
}
220224

221225
auto detectorsString = detectors::DetID::getNames(detectorsMask);
@@ -228,14 +232,15 @@ void Screenshot::perform(std::string fileName, o2::detectors::DetID::mask_t dete
228232
lines.push_back((std::string)settings.GetValue("screenshot.message.line.3", TString::Format("Detectors: %s", detectorsString.c_str())));
229233
}
230234

231-
image.BeginPaint();
235+
image->BeginPaint();
232236

233237
for (int i = 0; i < 4; i++) {
234-
image.DrawText(textX, textY + i * textLineHeight, lines[i].c_str(), fontSize, "#BBBBBB", "FreeSansBold.otf");
238+
image->DrawText(textX, textY + i * textLineHeight, lines[i].c_str(), fontSize, "#BBBBBB", "FreeSansBold.otf");
235239
}
236-
image.EndPaint();
240+
image->EndPaint();
237241

238-
image.WriteImage(fileName.c_str(), TImage::kPng);
242+
image->WriteImage(fileName.c_str(), TImage::kPng);
243+
delete image;
239244
}
240245

241246
} // namespace event_visualisation

0 commit comments

Comments
 (0)