Skip to content

Commit

Permalink
Move Event Configuration to EventConfig class
Browse files Browse the repository at this point in the history
Designwise, the EventConfig class should handle all the ugly details of
configuring the Events from the given Config(), such as setting specific
bits.

The sample::Reader for example asks the EventConfig for a sample event.
The EventConfig then selects the correct sampling event using the
EventProvider and the Config, configures all the options, such as
sample_period and then gives it back to the sample::Reader.
The sample::Reader does not need to change anything about the event.

The EventProvider should only provide events, reading them from
different sources, such as pre-defined, PFM, PMU events.

The CounterProvider did not do anything special enough to warrant its
continuing existence, merge it with EventConfig

Smaller fixes
- delete needless getter in CounterCollection
- provide default values for bools in Config()
- check exclude_kernel once in EventConfig() instead of for every event
  • Loading branch information
cvonelm committed Jan 22, 2025
1 parent b82a776 commit baf36c2
Show file tree
Hide file tree
Showing 23 changed files with 630 additions and 739 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ set(SOURCE_FILES
src/perf/event.cpp

src/perf/bio/block_device.cpp
src/perf/counter/counter_provider.cpp
src/perf/event_config.cpp
src/perf/counter/group/reader.cpp
src/perf/counter/userspace/reader.cpp

Expand Down
11 changes: 7 additions & 4 deletions include/lo2s/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,23 +83,26 @@ struct Config
std::uint64_t metric_count;
std::uint64_t metric_frequency;

std::string metric_leader;
std::vector<std::string> group_counters;
std::vector<std::string> userspace_counters;
// time synchronization
bool use_clockid;
bool use_pebs;
clockid_t clockid;
// x86_energy
bool use_x86_energy;
bool use_x86_energy = false;
// block I/O
bool use_block_io;
bool use_block_io = false;
// syscalls
bool use_syscalls = false;
std::vector<int64_t> syscall_filter;
// NEC SX-Aurora Tsubasa
bool use_nec;
bool use_nec = false;
std::chrono::microseconds nec_read_interval;
std::chrono::milliseconds nec_check_interval;
// Nvidia CUPTI
bool use_nvidia;
bool use_nvidia = false;
std::string cuda_injectionlib_path;
uint64_t nvidia_ringbuf_size;
};
Expand Down
9 changes: 4 additions & 5 deletions include/lo2s/perf/bio/writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#pragma once

#include <lo2s/perf/event_config.hpp>
#include <lo2s/perf/io_reader.hpp>
#include <lo2s/perf/time/converter.hpp>
#include <lo2s/perf/tracepoint/format.hpp>
Expand Down Expand Up @@ -157,12 +158,10 @@ class Writer

