diff --git a/src/iostats.cpp b/src/iostats.cpp new file mode 100644 index 00000000..bd0ef5f5 --- /dev/null +++ b/src/iostats.cpp @@ -0,0 +1,27 @@ +#include "iostats.h" +#include "string_utils.h" +#include + +pthread_t ioThread; +void *getIoStats(void *args) { + iostats *io = reinterpret_cast(args); + if (io) { + io->prev.read_bytes = io->curr.read_bytes; + io->prev.write_bytes = io->curr.write_bytes; + + std::string line; + std::ifstream f("/proc/self/io"); + while (std::getline(f, line)) { + if (starts_with(line, "read_bytes:")) { + try_stoull(io->curr.read_bytes, line.substr(12)); + } + else if (starts_with(line, "write_bytes:")) { + try_stoull(io->curr.write_bytes, line.substr(13)); + } + } + io->diff.read = (io->curr.read_bytes - io->prev.read_bytes) / (1024.f * 1024.f); + io->diff.write = (io->curr.write_bytes - io->prev.write_bytes) / (1024.f * 1024.f); + } + pthread_detach(ioThread); + return NULL; +} diff --git a/src/iostats.h b/src/iostats.h new file mode 100644 index 00000000..eae538c4 --- /dev/null +++ b/src/iostats.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include + +extern pthread_t ioThread; + +struct iostats { + struct { + unsigned long long read_bytes; + unsigned long long write_bytes; + } curr; + struct { + unsigned long long read_bytes; + unsigned long long write_bytes; + } prev; + struct { + float read; + float write; + } diff; +}; + +void *getIoStats(void *args); diff --git a/src/meson.build b/src/meson.build index cf52db61..8f53ec31 100644 --- a/src/meson.build +++ b/src/meson.build @@ -41,6 +41,7 @@ vklayer_files = files( 'file_utils.cpp', 'memory.cpp', 'config.cpp', + 'iostats.cpp', ) # lib_xnvctrl = cc.find_library('XNVCtrl') diff --git a/src/overlay.cpp b/src/overlay.cpp index 5e455c2e..9024aed7 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -54,6 +54,7 @@ #include "logging.h" #include "keybinds.h" #include "cpu.h" +#include "iostats.h" #include "loaders/loader_nvml.h" bool open = false; @@ -223,6 +224,8 @@ struct swapchain_data { /* Over fps_sampling_period */ struct frame_stat accumulated_stats; + + struct iostats io; }; static const VkQueryPipelineStatisticFlags overlay_query_flags = @@ -986,6 +989,7 @@ static void snapshot_swapchain_frame(struct swapchain_data *data) // get ram usage/max pthread_create(&memoryThread, NULL, &update_meminfo, NULL); + pthread_create(&ioThread, NULL, &getIoStats, &data->io); // update variables for logging // cpuLoadLog = cpuArray[0].value; @@ -1212,6 +1216,26 @@ static void compute_swapchain_display(struct swapchain_data *data) ImGui::Text("GB"); ImGui::PopFont(); } + if (instance_data->params.io_read){ + auto sampling = instance_data->params.fps_sampling_period; + ImGui::TextColored(ImVec4(0.760, 0.576, 0.4, 1.00f), "IO rd"); + ImGui::SameLine(hudFirstRow); + ImGui::Text("%.2f", data->io.diff.read * (1000000 / sampling)); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(data->font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); + } + if (instance_data->params.io_write){ + auto sampling = instance_data->params.fps_sampling_period; + ImGui::TextColored(ImVec4(0.760, 0.576, 0.4, 1.00f), "IO wr"); + ImGui::SameLine(hudFirstRow); + ImGui::Text("%.2f", data->io.diff.write * (1000000 / sampling)); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(data->font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); + } if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_fps]){ ImGui::TableNextRow(); ImGui::TextColored(ImVec4(0.925, 0.411, 0.411, 1.00f), "%s", engineName.c_str()); diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index c1783878..9ff6b0c8 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -147,6 +147,8 @@ parse_str(const char *str) #define parse_offset_x(s) parse_unsigned(s) #define parse_offset_y(s) parse_unsigned(s) #define parse_time_format(s) parse_str(s) +#define parse_io_read(s) parse_unsigned(s) +#define parse_io_write(s) parse_unsigned(s) #define parse_crosshair_color(s) parse_color(s) diff --git a/src/overlay_params.h b/src/overlay_params.h index e52e9dff..e68a3b00 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -73,6 +73,8 @@ extern "C" { OVERLAY_PARAM_CUSTOM(crosshair_color) \ OVERLAY_PARAM_CUSTOM(background_alpha) \ OVERLAY_PARAM_CUSTOM(time_format) \ + OVERLAY_PARAM_CUSTOM(io_read) \ + OVERLAY_PARAM_CUSTOM(io_write) \ OVERLAY_PARAM_CUSTOM(help) enum overlay_param_position { @@ -102,6 +104,7 @@ struct overlay_params { bool help; bool no_display; bool full; + bool io_read, io_write; unsigned width; unsigned height; unsigned offset_x; diff --git a/src/string_utils.h b/src/string_utils.h index 780ec38b..16fa42f4 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -73,4 +73,15 @@ static bool try_stoi(int& val, const std::string& str, std::size_t* pos = 0, int return false; } +static bool try_stoull(unsigned long long& val, const std::string& str, std::size_t* pos = 0, int base = 10) +{ + try { + val = std::stoull(str, pos, base); + return true; + } catch (std::invalid_argument& e) { + std::cerr << __func__ << ": invalid argument: '" << str << "'" << std::endl; + } + return false; +} + #pragma GCC diagnostic pop