#include "system_metrics.hxx"
-static double calc_cpu_usage(struct cpu_times &prev_ct, const struct cpu_times &ct);
double
system_metrics::cpu_usage()
return ret;
}
+
+
//
// util functions
//
-static double
+double
calc_cpu_usage(struct cpu_times &prev_ct, const struct cpu_times &ct)
{
uint64_t idle = ct.idle;
// () is a magic value that signals the end of the list, see _SM_DISCARD_IF_END().\r
#define _SM_FOREACH(...) _SM_FOREACH2(__VA_ARGS__, ())\r
\r
-#define _SM_ADD_FIELD(field_name) { #field_name , &std::remove_pointer<decltype(this)>::type::name }\r
+#define _SM_ADD_FIELD(field_name) { #field_name , &std::remove_pointer<decltype(this)>::type::field_name }\r
\r
// SM_MAPIFY_STRUCT(type, field1, ...) is a macro that adds std::map-like at()\r
// and contains() methods to a struct for specified fields. All mapified fields\r
} \\r
bool contains(const std::string_view &field) { \\r
return static_cast<bool>(this->_sm_fields_map().count(field)); \\r
- } \\r
- }\r
+ }\r
+\r
#pragma once
-#include <cstdef>
+#include <cstddef>
#include <memory>
#include <string>
#include <vector>
+#include <unordered_map>
#include <stdint.h>
+#include <string_view>
+
+#include "sm_mapify.hxx"
#if defined(__GNUC__) || defined(__clang__)
# define SM_LIKELY(x) __builtin_expect(!!(x),1)
uint64_t pid = 0;
uint64_t ppid = 0;
std::string path;
+ double cpu_usage = -1;
};
class system_metrics {
struct cpu_times prev_cpu_times;
std::vector<struct cpu_times> prev_per_cpu_times;
std::unique_ptr<struct sm_private> _priv;
+ std::unordered_map<uint64_t, struct cpu_times > prev_proc_cpu_times;
+};
+
+struct process_list_fields {
+ bool pid = true;
+ bool cpu_usage;
+ bool name;
+ SM_MAPIFY_STRUCT(bool, pid, cpu_usage, name)
};
+
+double calc_cpu_usage(struct cpu_times &prev_ct, const struct cpu_times &ct);
#include "win32_exception.hxx"
#include <string>
-#include <vector>
#include <mutex>
#include <psapi.h>
{
auto &buf = this->_priv->proc_info_buf;
+ struct cpu_times ct;
for (;;) {
ULONG ret_size_bytes;
+
+ ct = this->cpu_times();
NTSTATUS status = NtQuerySystemInformation(
SystemProcessInformation,
buf.data(),
break;
}
+ uint64_t total_cpu;
+
SYSTEM_PROCESS_INFORMATION *info = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(&buf[0]);
std::vector<struct process> ret;
for (;;) {
p.pid = reinterpret_cast<uint64_t>(info->UniqueProcessId);
unicode_string_to_string(info->ImageName, p.path);
+ struct cpu_times t;
+ t.user = info->UserTime.QuadPart;
+ t.system = info->KernelTime.QuadPart;
+ t.idle = ct.system + ct.idle + ct.user - t.user - t.system;
+
+ p.cpu_usage = calc_cpu_usage(
+ this->prev_proc_cpu_times[p.pid],
+ t
+ );
+
ret.push_back(p);
+
if (info->NextEntryOffset)
info = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(
reinterpret_cast<std::byte*>(info) + info->NextEntryOffset
RETVAL
AV*
-system_metrics::process_list()
+system_metrics::process_list(...)
CODE:
+ //if (items%2==0)
+ // croak("uneven");
+ process_list_fields fields;
+ for (size_t i = 1; items > i; i+=1) {
+ STRLEN len;
+ char *key = SvPV(ST(i), len);
+ fields.at({key,len}) = true;
+ }
+ printf("pid: %d\ncpu_usage: %d\nname: %d", (int)fields.pid, (int)fields.cpu_usage, (int)fields.name);
std::vector<struct process> proc_list;
SM_BEGIN_WRAP_EXCEPTION
proc_list = THIS->process_list();
HV *proc_hv = newHV();
hv_stores(proc_hv, "pid", newSVuv(p.pid));
hv_stores(proc_hv, "path", newSVpvn_flags(p.path.data(), p.path.size(), 0));
+ hv_stores(proc_hv, "cpu_usage", newSVnv(p.cpu_usage));
AvARRAY(ret)[i++] = newRV_noinc((SV*)proc_hv);
}
RETVAL = ret;