std::vector<perf::tracepoint::TracepointEvent> get_tracepoints()
{
bio_queue_ =
perf::EventProvider::instance().create_tracepoint_event("block:block_bio_queue");
bio_issue_ =
perf::EventProvider::instance().create_tracepoint_event("block:block_rq_issue");
bio_queue_ = perf::EventConfig::instance().create_tracepoint_event("block:block_bio_queue");
bio_issue_ = perf::EventConfig::instance().create_tracepoint_event("block:block_rq_issue");
bio_complete_ =
perf::EventProvider::instance().create_tracepoint_event("block:block_rq_complete");
perf::EventConfig::instance().create_tracepoint_event("block:block_rq_complete");

return { bio_queue_.value(), bio_issue_.value(), bio_complete_.value() };
}
Expand Down
19 changes: 9 additions & 10 deletions include/lo2s/perf/counter/counter_collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,28 @@ namespace counter
{
struct CounterCollection
{
std::optional<Event> leader_;
CounterCollection() : leader(std::nullopt)
{
}

std::optional<Event> leader = std::nullopt;
std::vector<Event> counters;

double get_scale(int index) const
{
if (index == 0)
{
return leader_.value().scale();
return leader.value().scale();
}
else
{
return counters[index - 1].scale();
}
}

Event& leader() const
{
return const_cast<Event&>(leader_.value());
}

friend bool operator==(const CounterCollection& lhs, const CounterCollection& rhs)
{
if (lhs.leader_.value() == rhs.leader_.value())
if (lhs.leader.value() == rhs.leader.value())
{
return lhs.counters == rhs.counters;
}
Expand All @@ -65,11 +64,11 @@ struct CounterCollection

friend bool operator<(const CounterCollection& lhs, const CounterCollection& rhs)
{
if (lhs.leader_.value() == rhs.leader_.value())
if (lhs.leader.value() == rhs.leader.value())
{
return lhs.counters < rhs.counters;
}
return lhs.leader_.value() < rhs.leader_.value();
return lhs.leader.value() < rhs.leader.value();
}
};

Expand Down
69 changes: 0 additions & 69 deletions include/lo2s/perf/counter/counter_provider.hpp

This file was deleted.

70 changes: 70 additions & 0 deletions include/lo2s/perf/event_config.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* This file is part of the lo2s software.
* Linux OTF2 sampling
*
* Copyright (c) 2016,
* Technische Universitaet Dresden, Germany
*
* lo2s is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lo2s is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lo2s. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <lo2s/config.hpp>
#include <lo2s/measurement_scope.hpp>
#include <lo2s/perf/counter/counter_collection.hpp>
#include <lo2s/perf/event_provider.hpp>

namespace lo2s
{
namespace perf
{
class EventConfig
{

public:
EventConfig();

static EventConfig& instance()
{
static EventConfig e;
return e;
}

counter::CounterCollection counters_for(MeasurementScope scope);

Event create_time_event(uint64_t local_time);
Event create_sampling_event();
perf::tracepoint::TracepointEvent create_tracepoint_event(std::string name);
std::vector<perf::tracepoint::TracepointEvent> get_tracepoints();

private:
// When we poll on the fd given by perf_event_open, wakeup, when our buffer is 80% full
// Default behaviour is to wakeup on every event, which is horrible performance wise
void watermark(Event& ev)
{
ev.set_watermark(0.8 * config().mmap_pages * sysconf(_SC_PAGESIZE));
}

void read_userspace_counters();
void read_group_counters();

std::optional<Event> sampling_event_;
std::optional<counter::CounterCollection> group_counters_;
std::optional<counter::CounterCollection> userspace_counters_;
std::optional<std::vector<tracepoint::TracepointEvent>> tracepoint_events_;
bool exclude_kernel_;
};
} // namespace perf
} // namespace lo2s
39 changes: 12 additions & 27 deletions include/lo2s/perf/event_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,16 @@ namespace perf
class EventProvider
{
public:
EventProvider();
EventProvider(const EventProvider&) = delete;
void operator=(const EventProvider&) = delete;

static const EventProvider& instance()
{
return instance_mutable();
}

static Event get_event_by_name(const std::string& name);
Event get_event_by_name(const std::string& name);

static bool has_event(const std::string& name);
bool has_event(const std::string& name);

static std::vector<Event> get_predefined_events();
static std::vector<SysfsEvent> get_pmu_events();
std::vector<Event> get_predefined_events();
std::vector<SysfsEvent> get_pmu_events();

static Event fallback_metric_leader_event();

static Event create_time_event(std::uint64_t local_time, bool enable_on_exec = false);
static Event create_event(const std::string& name, perf_type_id type, std::uint64_t config,
std::uint64_t config1 = 0);
static SysfsEvent create_sampling_event(bool enable_on_exec);
static SysfsEvent create_sysfs_event(const std::string& name, bool use_config = true);
static tracepoint::TracepointEvent create_tracepoint_event(const std::string& name,
bool use_config = true,
bool enable_on_exec = false);
Event get_metric_leader(std::string metric_leader);

std::vector<std::string> get_tracepoint_event_names();

Check failure on line 48 in include/lo2s/perf/event_provider.hpp

View check run for this annotation

Code Style Turtle / Code Formatting Test

include/lo2s/perf/event_provider.hpp#L48

+
class InvalidEvent : public std::runtime_error
{
public:
Expand All @@ -72,15 +55,17 @@ class EventProvider
}
};

private:
static EventProvider& instance_mutable()
static EventProvider& instance()
{
static EventProvider e;
return e;
}

static void apply_config_attrs(Event& event);
static void apply_default_attrs(Event& event);
private:
Event fallback_metric_leader_event();
EventProvider();
EventProvider(const EventProvider&) = delete;
void operator=(const EventProvider&) = delete;

Event cache_event(const std::string& name);

Expand Down
1 change: 1 addition & 0 deletions include/lo2s/perf/io_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#pragma once

#include <lo2s/measurement_scope.hpp>
#include <lo2s/perf/event_config.hpp>
#include <lo2s/perf/event_provider.hpp>
#include <lo2s/perf/event_reader.hpp>
#include <lo2s/perf/tracepoint/event.hpp>
Expand Down
41 changes: 10 additions & 31 deletions include/lo2s/perf/sample/reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#pragma once

#include <lo2s/perf/event_config.hpp>
#include <lo2s/perf/event_provider.hpp>
#include <lo2s/perf/event_reader.hpp>
#include <lo2s/perf/util.hpp>
Expand Down Expand Up @@ -84,40 +85,18 @@ class Reader : public EventReader<T>
Log::debug() << "initializing event_reader for:" << scope.name()
<< ", enable_on_exec: " << enable_on_exec;

Event event = EventProvider::instance().create_sampling_event(enable_on_exec);

do
Event event = EventConfig::instance().create_sampling_event();
if (enable_on_exec)
{
try
{
event_ = event.open(scope, config().cgroup_fd);
}
catch (const std::system_error& e)
{
if (e.code().value() == EACCES && !event.attr().exclude_kernel &&
perf_event_paranoid() > 1)
{
event.mut_attr().exclude_kernel = 1;
perf_warn_paranoid();
continue;
}

if (!event.degrade_precision())
{
Log::error() << "perf_event_open for sampling failed: " << e.what();

if (event.attr().use_clockid)
{
Log::error() << "maybe the specified clock is unavailable?";
}
throw_errno();
}
}
} while (!event_.value().is_valid());
event.set_flags({ EventFlag::ENABLE_ON_EXEC });
}
else
{
event.set_flags({ EventFlag::DISABLED });
}

Log::debug() << "Using precise_ip level: " << event.attr().precise_ip;
event_ = event.open(scope, config().cgroup_fd);

// Exception safe, so much wow!
try
{
init_mmap(event_.value().get_fd());
Expand Down
Loading

0 comments on commit baf36c2

Please sign in to comment.