[gnome-system-monitor] Cache cgroup expansive parsing by file and line which makes it even faster than the original C code.
- From: Benoît Dejean <bdejean src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-system-monitor] Cache cgroup expansive parsing by file and line which makes it even faster than the original C code.
- Date: Fri, 28 Oct 2016 13:45:34 +0000 (UTC)
commit 0337fe894ddac54e0dd814cb548a8159163fd895
Author: Benoît Dejean <bdejean gmail com>
Date: Fri Oct 28 10:08:57 2016 +0200
Cache cgroup expansive parsing by file and line which makes it even faster than the
original C code.
Parse all cgroups because previously systemd cgroups were ignored.
Condensed output for cgroups with multiple categories.
src/cgroups.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 88 insertions(+), 27 deletions(-)
---
diff --git a/src/cgroups.cpp b/src/cgroups.cpp
index b75b9fb..42d1eef 100644
--- a/src/cgroups.cpp
+++ b/src/cgroups.cpp
@@ -2,6 +2,10 @@
#include "cgroups.h"
#include "util.h"
+#include <map>
+#include <unordered_map>
+#include <utility>
+
bool
cgroups_enabled(void)
{
@@ -16,43 +20,100 @@ cgroups_enabled(void)
return has_cgroups;
}
-static std::pair<Glib::ustring, Glib::ustring>
-parse_cgroup_line(const Glib::ustring& line) {
- auto split = std::vector<Glib::ustring>(Glib::Regex::split_simple(":", line));
- if (split.size() < 3) { return std::make_pair("", ""); }
- auto cgroups = split.at(2);
- if (cgroups.empty() || cgroups == "/") { return std::make_pair("", ""); }
- auto category = split.at(1);
- if (category.find("name=") != category.npos) { return std::make_pair("", ""); }
- return std::make_pair(category, cgroups);
+
+static const std::pair<std::string, std::string> &
+parse_cgroup_line(const std::string& line) {
+
+ static std::unordered_map<std::string, std::pair<std::string, std::string>> line_cache;
+
+ auto it = line_cache.insert({line, {"", ""} });
+ if (it.second) { // inserted new
+ std::string::size_type cat_start, name_start;
+
+ if ((cat_start = line.find(':')) != std::string::npos
+ && (name_start = line.find(':', cat_start + 1)) != std::string::npos) {
+
+ // printf("%s %lu %lu\n", line.c_str(), cat_start, name_start);
+ auto cat = line.substr(cat_start + 1, name_start - cat_start - 1);
+ auto name = line.substr(name_start + 1);
+
+ // strip the name= prefix
+ if (cat.find("name=") == 0) {
+ cat.erase(0, 5);
+ }
+
+ if (!name.empty() && name != "/") {
+ it.first->second = {name, cat};
+ }
+ }
+ }
+
+ return it.first->second;
}
-static Glib::ustring
-get_process_cgroup_string(unsigned int pid) {
- if (not cgroups_enabled())
- return "";
+
+static const std::string&
+get_process_cgroup_string(pid_t pid) {
+
+ static std::unordered_map<std::string, std::string> file_cache{ {"", ""} };
/* read out of /proc/pid/cgroup */
- auto path = Glib::ustring::compose("/proc/%1/cgroup", pid);
- Glib::ustring text;
- try { text = Glib::file_get_contents(path); } catch (...) { return ""; }
- auto lines = std::vector<Glib::ustring>(Glib::Regex::split_simple("\n", text));
-
- Glib::ustring cgroup_string;
- for (auto& line : lines) {
- auto data = parse_cgroup_line(line);
- if (data.first.empty() || data.second.empty()) { continue; }
- if (!cgroup_string.empty()) { cgroup_string += ", "; }
- cgroup_string += Glib::ustring::compose("%1 (%2)", data.second, data.first);
+ auto path = "/proc/" + std::to_string(pid) + "/cgroup";
+ std::string text;
+ try { text = Glib::file_get_contents(path); } catch (...) { return file_cache[""]; }
+
+ auto it = file_cache.insert({ text, "" });
+
+ if (it.second) { // inserted new
+
+ // name -> [cat...], sorted by name;
+ std::map<std::string, std::vector<std::string>> names;
+
+ std::string::size_type last = 0, eol;
+
+ // for each line in the file
+ while ((eol = text.find('\n', last)) != std::string::npos) {
+ auto line = text.substr(last, eol - last);
+ last = eol + 1;
+
+ const auto& p = parse_cgroup_line(line);
+ if (!p.first.empty()) {
+ names[p.first].push_back(p.second);
+ }
+ }
+
+
+ // name (cat1, cat2), ...
+ // sorted by name, categories
+ std::string groups;
+
+ for (auto& i : names) {
+ std::string cats;
+ std::sort(begin(i.second), end(i.second));
+
+ for (const auto & cat : i.second) {
+ if (!cats.empty()) { cats += ", "; }
+ cats += cat;
+ }
+
+ if (!groups.empty()) { groups += ", "; }
+ groups += i.first + " (" + cats + ')';
+ }
+
+ it.first->second = std::move(groups);
}
- return cgroup_string;
+ return it.first->second;
}
+
void get_process_cgroup_info(ProcInfo& info) {
- auto cgroup_string = get_process_cgroup_string(info.pid);
+ if (not cgroups_enabled())
+ return;
+ const auto& cgroup_string = get_process_cgroup_string(info.pid);
g_free(info.cgroup_name);
- info.cgroup_name = cgroup_string.empty() ? nullptr : g_strdup(cgroup_string.c_str());
+ info.cgroup_name = g_strdup(cgroup_string.c_str());
}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]