From 866fd8bc2473f772ac68f0463100e4f4ed47798a Mon Sep 17 00:00:00 2001 From: jackun Date: Sat, 7 Aug 2021 15:55:04 +0300 Subject: [PATCH] Add per process memory usage (`procmem` etc) --- README.md | 1 + bin/MangoHud.conf | 6 ++++ src/gl/imgui_hud.cpp | 1 + src/hud_elements.cpp | 77 ++++++++++++++++++++++++++++++++++++++---- src/hud_elements.h | 18 +++++----- src/memory.cpp | 31 ++++++++++++++++- src/memory.h | 8 +++++ src/overlay.cpp | 4 ++- src/overlay.h | 4 +-- src/overlay_params.cpp | 8 +++-- src/overlay_params.h | 3 ++ 11 files changed, 140 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index c7546ae6..a3079f45 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `gpu_core_clock`
`gpu_mem_clock`| Displays GPU core/memory frequency | | `ram`
`vram` | Displays system RAM/VRAM usage | | `swap` | Displays swap space usage next to system RAM usage | +| `procmem`
`procmem_shared`, `procmem_virt`| Displays process' memory usage: resident, shared and/or virtual. `procmem` (resident) also toggles others off if disabled. | | `full` | Enables most of the toggleable parameters (currently excludes `histogram`) | | `font_size=` | Customizeable font size (default=24) | | `font_size_text=` | Customizeable font size for other text like media metadata (default=24) | diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 4906b4d9..2e082d6d 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -110,6 +110,12 @@ position=top-left # swap # vram +### Display per process memory usage +## Show resident memory and other types, if enabled +# procmem +# procmem_shared +# procmem_virt + ### Display MangoHud, engine or Wine version # version # engine_version diff --git a/src/gl/imgui_hud.cpp b/src/gl/imgui_hud.cpp index 5e7fcdbb..adb9cb9a 100644 --- a/src/gl/imgui_hud.cpp +++ b/src/gl/imgui_hud.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 096c913d..3f9d3d25 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -1,6 +1,13 @@ +#include #include +#include +#include #include +#include "overlay.h" +#include "overlay_params.h" #include "hud_elements.h" +#include "logging.h" +#include "battery.h" #include "cpu.h" #include "memory.h" #include "mesa/util/macros.h" @@ -48,6 +55,20 @@ ImVec4 LinearToSRGB(ImVec4 col) return col; } +template +R format_units(T value, const char*& unit) +{ + static const char* const units[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"}; + size_t u = 0; + R out_value = value; + while (out_value > 1023 && u < ARRAY_SIZE(units)) { + out_value /= 1024; + ++u; + } + unit = units[u]; + return out_value; +} + void HudElements::convert_colors(struct overlay_params& params) { HUDElements.colors.update = false; @@ -273,6 +294,7 @@ void HudElements::core_load(){ } } } + void HudElements::io_stats(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]){ ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -324,6 +346,7 @@ void HudElements::vram(){ } } } + void HudElements::ram(){ #ifdef __gnu_linux__ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram]){ @@ -335,7 +358,7 @@ void HudElements::ram(){ ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("GiB"); ImGui::PopFont(); - } + } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_swap]){ ImGui::TableNextColumn(); @@ -348,6 +371,45 @@ void HudElements::ram(){ #endif } +void HudElements::procmem() +{ + const char* unit = nullptr; + if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_procmem]) + return; + + ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::TextColored(HUDElements.colors.ram, "PMEM"); + ImGui::TableNextColumn(); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", format_units(proc_mem.resident, unit)); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("%s", unit); + ImGui::PopFont(); + + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_procmem_shared]){ + ImGui::TableNextColumn(); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", format_units(proc_mem.shared, unit)); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("%s", unit); + ImGui::PopFont(); + } + + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_procmem_shared] && HUDElements.params->table_columns < 4){ + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + } + + if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_procmem_virt]){ + ImGui::TableNextColumn(); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", format_units(proc_mem.virt, unit)); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("%s", unit); + ImGui::PopFont(); + } +} + void HudElements::fps(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps]){ ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -540,7 +602,7 @@ void HudElements::show_fps_limit(){ void HudElements::custom_text_center(){ ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::PushFont(HUDElements.sw_stats->font1); - std::string value = HUDElements.ordered_functions[HUDElements.place].second; + const std::string& value = HUDElements.ordered_functions[HUDElements.place].second; center_text(value); ImGui::TextColored(HUDElements.colors.text, "%s",value.c_str()); ImGui::NewLine(); @@ -550,13 +612,13 @@ void HudElements::custom_text_center(){ void HudElements::custom_text(){ ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::PushFont(HUDElements.sw_stats->font1); - std::string value = HUDElements.ordered_functions[HUDElements.place].second; + const std::string& value = HUDElements.ordered_functions[HUDElements.place].second; ImGui::TextColored(HUDElements.colors.text, "%s",value.c_str()); ImGui::PopFont(); } void HudElements::_exec(){ - std::string value = HUDElements.ordered_functions[HUDElements.place].second; + //const std::string& value = HUDElements.ordered_functions[HUDElements.place].second; ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::TableNextColumn(); for (auto& item : HUDElements.exec_list){ @@ -633,7 +695,7 @@ void HudElements::battery(){ void HudElements::graphs(){ ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); - std::string value = HUDElements.ordered_functions[HUDElements.place].second; + const std::string& value = HUDElements.ordered_functions[HUDElements.place].second; std::vector arr(50, 0); ImGui::PushFont(HUDElements.sw_stats->font1); @@ -765,6 +827,7 @@ void HudElements::sort_elements(const std::pair& optio if (param == "io_stats") { ordered_functions.push_back({io_stats, value}); } if (param == "vram") { ordered_functions.push_back({vram, value}); } if (param == "ram") { ordered_functions.push_back({ram, value}); } + if (param == "procmem") { ordered_functions.push_back({procmem, value}); } if (param == "fps") { ordered_functions.push_back({fps, value}); } if (param == "engine_version") { ordered_functions.push_back({engine_version, value}); } if (param == "gpu_name") { ordered_functions.push_back({gpu_name, value}); } @@ -790,7 +853,9 @@ void HudElements::sort_elements(const std::pair& optio if (find(permitted_params.begin(), permitted_params.end(), value) != permitted_params.end()) ordered_functions.push_back({graphs, value}); else - printf("MANGOHUD: Unrecognized graph type: %s\n", value.c_str()); + { + spdlog::info("Unrecognized graph type: {}", value); + } } } return; diff --git a/src/hud_elements.h b/src/hud_elements.h index af64d6c3..6b001a60 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -1,17 +1,16 @@ #pragma once -#include "overlay.h" -#include "overlay_params.h" -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include "timing.hpp" +struct overlay_params; class HudElements{ public: struct swapchain_stats *sw_stats; struct overlay_params *params; - struct exec_list { + struct exec_entry { int pos; std::string value; std::string ret; @@ -29,7 +28,7 @@ class HudElements{ "gpu_load", "cpu_load", "gpu_core_clock", "gpu_mem_clock", "vram", "ram", "cpu_temp", "gpu_temp" }; - std::vector exec_list; + std::vector exec_list; void sort_elements(const std::pair& option); void legacy_elements(); void update_exec(); @@ -41,6 +40,7 @@ class HudElements{ static void io_stats(); static void vram(); static void ram(); + static void procmem(); static void fps(); static void engine_version(); static void gpu_name(); diff --git a/src/memory.cpp b/src/memory.cpp index 63b0c5d9..9102352e 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1,12 +1,15 @@ +#include #include "memory.h" #include #include #include #include #include +#include struct memory_information mem_info; float memused, memmax, swapused, swapmax; +struct process_mem proc_mem {}; FILE *open_file(const char *file, int *reported) { FILE *fp = nullptr; @@ -15,7 +18,7 @@ FILE *open_file(const char *file, int *reported) { if (fp == nullptr) { if ((reported == nullptr) || *reported == 0) { - // NORM_ERR("can't open %s: %s", file, strerror(errno)); + SPDLOG_ERROR("can't open {}: {}", file, strerror(errno)); if (reported != nullptr) { *reported = 1; } } return nullptr; @@ -100,3 +103,29 @@ void update_meminfo(void) { fclose(meminfo_fp); } + +void update_procmem() +{ + static int reported = 0; + FILE *statm = open_file("/proc/self/statm", &reported); + if (!statm) + return; + + static auto pageSize = sysconf(_SC_PAGESIZE); + if (pageSize < 0) pageSize = 4096; + + long int temp[7]; + if (fscanf(statm, "%ld %ld %ld %ld %ld %ld %ld", + &temp[0], &temp[1], &temp[2], &temp[3], + &temp[4], /* unused since Linux 2.6; always 0 */ + &temp[5], &temp[6]) == 7) + { + proc_mem.virt = temp[0] * pageSize;// / (1024.f * 1024.f); //MiB + proc_mem.resident = temp[1] * pageSize;// / (1024.f * 1024.f); //MiB + proc_mem.shared = temp[2] * pageSize;// / (1024.f * 1024.f); //MiB; + proc_mem.text = temp[3]; + proc_mem.data = temp[5]; + proc_mem.dirty = temp[6]; + } + fclose(statm); +} diff --git a/src/memory.h b/src/memory.h index 469c14e8..c48603ac 100644 --- a/src/memory.h +++ b/src/memory.h @@ -15,7 +15,15 @@ struct memory_information { unsigned long long bufmem, buffers, cached; }; +struct process_mem +{ + float virt, resident, shared; + long int text, data, dirty; +}; +extern process_mem proc_mem; + void update_meminfo(void); +void update_procmem(); FILE *open_file(const char *file, int *reported); #endif //MANGOHUD_MEMORY_H diff --git a/src/overlay.cpp b/src/overlay.cpp index 427defaf..bdd51208 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -70,6 +70,8 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par #ifdef __gnu_linux__ if (params.enabled[OVERLAY_PARAM_ENABLED_ram] || params.enabled[OVERLAY_PARAM_ENABLED_swap] || logger->is_active()) update_meminfo(); + if (params.enabled[OVERLAY_PARAM_ENABLED_procmem]) + update_procmem(); if (params.enabled[OVERLAY_PARAM_ENABLED_io_read] || params.enabled[OVERLAY_PARAM_ENABLED_io_write]) getIoStats(&sw_stats.io); #endif @@ -248,7 +250,7 @@ void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...) ImGui::TextColored(col,"%s",buffer); } -void center_text(std::string& text) +void center_text(const std::string& text) { ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(text.c_str()).x / 2)); } diff --git a/src/overlay.h b/src/overlay.h index 0d1927df..0b6fa5f8 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -5,7 +5,7 @@ #include #include #include -#include "imgui.h" +#include #include "overlay_params.h" #include "iostats.h" #include "timing.hpp" @@ -119,7 +119,7 @@ void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& void calculate_benchmark_data(void *params_void); void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font); void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...); -void center_text(std::string& text); +void center_text(const std::string& text); ImVec4 change_on_load_temp(LOAD_DATA& data, unsigned current); float get_time_stat(void *_data, int _idx); diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index eaf43e8a..04282fe0 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -559,6 +559,9 @@ parse_overlay_config(struct overlay_params *params, { if (!spdlog::get("MANGOHUD")) spdlog::set_default_logger(spdlog::stderr_color_mt("MANGOHUD")); // Just to get the name in log +#ifndef NDEBUG + spdlog::set_level(spdlog::level::level_enum::debug); +#endif spdlog::cfg::load_env_levels(); *params = {}; @@ -784,8 +787,9 @@ parse_overlay_config(struct overlay_params *params, } #endif - if(!params->output_file.empty()) - printf("MANGOHUD: output_file is Deprecated, use output_folder instead\n"); + if(!params->output_file.empty()) { + SPDLOG_INFO("output_file is deprecated, use output_folder instead"); + } auto real_size = params->font_size * params->font_scale; real_font_size = ImVec2(real_size, real_size / 2); diff --git a/src/overlay_params.h b/src/overlay_params.h index e7530d2f..4c0d391b 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -36,6 +36,9 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(ram) \ OVERLAY_PARAM_BOOL(swap) \ OVERLAY_PARAM_BOOL(vram) \ + OVERLAY_PARAM_BOOL(procmem) \ + OVERLAY_PARAM_BOOL(procmem_shared) \ + OVERLAY_PARAM_BOOL(procmem_virt) \ OVERLAY_PARAM_BOOL(time) \ OVERLAY_PARAM_BOOL(full) \ OVERLAY_PARAM_BOOL(read_cfg) \