Skip to content

Commit 2a5f542

Browse files
committed
Merge CMSSW_15_1_X into CMSSW_15_1_FASTPU_X.
2 parents 87689c9 + e04f43e commit 2a5f542

File tree

7 files changed

+241
-0
lines changed

7 files changed

+241
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef FWCore_AbstractServices_IntrusiveMonitorBase_h
2+
#define FWCore_AbstractServices_IntrusiveMonitorBase_h
3+
4+
#include <string_view>
5+
6+
namespace edm {
7+
class IntrusiveMonitorBase {
8+
public:
9+
IntrusiveMonitorBase() = default;
10+
IntrusiveMonitorBase(IntrusiveMonitorBase const&) = delete;
11+
IntrusiveMonitorBase& operator=(IntrusiveMonitorBase const&) = delete;
12+
IntrusiveMonitorBase(IntrusiveMonitorBase&&) = delete;
13+
IntrusiveMonitorBase& operator=(IntrusiveMonitorBase&&) = delete;
14+
virtual ~IntrusiveMonitorBase();
15+
16+
class Guard {
17+
public:
18+
Guard(IntrusiveMonitorBase& mon, std::string_view name) : monitor_(mon), name_(name) { monitor_.start(); }
19+
Guard(Guard const&) = delete;
20+
Guard& operator=(Guard const&) = delete;
21+
Guard(Guard&&) = delete;
22+
Guard& operator=(Guard&&) = delete;
23+
24+
~Guard() { monitor_.stop(name_); }
25+
26+
private:
27+
IntrusiveMonitorBase& monitor_;
28+
std::string_view name_;
29+
};
30+
31+
Guard startMonitoring(std::string_view name) { return Guard(*this, name); }
32+
33+
private:
34+
virtual void start() = 0;
35+
virtual void stop(std::string_view name) = 0;
36+
};
37+
} // namespace edm
38+
39+
#endif
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "FWCore/AbstractServices/interface/IntrusiveMonitorBase.h"
2+
3+
namespace edm {
4+
IntrusiveMonitorBase::~IntrusiveMonitorBase() = default;
5+
}

IOPool/TFileAdaptor/src/TStorageFactoryFile.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,13 @@ Bool_t TStorageFactoryFile::ReadBuffer(char *buf, Int_t len) {
303303
GetRelOffset(),
304304
GetSize());
305305
}
306+
307+
// Update ROOT's statistics
308+
fBytesRead += n;
309+
fgBytesRead += n;
310+
fReadCalls++;
311+
fgReadCalls++;
312+
306313
return n ? kFALSE : kTRUE;
307314
}
308315

