14#include "arcane/utils/IPerformanceCounterService.h"
15#include "arcane/utils/TraceAccessor.h"
16#include "arcane/utils/FatalErrorException.h"
18#include "arcane/core/FactoryService.h"
20#include <linux/perf_event.h>
21#include <linux/hw_breakpoint.h>
36class LinuxPerfPerformanceCounterService
46 ~LinuxPerfPerformanceCounterService()
61 bool _addEvent(
int event_type,
int event_config,
bool is_optional =
false)
63 struct perf_event_attr attr;
64 memset(&attr, 0,
sizeof(attr));
66 attr.type = event_type,
67 attr.config = event_config;
68 attr.size =
sizeof(
struct perf_event_attr);
69 attr.exclude_kernel = 1;
76 unsigned long flags = 0;
77 long long_fd = syscall(__NR_perf_event_open, &attr, m_process_id, cpu, group_fd, flags);
78 info(4) <<
"AddEvent type=" << attr.type <<
" id=" << attr.config <<
" fd=" << long_fd;
79 if (long_fd == (-1)) {
82 ARCANE_FATAL(
"ERROR for event type={0} id={1} error={2}", attr.type, attr.config, strerror(errno));
84 int fd =
static_cast<int>(long_fd);
85 m_events_file_descriptor.add(fd);
94 info(4) <<
"LinuxPerf: Start";
95 for (
int fd : m_events_file_descriptor) {
96 int r = ::ioctl(fd, PERF_EVENT_IOC_ENABLE);
98 ARCANE_FATAL(
"Error starting event r={0} error={1}", r, strerror(errno));
106 info(4) <<
"LinuxPerf: Stop";
107 for (
int fd : m_events_file_descriptor) {
108 int r = ::ioctl(fd, PERF_EVENT_IOC_DISABLE);
110 ARCANE_FATAL(
"Error stopping event r={0} error={1}", r, strerror(errno));
112 m_is_started =
false;
122 for (
Int32 index = 0, n = m_events_file_descriptor.size(); index < n; ++index) {
123 Int64 value = _getOneCounter(index);
124 Int64 current_value = counters[index];
125 counters[index] = (do_substract) ? value - current_value : value;
132 return _getOneCounter(0);
138 bool m_is_started =
false;
139 bool m_is_init =
false;
140 pid_t m_process_id = -1;
146 for (
int fd : m_events_file_descriptor) {
150 m_events_file_descriptor.
clear();
155 int fd = m_events_file_descriptor[index];
156 uint64_t value[1] = { 0 };
157 const size_t s =
sizeof(uint64_t);
158 size_t nb_read = ::read(fd, value, s);
164 void _checkInitialize()
169 info() <<
"Initialize LinuxPerfPerformanceCounterService";
170 m_process_id = ::getpid();
172 _addEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES);
174 _addEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS);
182 const bool is_optional =
true;
185 int cache_access = (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16);
186 is_bad =
_addEvent(PERF_TYPE_HW_CACHE, PERF_COUNT_HW_CACHE_LL | cache_access, is_optional);
189 is_bad =
_addEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, is_optional);
191 _addEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES, is_optional);
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
void clear()
Removes the elements from the array.
virtual ITraceMng * traceMng() const =0
Trace manager.
IApplication * application() const
Access to the associated IApplication.
Structure containing the information to create a service.
Service creation properties.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
1D data vector with value semantics (STL style).
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
ArrayView< Int64 > Int64ArrayView
C equivalent of a 1D array of 64-bit integers.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
@ ST_Application
The service is used at the application level.
std::int32_t Int32
Signed integer type of 32 bits.