perf(memory): eliminate deep copies in range-based for loops and lambdas
This commit addresses memory churn caused by implicit deep copies during traversal and allocation of complex structures: - Replaced pass-by-value 'Json::Value' in std::ranges and range-based for loops with 'const auto&' or 'const Json::Value&' in Hyprland modules, preventing large JSON tree duplications on every update. - Fixed implicit string and pair copies in UPower and CPU Frequency loops by converting 'auto' to 'const auto&' where possible. - Added 'std::vector::reserve' calls before 'push_back' loops in MPRIS, Niri, and CFFI modules to prevent exponential vector reallocation during initialization. Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
This commit is contained in:
@@ -71,6 +71,7 @@ CFFI::CFFI(const std::string& name, const std::string& id, const Json::Value& co
|
|||||||
|
|
||||||
// Prepare config_entries array
|
// Prepare config_entries array
|
||||||
std::vector<ffi::wbcffi_config_entry> config_entries;
|
std::vector<ffi::wbcffi_config_entry> config_entries;
|
||||||
|
config_entries.reserve(keys.size());
|
||||||
for (size_t i = 0; i < keys.size(); i++) {
|
for (size_t i = 0; i < keys.size(); i++) {
|
||||||
config_entries.push_back({keys[i].c_str(), config_entries_stringstor[i].c_str()});
|
config_entries.push_back({keys[i].c_str(), config_entries_stringstor[i].c_str()});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ std::vector<float> waybar::modules::CpuFrequency::parseCpuFrequencies() {
|
|||||||
if (std::filesystem::exists(cpufreq_dir)) {
|
if (std::filesystem::exists(cpufreq_dir)) {
|
||||||
std::vector<std::string> frequency_files = {"/cpuinfo_min_freq", "/cpuinfo_max_freq"};
|
std::vector<std::string> frequency_files = {"/cpuinfo_min_freq", "/cpuinfo_max_freq"};
|
||||||
for (auto& p : std::filesystem::directory_iterator(cpufreq_dir)) {
|
for (auto& p : std::filesystem::directory_iterator(cpufreq_dir)) {
|
||||||
for (auto freq_file : frequency_files) {
|
for (const auto& freq_file : frequency_files) {
|
||||||
std::string freq_file_path = p.path().string() + freq_file;
|
std::string freq_file_path = p.path().string() + freq_file;
|
||||||
if (std::filesystem::exists(freq_file_path)) {
|
if (std::filesystem::exists(freq_file_path)) {
|
||||||
std::string freq_value;
|
std::string freq_value;
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ auto Window::getActiveWorkspace(const std::string& monitorName) -> Workspace {
|
|||||||
const auto monitors = IPC::inst().getSocket1JsonReply("monitors");
|
const auto monitors = IPC::inst().getSocket1JsonReply("monitors");
|
||||||
if (monitors.isArray()) {
|
if (monitors.isArray()) {
|
||||||
auto monitor = std::ranges::find_if(
|
auto monitor = std::ranges::find_if(
|
||||||
monitors, [&](Json::Value monitor) { return monitor["name"] == monitorName; });
|
monitors, [&](const Json::Value& monitor) { return monitor["name"] == monitorName; });
|
||||||
if (monitor == std::end(monitors)) {
|
if (monitor == std::end(monitors)) {
|
||||||
spdlog::warn("Monitor not found: {}", monitorName);
|
spdlog::warn("Monitor not found: {}", monitorName);
|
||||||
return Workspace{
|
return Workspace{
|
||||||
@@ -139,7 +139,7 @@ auto Window::getActiveWorkspace(const std::string& monitorName) -> Workspace {
|
|||||||
const auto workspaces = IPC::inst().getSocket1JsonReply("workspaces");
|
const auto workspaces = IPC::inst().getSocket1JsonReply("workspaces");
|
||||||
if (workspaces.isArray()) {
|
if (workspaces.isArray()) {
|
||||||
auto workspace = std::ranges::find_if(
|
auto workspace = std::ranges::find_if(
|
||||||
workspaces, [&](Json::Value workspace) { return workspace["id"] == id; });
|
workspaces, [&](const Json::Value& workspace) { return workspace["id"] == id; });
|
||||||
if (workspace == std::end(workspaces)) {
|
if (workspace == std::end(workspaces)) {
|
||||||
spdlog::warn("No workspace with id {}", id);
|
spdlog::warn("No workspace with id {}", id);
|
||||||
return Workspace{
|
return Workspace{
|
||||||
@@ -190,7 +190,7 @@ void Window::queryActiveWorkspace() {
|
|||||||
const auto clients = m_ipc.getSocket1JsonReply("clients");
|
const auto clients = m_ipc.getSocket1JsonReply("clients");
|
||||||
if (clients.isArray()) {
|
if (clients.isArray()) {
|
||||||
auto activeWindow = std::ranges::find_if(
|
auto activeWindow = std::ranges::find_if(
|
||||||
clients, [&](Json::Value window) { return window["address"] == workspace_.last_window; });
|
clients, [&](const Json::Value& window) { return window["address"] == workspace_.last_window; });
|
||||||
|
|
||||||
if (activeWindow == std::end(clients)) {
|
if (activeWindow == std::end(clients)) {
|
||||||
focused_ = false;
|
focused_ = false;
|
||||||
@@ -200,19 +200,19 @@ void Window::queryActiveWorkspace() {
|
|||||||
windowData_ = WindowData::parse(*activeWindow);
|
windowData_ = WindowData::parse(*activeWindow);
|
||||||
updateAppIconName(windowData_.class_name, windowData_.initial_class_name);
|
updateAppIconName(windowData_.class_name, windowData_.initial_class_name);
|
||||||
std::vector<Json::Value> workspaceWindows;
|
std::vector<Json::Value> workspaceWindows;
|
||||||
std::ranges::copy_if(clients, std::back_inserter(workspaceWindows), [&](Json::Value window) {
|
std::ranges::copy_if(clients, std::back_inserter(workspaceWindows), [&](const Json::Value& window) {
|
||||||
return window["workspace"]["id"] == workspace_.id && window["mapped"].asBool();
|
return window["workspace"]["id"] == workspace_.id && window["mapped"].asBool();
|
||||||
});
|
});
|
||||||
swallowing_ = std::ranges::any_of(workspaceWindows, [&](Json::Value window) {
|
swallowing_ = std::ranges::any_of(workspaceWindows, [&](const Json::Value& window) {
|
||||||
return !window["swallowing"].isNull() && window["swallowing"].asString() != "0x0";
|
return !window["swallowing"].isNull() && window["swallowing"].asString() != "0x0";
|
||||||
});
|
});
|
||||||
std::vector<Json::Value> visibleWindows;
|
std::vector<Json::Value> visibleWindows;
|
||||||
std::ranges::copy_if(workspaceWindows, std::back_inserter(visibleWindows),
|
std::ranges::copy_if(workspaceWindows, std::back_inserter(visibleWindows),
|
||||||
[&](Json::Value window) { return !window["hidden"].asBool(); });
|
[&](const Json::Value& window) { return !window["hidden"].asBool(); });
|
||||||
solo_ = 1 == std::count_if(visibleWindows.begin(), visibleWindows.end(),
|
solo_ = 1 == std::count_if(visibleWindows.begin(), visibleWindows.end(),
|
||||||
[&](Json::Value window) { return !window["floating"].asBool(); });
|
[&](const Json::Value& window) { return !window["floating"].asBool(); });
|
||||||
allFloating_ = std::ranges::all_of(
|
allFloating_ = std::ranges::all_of(
|
||||||
visibleWindows, [&](Json::Value window) { return window["floating"].asBool(); });
|
visibleWindows, [&](const Json::Value& window) { return window["floating"].asBool(); });
|
||||||
fullscreen_ = windowData_.fullscreen;
|
fullscreen_ = windowData_.fullscreen;
|
||||||
|
|
||||||
// Fullscreen windows look like they are solo
|
// Fullscreen windows look like they are solo
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ auto WindowCount::getActiveWorkspace(const std::string& monitorName) -> Workspac
|
|||||||
const auto monitors = m_ipc.getSocket1JsonReply("monitors");
|
const auto monitors = m_ipc.getSocket1JsonReply("monitors");
|
||||||
if (monitors.isArray()) {
|
if (monitors.isArray()) {
|
||||||
auto monitor = std::ranges::find_if(
|
auto monitor = std::ranges::find_if(
|
||||||
monitors, [&](Json::Value monitor) { return monitor["name"] == monitorName; });
|
monitors, [&](const Json::Value& monitor) { return monitor["name"] == monitorName; });
|
||||||
if (monitor == std::end(monitors)) {
|
if (monitor == std::end(monitors)) {
|
||||||
spdlog::warn("Monitor not found: {}", monitorName);
|
spdlog::warn("Monitor not found: {}", monitorName);
|
||||||
return Workspace{
|
return Workspace{
|
||||||
@@ -93,7 +93,7 @@ auto WindowCount::getActiveWorkspace(const std::string& monitorName) -> Workspac
|
|||||||
const auto workspaces = m_ipc.getSocket1JsonReply("workspaces");
|
const auto workspaces = m_ipc.getSocket1JsonReply("workspaces");
|
||||||
if (workspaces.isArray()) {
|
if (workspaces.isArray()) {
|
||||||
auto workspace = std::ranges::find_if(
|
auto workspace = std::ranges::find_if(
|
||||||
workspaces, [&](Json::Value workspace) { return workspace["id"] == id; });
|
workspaces, [&](const Json::Value& workspace) { return workspace["id"] == id; });
|
||||||
if (workspace == std::end(workspaces)) {
|
if (workspace == std::end(workspaces)) {
|
||||||
spdlog::warn("No workspace with id {}", id);
|
spdlog::warn("No workspace with id {}", id);
|
||||||
return Workspace{
|
return Workspace{
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ bool Workspace::handleClicked(GdkEventButton* bt) const {
|
|||||||
|
|
||||||
void Workspace::initializeWindowMap(const Json::Value& clients_data) {
|
void Workspace::initializeWindowMap(const Json::Value& clients_data) {
|
||||||
m_windowMap.clear();
|
m_windowMap.clear();
|
||||||
for (auto client : clients_data) {
|
for (const auto& client : clients_data) {
|
||||||
if (client["workspace"]["id"].asInt() == id()) {
|
if (client["workspace"]["id"].asInt() == id()) {
|
||||||
insertWindow({client});
|
insertWindow({client});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ void Workspaces::initializeWorkspaces() {
|
|||||||
auto const workspacesJson = m_ipc.getSocket1JsonReply("workspaces");
|
auto const workspacesJson = m_ipc.getSocket1JsonReply("workspaces");
|
||||||
auto const clientsJson = m_ipc.getSocket1JsonReply("clients");
|
auto const clientsJson = m_ipc.getSocket1JsonReply("clients");
|
||||||
|
|
||||||
for (Json::Value workspaceJson : workspacesJson) {
|
for (const auto& workspaceJson : workspacesJson) {
|
||||||
std::string workspaceName = workspaceJson["name"].asString();
|
std::string workspaceName = workspaceJson["name"].asString();
|
||||||
if ((allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
|
if ((allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
|
||||||
(!workspaceName.starts_with("special") || showSpecial()) &&
|
(!workspaceName.starts_with("special") || showSpecial()) &&
|
||||||
@@ -401,7 +401,7 @@ void Workspaces::onWorkspaceCreated(std::string const& payload, Json::Value cons
|
|||||||
auto const workspaceRules = m_ipc.getSocket1JsonReply("workspacerules");
|
auto const workspaceRules = m_ipc.getSocket1JsonReply("workspacerules");
|
||||||
auto const workspacesJson = m_ipc.getSocket1JsonReply("workspaces");
|
auto const workspacesJson = m_ipc.getSocket1JsonReply("workspaces");
|
||||||
|
|
||||||
for (Json::Value workspaceJson : workspacesJson) {
|
for (auto workspaceJson : workspacesJson) {
|
||||||
const auto currentId = workspaceJson["id"].asInt();
|
const auto currentId = workspaceJson["id"].asInt();
|
||||||
if (currentId == *workspaceId) {
|
if (currentId == *workspaceId) {
|
||||||
std::string workspaceName = workspaceJson["name"].asString();
|
std::string workspaceName = workspaceJson["name"].asString();
|
||||||
@@ -1004,7 +1004,7 @@ void Workspaces::setUrgentWorkspace(std::string const& windowaddress) {
|
|||||||
const Json::Value clientsJson = m_ipc.getSocket1JsonReply("clients");
|
const Json::Value clientsJson = m_ipc.getSocket1JsonReply("clients");
|
||||||
int workspaceId = -1;
|
int workspaceId = -1;
|
||||||
|
|
||||||
for (Json::Value clientJson : clientsJson) {
|
for (const auto& clientJson : clientsJson) {
|
||||||
if (clientJson["address"].asString().ends_with(windowaddress)) {
|
if (clientJson["address"].asString().ends_with(windowaddress)) {
|
||||||
workspaceId = clientJson["workspace"]["id"].asInt();
|
workspaceId = clientJson["workspace"]["id"].asInt();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ Mpris::Mpris(const std::string& id, const Json::Value& config)
|
|||||||
player_ = config_["player"].asString();
|
player_ = config_["player"].asString();
|
||||||
}
|
}
|
||||||
if (config_["ignored-players"].isArray()) {
|
if (config_["ignored-players"].isArray()) {
|
||||||
|
ignored_players_.reserve(config_["ignored-players"].size());
|
||||||
for (const auto& item : config_["ignored-players"]) {
|
for (const auto& item : config_["ignored-players"]) {
|
||||||
if (item.isString()) {
|
if (item.isString()) {
|
||||||
ignored_players_.push_back(item.asString());
|
ignored_players_.push_back(item.asString());
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ void Language::updateFromIPC() {
|
|||||||
auto ipcLock = gIPC->lockData();
|
auto ipcLock = gIPC->lockData();
|
||||||
|
|
||||||
layouts_.clear();
|
layouts_.clear();
|
||||||
|
layouts_.reserve(gIPC->keyboardLayoutNames().size());
|
||||||
for (const auto& fullName : gIPC->keyboardLayoutNames()) layouts_.push_back(getLayout(fullName));
|
for (const auto& fullName : gIPC->keyboardLayoutNames()) layouts_.push_back(getLayout(fullName));
|
||||||
|
|
||||||
current_idx_ = gIPC->keyboardLayoutCurrent();
|
current_idx_ = gIPC->keyboardLayoutCurrent();
|
||||||
|
|||||||
Reference in New Issue
Block a user