@@ -410,6 +417,12 @@ Bool_t TStorageFactoryFile::ReadBuffersSync(char *buf, Long64_t *pos, Int_t *len
410417
xstats.tick(io_buffer_used);
411418
repacker.unpack(current_buffer);
412419

420+
// Update ROOT's statistics
421+
fBytesRead += result;
422+
fgBytesRead += result;
423+
fReadCalls++;
424+
fgReadCalls++;
425+
413426
// Update the location of the unused part of the input buffer.
414427
remaining_buffer_size -= real_bytes_processed;
415428
current_buffer += real_bytes_processed;

PerfTools/AllocMonitor/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,36 @@ service in the configuration. The parameters are
132132
The beginning of the file contains a description of the structure and contents of the file. The file can be analyzed with the helper script `edmModuleEventAllocMonitorAnalyze.py`. The script can be used to find modules where the memory is being retained between Events as well as modules where the memory appears to be growing Event to Event. Use `--help` with the script for a full description.
133133

134134
This service is multi-thread safe.
135+
136+
137+
### IntrusiveAllocMonitor
138+
139+
This service registers a monitor when the service is created (after python parsing is finished, but before any modules have been loaded into cmsRun). The user can then start the monitoring in their code as shown in the example below. The monitoring stops, in an RAII fashion, at the end of the scope and the results of the memory operations are printed with the [MessageLogger](../../FWCore/MessageService/Readme.md) with an `IntrusiveAllocMonitor` message category.
140+
141+
```cpp
142+
#include "FWCore/AbstractServices/interface/IntrusiveMonitorBase.h"
143+
#include "FWCore/ServiceRegistry/interface/Service.h"
144+
145+
146+
void someFunction() {
147+
{
148+
edm::Service<IntrusiveMonitorBase> monitor;
149+
auto guard = monitor.startMeasurement("Measurement description");
150+
151+
// more code doing memory allocations
152+
}
153+
}
154+
155+
```
156+
157+
The message will print
158+
| Field | Description |
159+
|-------|-------------|
160+
| `requested` | Total number of requested bytes |
161+
| `added ` | Total number of bytes added (can be more than `requested`) |
162+
| `max alloc` | Largest single memory allocation |
163+
| `peak` | Maximum amount of allocated memory at any given moment |
164+
| `nAlloc` | Number of memory allocations |
165+
| `nDealloc` | Number of memory deallocations |
166+
167+
This service is multi-thread safe, and concurrent measurements can be done in different threads. Nested measurements are not supported (i.e. one thread can be doing only one measurement at a time), and neither are measurements started in one thread and ended in different thread.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#include "FWCore/AbstractServices/interface/IntrusiveMonitorBase.h"
2+
#include "FWCore/MessageLogger/interface/MessageLogger.h"
3+
#include "FWCore/ServiceRegistry/interface/ServiceMaker.h"
4+
5+
#include "PerfTools/AllocMonitor/interface/AllocMonitorBase.h"
6+
#include "PerfTools/AllocMonitor/interface/AllocMonitorRegistry.h"
7+
8+
#include "ThreadAllocInfo.h"
9+
#include "ThreadTracker.h"
10+
11+
namespace {
12+
using namespace edm::service::moduleAlloc;
13+
class MonitorAdaptor : public cms::perftools::AllocMonitorBase {
14+
public:
15+
static void startOnThread() { threadAllocInfo().reset(); }
16+
static ThreadAllocInfo const& stopOnThread() {
17+
auto& t = threadAllocInfo();
18+
if (not t.active_) {
19+
t.reset();
20+
} else {
21+
t.deactivate();
22+
}
23+
return t;
24+
}
25+
26+
static ThreadAllocInfo& threadAllocInfo() {
27+
using namespace cms::perftools::allocMon;
28+
static ThreadAllocInfo s_info[ThreadTracker::kTotalEntries];
29+
return s_info[ThreadTracker::instance().thread_index()];
30+
}
31+
32+
private:
33+
void allocCalled(size_t iRequested, size_t iActual, void const*) final {
34+
auto& allocInfo = threadAllocInfo();
35+
if (not allocInfo.active_) {
36+
return;
37+
}
38+
allocInfo.nAllocations_ += 1;
39+
allocInfo.requested_ += iRequested;
40+
41+
if (allocInfo.maxSingleAlloc_ < iRequested) {
42+
allocInfo.maxSingleAlloc_ = iRequested;
43+
}
44+
45+
allocInfo.presentActual_ += iActual;
46+
if (allocInfo.presentActual_ > static_cast<long long>(allocInfo.maxActual_)) {
47+
allocInfo.maxActual_ = allocInfo.presentActual_;
48+
}
49+
}
50+
void deallocCalled(size_t iActual, void const*) final {
51+
auto& allocInfo = threadAllocInfo();
52+
if (not allocInfo.active_) {
53+
return;
54+
}
55+
56+
allocInfo.nDeallocations_ += 1;
57+
allocInfo.presentActual_ -= iActual;
58+
if (allocInfo.presentActual_ < 0) {
59+
if (allocInfo.minActual_ == 0 or allocInfo.minActual_ > allocInfo.presentActual_) {
60+
allocInfo.minActual_ = allocInfo.presentActual_;
61+
}
62+
}
63+
}
64+
};
65+
} // namespace
66+
67+
class IntrusiveAllocMonitor : public edm::IntrusiveMonitorBase {
68+
public:
69+
IntrusiveAllocMonitor() {
70+
(void)cms::perftools::AllocMonitorRegistry::instance().createAndRegisterMonitor<MonitorAdaptor>();
71+
};
72+
~IntrusiveAllocMonitor() override = default;
73+
74+
void start() final { MonitorAdaptor::startOnThread(); }
75+
void stop(std::string_view name) final {
76+
MonitorAdaptor::stopOnThread();
77+
auto& info = MonitorAdaptor::threadAllocInfo();
78+
edm::LogSystem("IntrusiveAllocMonitor")
79+
.format("{}: requested {} added {} max alloc {} peak {} nAlloc {} nDealloc {}",
80+
name,
81+
info.requested_,
82+
info.presentActual_,
83+
info.maxSingleAlloc_,
84+
info.maxActual_,
85+
info.nAllocations_,
86+
info.nDeallocations_);
87+
}
88+
};
89+
90+
typedef edm::serviceregistry::NoArgsMaker<edm::IntrusiveMonitorBase, IntrusiveAllocMonitor> IntrusiveAllocMonitorMaker;
91+
DEFINE_FWK_SERVICE_MAKER(IntrusiveAllocMonitor, IntrusiveAllocMonitorMaker);

PerfTools/AllocMonitor/test/BuildFile.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,18 @@
2323
<flags CXXFLAGS="-O0"/>
2424
</bin>
2525
<test name="TestPerfToolsModuleAllocMonitor" command="runModuleAlloc.sh"/>
26+
27+
<!-- can't be part of the catch2 tests above because of ASAN exclusion -->
28+
<bin file="test_intrusiveAllocMonitor.cc" name="testIntrusiveAllocMonitor">
29+
<use name="FWCore/AbstractServices"/>
30+
<use name="FWCore/ParameterSet"/>
31+
<use name="FWCore/ParameterSetReader"/>
32+
<use name="FWCore/PluginManager"/>
33+
<use name="FWCore/ServiceRegistry"/>
34+
<use name="PerfTools/AllocMonitor"/>
35+
<use name="PerfTools/AllocMonitorPreload"/>
36+
</bin>
37+
<test name="testIntrusiveAllocMonitorOutput" command="testIntrusiveAllocMonitor 2>&amp;1 | grep -q 'Vector fill: requested'">
38+
<flags PRE_TEST="testIntrusiveAllocMonitor"/>
39+
</test>
2640
</ifrelease>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "FWCore/AbstractServices/interface/IntrusiveMonitorBase.h"
2+
#include "FWCore/MessageLogger/interface/MessageLogger.h"
3+
#include "FWCore/ParameterSet/interface/ParameterSet.h"
4+
#include "FWCore/ParameterSetReader/interface/ParameterSetReader.h"
5+
#include "FWCore/PluginManager/interface/PluginManager.h"
6+
#include "FWCore/PluginManager/interface/standard.h"
7+
#include "FWCore/ServiceRegistry/interface/Service.h"
8+
#include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
9+
#include "FWCore/ServiceRegistry/interface/ServiceToken.h"
10+
11+
#include <cassert>
12+
#include <vector>
13+
14+
int main() {
15+
edmplugin::PluginManager::configure(edmplugin::standard::config());
16+
17+
std::string const config = R"_(
18+
import FWCore.ParameterSet.Config as cms
19+
process = cms.Process('Test')
20+
process.add_(cms.Service('IntrusiveAllocMonitor'))
21+
)_";
22+
std::unique_ptr<edm::ParameterSet> params;
23+
edm::makeParameterSets(config, params);
24+
auto token = edm::ServiceToken(edm::ServiceRegistry::createServicesFromConfig(std::move(params)));
25+
edm::ServiceRegistry::Operate operate(token);
26+
27+
edm::Service<edm::IntrusiveMonitorBase> imb;
28+
assert(imb.isAvailable());
29+
30+
std::vector<int> vec;
31+
{
32+
auto guard = imb->startMonitoring("Vector fill");
33+
for (int i = 0; i < 10000; ++i) {
34+
vec.push_back(i * 2 - 1);
35+
}
36+
37+
int sum = 0;
38+
for (int a : vec) {
39+
sum += a;
40+
}
41+
42+
edm::LogPrint("Test").format("Sum {}", sum);
43+
}
44+
45+
return 0;
46+
}

0 commit comments

Comments
 (0)