Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
JsonMessagePassingProfilingService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* JsonMessagePassingProfilingService.cc (C) 2000-2022 */
9/* */
10/* Performance information for "message passing" in JSON format */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/std/JsonMessagePassingProfilingService.h"
15
16#include <algorithm>
17#include <string>
18
20#include "arcane/core/CommonVariables.h"
21#include "arcane/core/ITimeLoopMng.h"
22#include "arcane/core/IParallelMng.h"
23#include "arcane/core/IEntryPoint.h"
24
25#include "arcane/parallel/IStat.h"
26#include "arcane/utils/JSONWriter.h"
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31namespace Arcane
32{
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
38 ServiceProperty("JsonMessagePassingProfiling", ST_SubDomain),
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44JsonMessagePassingProfilingService::
45JsonMessagePassingProfilingService(const ServiceBuildInfo& sbi)
46: AbstractService(sbi)
47, m_sub_domain(sbi.subDomain())
48, m_json_writer(nullptr)
49, m_impl_name("JsonMessagePassingProfiling")
50{
51}
52
53/*---------------------------------------------------------------------------*/
54/*---------------------------------------------------------------------------*/
55
56JsonMessagePassingProfilingService::
57~JsonMessagePassingProfilingService()
58{
59 if (m_json_writer)
60 delete m_json_writer;
61}
62
63/*---------------------------------------------------------------------------*/
64/*---------------------------------------------------------------------------*/
65
66void JsonMessagePassingProfilingService::
67startProfiling()
68{
69 // creation of the json writer
70 if (!m_json_writer) {
71 m_json_writer = new JSONWriter(JSONWriter::FormatFlags::None);
72 m_json_writer->beginObject();
73 }
74
75 // When starting profiling, we begin observing the timeLoopMng events
76 m_observer.addObserver(this, &JsonMessagePassingProfilingService::_updateFromBeginEntryPointEvt,
77 m_sub_domain->timeLoopMng()->observable(eTimeLoopEventType::BeginEntryPoint));
78 m_observer.addObserver(this, &JsonMessagePassingProfilingService::_updateFromEndEntryPointEvt,
79 m_sub_domain->timeLoopMng()->observable(eTimeLoopEventType::EndEntryPoint));
80 m_observer.addObserver(this, &JsonMessagePassingProfilingService::_updateFromBeginIterationEvt,
81 m_sub_domain->timeLoopMng()->observable(eTimeLoopEventType::BeginIteration));
82 m_observer.addObserver(this, &JsonMessagePassingProfilingService::_updateFromEndIterationEvt,
83 m_sub_domain->timeLoopMng()->observable(eTimeLoopEventType::EndIteration));
84}
85
86/*---------------------------------------------------------------------------*/
87/*---------------------------------------------------------------------------*/
88
89void JsonMessagePassingProfilingService::
90stopProfiling()
91{
92 // Stop observations
93 m_observer.detachAll();
94 // We flush the information
95 if (m_json_writer) {
96 _dumpCurrentIterationInJSON();
97 m_json_writer->endObject();
98 }
99}
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103void JsonMessagePassingProfilingService::
104printInfos(std::ostream& output)
105{
106 output << m_json_writer->getBuffer();
107}
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111String JsonMessagePassingProfilingService::
112implName()
113{
114 return m_impl_name;
115}
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
120void JsonMessagePassingProfilingService::
121_dumpCurrentIterationInJSON()
122{
123 if (m_ep_mpstat_col.empty())
124 return;
125
126 // Iteration number (offset by one because the counter increments before the notification)
127 JSONWriter::Object obj_it(*m_json_writer,
128 String::fromNumber(m_sub_domain->commonVariables().globalIteration() - 1));
129 // Per entry point
130 for (const auto& ep_mpstat : m_ep_mpstat_col) {
131 // Alias for the message passing stats for this entry point
132 const auto& stats_(ep_mpstat.second.stats());
133 // We write the entry point only if there is a non-zero message passing stat
134 if (std::any_of(stats_.cbegin(), stats_.cend(), [&](const Arccore::MessagePassing::OneStat& os) { return static_cast<bool>(os.nbMessage()); })) {
135 // Entry point name
136 JSONWriter::Object obj_ep(*m_json_writer, ep_mpstat.first);
137 // Per message passing stat
138 for (const auto& mpstat : stats_) {
139 // Message passing stats if they exist
140 if (mpstat.nbMessage())
141 Parallel::dumpJSON(*m_json_writer, mpstat, false);
142 }
143 }
144 }
145}
146
147/*---------------------------------------------------------------------------*/
148/*---------------------------------------------------------------------------*/
149
150void JsonMessagePassingProfilingService::
151_updateFromBeginEntryPointEvt()
152{
153 // When entering the entry point, we ensure that the stats are reset to zero
154 m_sub_domain->parallelMng()->stat()->toArccoreStat()->resetCurrentStat();
155}
156
157/*---------------------------------------------------------------------------*/
158/*---------------------------------------------------------------------------*/
159
160void JsonMessagePassingProfilingService::
161_updateFromEndEntryPointEvt()
162{
163 // We retrieve the entry point name
164 const String& ep_name(m_sub_domain->timeLoopMng()->currentEntryPoint()->name());
165 auto pos(m_ep_mpstat_col.find(ep_name));
166 // If there are no stats yet for this entry point, we create them
167 Arccore::MessagePassing::StatData stat_data(m_sub_domain->parallelMng()->stat()->toArccoreStat()->stats());
168 if (pos == m_ep_mpstat_col.end())
169 m_ep_mpstat_col.emplace(ep_name, stat_data);
170 else // otherwise, we merge the stats
171 pos->second.mergeAllData(stat_data);
172}
173
174/*---------------------------------------------------------------------------*/
175/*---------------------------------------------------------------------------*/
176
177void JsonMessagePassingProfilingService::
178_updateFromBeginIterationEvt()
179{
180 // We start with an empty structure, since it is dumped at the end of each iteration
181 m_ep_mpstat_col.clear();
182}
183
184/*---------------------------------------------------------------------------*/
185/*---------------------------------------------------------------------------*/
186
187void JsonMessagePassingProfilingService::
188_updateFromEndIterationEvt()
189{
190 // We dump everything we have recorded for this iteration
191 if (m_json_writer)
192 _dumpCurrentIterationInJSON();
193}
194
195/*---------------------------------------------------------------------------*/
196/*---------------------------------------------------------------------------*/
197
198} // End namespace Arcane
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
This file contains the various service factories and macros for registering services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
Base class of a service.
Interface of a profiling service dedicated to "message passing".
Statistical data set for profiling.
Definition Stat.h:37
Structure containing the information to create a service.
Service creation properties.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
void dumpJSON(JSONWriter &writer, const Arccore::MessagePassing::OneStat &os, bool cumulative_stat=true)
Free function for dumping a message stat into JSON.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
@ ST_SubDomain
The service is used at the subdomain level.