Commit f7d71b74 authored by Ruben Laso Rodríguez's avatar Ruben Laso Rodríguez
Browse files

Refined algortihm (there is still work to be done).

parent 28d835ee
......@@ -154,14 +154,18 @@ namespace {
if (e.instructions()) {
samples::reduce_period_ins();
}
// std::cerr << "Not enough samples" << '\n';
std::cerr << "Not enough samples, reduced periods of sampling. New values: ";
for (const auto & period : samples::periods) {
std::cerr << period << '\t';
}
std::cerr << '\n';
// samples::update_periods();
samples::end();
samples::init();
samples::reboot();
// if (!samples::update_periods()) {
// std::cerr << "Error updating sample periods. Restarting sampling system..." << '\n';
// samples::end();
// samples::init();
// }
} catch (std::exception & e) {
std::cerr << "Error in main loop: " << e.what() << '\n';
} catch (...) {
......
......@@ -19,7 +19,7 @@ namespace samples {
perf_event_desc_t ** all_fds[NUM_GROUPS]; // Perf events File Descriptors
int num_fds[NUM_GROUPS]; // Number of File Descriptors
constexpr float multiplier = 0.9; // If samples < min_[mem,ins]_samples -> then latency/period *= 0.9;
constexpr float multiplier = 0.5; // If samples < min_[mem,ins]_samples -> then latency/period *= 0.9;
constexpr int min_mem_samples = 300; // Minimum number of samples to reduce minimum latency
constexpr int min_ins_samples = 300; // Minimum number of samples to reduce periods
......@@ -58,6 +58,7 @@ namespace samples {
}
fds[0].fd = -1;
for (int i = 0; i < num_fds[group]; i++) {
fds[i].hw.disabled = !i; // start immediately
......@@ -65,10 +66,8 @@ namespace samples {
if (fds[i].hw.sample_period) {
// set notification threshold to be halfway through the buffer
if (fds[i].hw.sample_period) {
fds[i].hw.wakeup_watermark = (mmap_pages * details::page_size) / 2;
fds[i].hw.watermark = 1;
}
fds[i].hw.wakeup_watermark = (mmap_pages * details::page_size) / 2;
fds[i].hw.watermark = 1;
fds[i].hw.sample_type =
PERF_SAMPLE_IP |
......@@ -83,6 +82,7 @@ namespace samples {
PERF_SAMPLE_DATA_SRC;
fds[i].hw.read_format = PERF_FORMAT_SCALE;
if (num_fds[group] > 1) {
fds[i].hw.read_format |= PERF_FORMAT_GROUP | PERF_FORMAT_ID;
}
......@@ -91,19 +91,20 @@ namespace samples {
fds[i].hw.exclude_guest = 1;
fds[i].hw.exclude_kernel = 1;
fds[i].fd = perf_event_open(&fds[i].hw, -1, cpu, fds[0].fd, flags); // Profile every PID for a given CPU
// Profile every PID for a given CPU
fds[i].fd = perf_event_open(&fds[i].hw, -1, cpu, fds[0].fd, flags);
if (fds[i].fd == -1) {
if (fds[i].hw.precise_ip) {
err(1, "cannot attach event %s: precise mode may not be supported", fds[i].name);
err(EXIT_FAILURE, "cannot attach event %s: precise mode may not be supported", fds[i].name);
}
err(1, "cannot attach event %s", fds[i].name);
err(EXIT_FAILURE, "cannot attach event %s", fds[i].name);
}
}
// kernel adds the header page to the size of the mmapped region
fds[0].buf = mmap(nullptr, details::map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fds[0].fd, 0);
if (fds[0].buf == MAP_FAILED) {
err(1, "cannot mmap buffer");
err(EXIT_FAILURE, "cannot mmap buffer");
}
// does not include header page
......@@ -116,7 +117,7 @@ namespace samples {
}
ret = ioctl(fds[i].fd, PERF_EVENT_IOC_SET_OUTPUT, fds[0].fd);
if (ret) {
err(1, "cannot redirect sampling output");
err(EXIT_FAILURE, "cannot redirect sampling output");
}
}
......@@ -126,7 +127,7 @@ namespace samples {
ret = read(fds[0].fd, val, sz);
if (ret == -1) {
err(1, "cannot read id %zu", sizeof(val));
err(EXIT_FAILURE, "cannot read id %zu", sizeof(val));
}
for (int i = 0; i < num_fds[group]; i++) {
......@@ -160,22 +161,24 @@ namespace samples {
periods[1] = std::max<int>(1, periods[1] * factor);
}
bool init () {
bool init (const bool reset_samples_counters = true) {
if (system_info::num_of_cpus() == 0) {
std::cerr << "System not detected" << '\n';
return false;
}
// Initialize variables
memset(details::collected_samples_group, 0, sizeof(details::collected_samples_group));
memset(details::processed_samples_group, 0, sizeof(details::processed_samples_group));
memset(details::buffer_reads, 0, sizeof(details::buffer_reads));
memset(details::lost_samples_group, 0, sizeof(details::lost_samples_group));
samples::details::unknown_samples = 0;
samples::details::page_size = sysconf(_SC_PAGESIZE);
samples::details::map_size = (mmap_pages + 1) * details::page_size;
samples::num_buffers = system_info::num_of_cpus() * NUM_GROUPS;
if (reset_samples_counters) {
// Initialize variables
memset(details::collected_samples_group, 0, sizeof(details::collected_samples_group));
memset(details::processed_samples_group, 0, sizeof(details::processed_samples_group));
memset(details::buffer_reads, 0, sizeof(details::buffer_reads));
memset(details::lost_samples_group, 0, sizeof(details::lost_samples_group));
samples::details::unknown_samples = 0;
samples::details::page_size = sysconf(_SC_PAGESIZE);
samples::details::map_size = (mmap_pages + 1) * details::page_size;
samples::num_buffers = system_info::num_of_cpus() * NUM_GROUPS;
}
for (auto & all_fd : all_fds) {
all_fd = new perf_event_desc_t * [system_info::num_of_cpus()];
......@@ -215,7 +218,7 @@ namespace samples {
}
const auto ret = ioctl(fds[0].fd, PERF_EVENT_IOC_ENABLE, 0);
if (ret) {
err(1, "cannot start counter");
err(EXIT_FAILURE, "Cannot start counter");
}
}
}
......@@ -279,7 +282,6 @@ namespace samples {
default:
// Skips different entire map page or partial
size_t to_skip = (ehdr.size == 0) ? details::map_size : ehdr.size - sizeof(ehdr);
//printf("Unknown sample type %d, skipping %lu bytes.\n", ehdr.type, to_skip);
perf_skip_buffer(hw, to_skip);
......@@ -314,7 +316,7 @@ namespace samples {
return std::move(samples);
}
void end () {
void end (const bool print_info = true) {
pfm_terminate();
delete[] pollfds;
......@@ -331,22 +333,50 @@ namespace samples {
delete[] all_fds[i];
}
const char * types[2] = {"memory", "instruction"};
for (size_t i = 0; i < NUM_GROUPS; i++) {
std::cout << details::collected_samples_group[i] << " (" << details::processed_samples_group[i] << ") "
<< types[i] << " samples collected (processed) in total " << details::buffer_reads[i]
<< " poll events and " << details::lost_samples_group[i] << " lost samples" << '\n';
if (print_info) {
const char * types[2] = {"memory", "instruction"};
for (size_t i = 0; i < NUM_GROUPS; i++) {
std::cout << details::collected_samples_group[i] << " (" << details::processed_samples_group[i] << ") "
<< types[i] << " samples collected (processed) in total " << details::buffer_reads[i]
<< " poll events and " << details::lost_samples_group[i] << " lost samples" << '\n';
}
std::cout << details::unknown_samples << " unknown samples." << '\n';
}
std::cout << details::unknown_samples << " unknown samples." << '\n';
}
void update_periods () {
for (size_t group = 0; group < NUM_GROUPS; group++) {
for (size_t cpu = 0; cpu < system_info::num_of_cpus(); cpu++) {
auto fds = all_fds[group][cpu];
fds->hw.sample_period = periods[group];
void reboot () {
samples::end(false);
samples::init(false);
}
bool update_periods () {
// TODO: find the way to update the periods of the HW counters without "rebooting"
bool correctly_updated = true;
// Update counters attributes
for (size_t i = 0; i < system_info::num_of_cpus(); i++) {
for (auto & all_fd : all_fds) {
auto fds = all_fd[i];
for (size_t group = 0; group < NUM_GROUPS; group++) {
if (fds[group].fd == -1) {
continue;
}
uint64_t new_period = periods[group];
fds->hw.sample_period = new_period;
correctly_updated &= (0 == ioctl(fds[group].fd, PERF_EVENT_IOC_PERIOD, &new_period));
std::clog << "Supposed new period[" << group << "]: " << periods[group] << " (" << new_period
<< "). fd.period: " << fds->hw.sample_period << '\n';
}
}
}
return correctly_updated;
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment