system
parent
2cc2b2d262
commit
93f56ebcb2
|
@ -9,22 +9,29 @@
|
||||||
|
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#else
|
#else
|
||||||
#include <x86intrin.h>
|
|
||||||
|
#include <x86intrin.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#endif
|
#endif
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace blt::system {
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace blt::system
|
||||||
|
{
|
||||||
//#ifdef __GNUC__
|
//#ifdef __GNUC__
|
||||||
// #define GNU_INLINE __attribute__((__gnu_inline__, __always_inline__))
|
// #define GNU_INLINE __attribute__((__gnu_inline__, __always_inline__))
|
||||||
//#else
|
//#else
|
||||||
// #define GNU_INLINE
|
// #define GNU_INLINE
|
||||||
//#endif
|
//#endif
|
||||||
inline std::uint64_t rdtsc(){
|
inline std::uint64_t rdtsc()
|
||||||
|
{
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
||||||
#else
|
#else
|
||||||
|
@ -33,6 +40,144 @@ namespace blt::system {
|
||||||
}
|
}
|
||||||
// TODO: system memory and current CPU usage. (Linux Only currently)
|
// TODO: system memory and current CPU usage. (Linux Only currently)
|
||||||
|
|
||||||
|
struct linux_proc_stat
|
||||||
|
{
|
||||||
|
// pid %d
|
||||||
|
std::int32_t PID;
|
||||||
|
// comm %s
|
||||||
|
std::string exec_name;
|
||||||
|
/*
|
||||||
|
* R Running
|
||||||
|
* S Sleeping in an interruptible wait
|
||||||
|
* D Waiting in uninterruptible disk sleep
|
||||||
|
* Z Zombie
|
||||||
|
* T Stopped (on a signal) or (before Linux 2.6.33) trace stopped
|
||||||
|
* t Tracing stop (Linux 2.6.33 onward)
|
||||||
|
* W Paging (only before Linux 2.6.0)
|
||||||
|
* X Dead (from Linux 2.6.0 onward)
|
||||||
|
* x Dead (Linux 2.6.33 to 3.13 only)
|
||||||
|
* K Wakekill (Linux 2.6.33 to 3.13 only)
|
||||||
|
* W Waking (Linux 2.6.33 to 3.13 only)
|
||||||
|
* P Parked (Linux 3.9 to 3.13 only)
|
||||||
|
* I Idle (Linux 4.14 onward)
|
||||||
|
*/
|
||||||
|
// state %c
|
||||||
|
char state;
|
||||||
|
// pid of parent
|
||||||
|
std::int32_t parent_pid;
|
||||||
|
// group id of process
|
||||||
|
std::int32_t group_id;
|
||||||
|
// session id of process
|
||||||
|
std::int32_t session_id;
|
||||||
|
// controlling terminal
|
||||||
|
std::int32_t tty_nr;
|
||||||
|
// The ID of the foreground process group of the controlling terminal of the process.
|
||||||
|
std::int32_t tpgid;
|
||||||
|
std::uint32_t flags;
|
||||||
|
std::uint64_t minflt;
|
||||||
|
std::uint64_t cminflt;
|
||||||
|
std::uint64_t majflt;
|
||||||
|
std::uint64_t cmajflt;
|
||||||
|
// amount of time process has been scheduled in user mode measured in clock ticks (divide by sysconf(_SC_CLK_TCK))
|
||||||
|
std::uint64_t utime;
|
||||||
|
// amount of time that this process has been scheduled in kernel mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
|
||||||
|
std::uint64_t stime;
|
||||||
|
// children times
|
||||||
|
std::int64_t cutime;
|
||||||
|
std::int64_t cstime;
|
||||||
|
std::int64_t priority;
|
||||||
|
std::int64_t nice;
|
||||||
|
std::int64_t num_threads;
|
||||||
|
std::int64_t itrealvalue;
|
||||||
|
// The time the process started after system boot. Since Linux 2.6, the value is expressed in clock ticks (divide by sysconf(_SC_CLK_TCK)).
|
||||||
|
std::uint64_t starttime;
|
||||||
|
// Virtual memory size in bytes.
|
||||||
|
std::uint64_t vsize;
|
||||||
|
// Resident Set Size: number of pages the process has in real memory.
|
||||||
|
// This is just the pages which count toward text, data, or stack space. This does not include pages which have not been demand-loaded
|
||||||
|
// in, or which are swapped out. This value is inaccurate; see /proc/pid/statm below.
|
||||||
|
std::int64_t rss;
|
||||||
|
// Current soft limit in bytes on the rss of the process; see the description of RLIMIT_RSS in getrlimit(2).
|
||||||
|
std::uint64_t rsslim;
|
||||||
|
std::uint64_t startcode;
|
||||||
|
std::uint64_t endcode;
|
||||||
|
std::uint64_t startstack;
|
||||||
|
std::uint64_t kstkesp;
|
||||||
|
std::uint64_t signal;
|
||||||
|
std::uint64_t blocked;
|
||||||
|
std::uint64_t sigignore;
|
||||||
|
std::uint64_t sigcatch;
|
||||||
|
std::uint64_t wchan;
|
||||||
|
std::uint64_t nswap;
|
||||||
|
std::uint64_t cnswap;
|
||||||
|
std::int32_t exit_signal;
|
||||||
|
std::int32_t processor;
|
||||||
|
std::uint32_t rt_priority;
|
||||||
|
std::uint32_t policy;
|
||||||
|
std::uint64_t delayacct_blkio_ticks;
|
||||||
|
std::uint64_t guest_time;
|
||||||
|
std::int64_t cguest_time;
|
||||||
|
std::uint64_t start_data;
|
||||||
|
std::uint64_t end_data;
|
||||||
|
std::uint64_t start_brk;
|
||||||
|
std::uint64_t arg_start;
|
||||||
|
std::uint64_t arg_end;
|
||||||
|
std::uint64_t env_start;
|
||||||
|
std::uint64_t env_end;
|
||||||
|
std::int32_t exit_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct memory_info_t
|
||||||
|
{
|
||||||
|
// total program size (bytes) (same as VmSize in status)
|
||||||
|
std::uint64_t size;
|
||||||
|
// size of memory portions (bytes) (same as VmRSS in status)
|
||||||
|
std::uint64_t resident;
|
||||||
|
// number of bytes that are shared (i.e. backed by a file, same as RssFile+RssShmem in status)
|
||||||
|
std::uint64_t shared;
|
||||||
|
// number of bytes that are 'code' (not including libs; broken, includes data segment)
|
||||||
|
std::uint64_t text;
|
||||||
|
// number of pages of library (0)
|
||||||
|
std::uint64_t lib;
|
||||||
|
// number of bytes of data/stack (including libs; broken, includes library text)
|
||||||
|
std::uint64_t data;
|
||||||
|
// number of dirty pages (0)
|
||||||
|
std::uint64_t dt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct timeval {
|
||||||
|
time_t tv_sec; /* Seconds */
|
||||||
|
suseconds_t tv_usec; /* Microseconds */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rusage {
|
||||||
|
timeval ru_utime; /* user CPU time used */
|
||||||
|
timeval ru_stime; /* system CPU time used */
|
||||||
|
long ru_maxrss; /* maximum resident set size */
|
||||||
|
|
||||||
|
long ru_ixrss; /* integral shared memory size */
|
||||||
|
long ru_idrss; /* integral unshared data size */
|
||||||
|
long ru_isrss; /* integral unshared stack size */
|
||||||
|
|
||||||
|
long ru_minflt; /* page reclaims (soft page faults) */
|
||||||
|
long ru_majflt; /* page faults (hard page faults) */
|
||||||
|
|
||||||
|
long ru_nswap; /* swaps */
|
||||||
|
|
||||||
|
long ru_inblock; /* block input operations */
|
||||||
|
long ru_oublock; /* block output operations */
|
||||||
|
long ru_msgsnd; /* IPC messages sent */
|
||||||
|
long ru_msgrcv; /* IPC messages received */
|
||||||
|
long ru_nsignals; /* signals received */
|
||||||
|
long ru_nvcsw; /* voluntary context switches */
|
||||||
|
long ru_nivcsw; /* involuntary context switches */
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<blt::system::rusage> get_resources_process();
|
||||||
|
std::optional<blt::system::rusage> get_resources_thread();
|
||||||
|
|
||||||
|
memory_info_t get_memory_process();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //BLT_SYSTEM_H
|
#endif //BLT_SYSTEM_H
|
||||||
|
|
|
@ -4,5 +4,139 @@
|
||||||
* See LICENSE file for license detail
|
* See LICENSE file for license detail
|
||||||
*/
|
*/
|
||||||
#include <blt/std/system.h>
|
#include <blt/std/system.h>
|
||||||
#include <blt/std/binary_tree.h>
|
#include <blt/std/logging.h>
|
||||||
#include <blt/math/math.h>
|
|
||||||
|
#include <sys/time.h> /* for struct timeval */
|
||||||
|
#include <climits> /* for CLK_TCK */
|
||||||
|
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <blt/std/loader.h>
|
||||||
|
#include "blt/std/assert.h"
|
||||||
|
|
||||||
|
inline long blt_get_page_size()
|
||||||
|
{
|
||||||
|
return sysconf(_SC_PAGESIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//struct proc_statm_t
|
||||||
|
//{
|
||||||
|
// // total program size (pages) (same as VmSize in status)
|
||||||
|
// std::uint64_t size;
|
||||||
|
// // size of memory portions (pages) (same as VmRSS in status)
|
||||||
|
// std::uint64_t resident;
|
||||||
|
// // number of pages that are shared (i.e. backed by a file, same as RssFile+RssShmem in status)
|
||||||
|
// std::uint64_t shared;
|
||||||
|
// // number of pages that are 'code' (not including libs; broken, includes data segment)
|
||||||
|
// std::uint64_t text;
|
||||||
|
// // number of pages of library (0)
|
||||||
|
// std::uint64_t lib;
|
||||||
|
// // number of pages of data/stack (including libs; broken, includes library text)
|
||||||
|
// std::uint64_t data;
|
||||||
|
// // number of dirty pages (0)
|
||||||
|
// std::uint64_t dt;
|
||||||
|
//};
|
||||||
|
|
||||||
|
blt::system::memory_info_t process_proc()
|
||||||
|
{
|
||||||
|
static auto page_size = blt_get_page_size();
|
||||||
|
|
||||||
|
auto str = blt::fs::getFile("/proc/self/statm");
|
||||||
|
|
||||||
|
auto data = blt::string::split(str, ' ');
|
||||||
|
BLT_ASSERT(data.size() == 7 && "Something went wrong when parsing /proc/self/statm! Expected 7 values!");
|
||||||
|
|
||||||
|
blt::system::memory_info_t mem {};
|
||||||
|
|
||||||
|
mem.size = page_size * std::stoull(data[0]);
|
||||||
|
mem.resident = page_size * std::stoull(data[1]);
|
||||||
|
mem.shared = page_size * std::stoull(data[2]);
|
||||||
|
mem.text = page_size * std::stoull(data[3]);
|
||||||
|
mem.lib = page_size * std::stoull(data[4]);
|
||||||
|
mem.data = page_size * std::stoull(data[5]);
|
||||||
|
mem.dt = page_size * std::stoull(data[6]);
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace blt
|
||||||
|
{
|
||||||
|
std::optional<system::rusage> get_resources(int who)
|
||||||
|
{
|
||||||
|
system::rusage usage{};
|
||||||
|
std::memset(&usage, 0, sizeof(system::rusage));
|
||||||
|
#ifdef WIN32
|
||||||
|
FILETIME starttime;
|
||||||
|
FILETIME exittime;
|
||||||
|
FILETIME kerneltime;
|
||||||
|
FILETIME usertime;
|
||||||
|
ULARGE_INTEGER li;
|
||||||
|
|
||||||
|
if (who != RUSAGE_SELF)
|
||||||
|
{
|
||||||
|
/* Only RUSAGE_SELF is supported in this implementation for now */
|
||||||
|
BLT_WARN("Only RUSAGE_SELF is supported in this implementation for now");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetProcessTimes(GetCurrentProcess(),
|
||||||
|
&starttime, &exittime, &kerneltime, &usertime) == 0)
|
||||||
|
{
|
||||||
|
BLT_WARN("Unable to get process resource usage, error: %d", GetLastError());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert FILETIMEs (0.1 us) to struct timeval */
|
||||||
|
memcpy(&li, &kerneltime, sizeof(FILETIME));
|
||||||
|
li.QuadPart /= 10L; /* Convert to microseconds */
|
||||||
|
usage.ru_stime.tv_sec = li.QuadPart / 1000000L;
|
||||||
|
usage.ru_stime.tv_usec = li.QuadPart % 1000000L;
|
||||||
|
|
||||||
|
memcpy(&li, &usertime, sizeof(FILETIME));
|
||||||
|
li.QuadPart /= 10L; /* Convert to microseconds */
|
||||||
|
usage.ru_utime.tv_sec = li.QuadPart / 1000000L;
|
||||||
|
usage.ru_utime.tv_usec = li.QuadPart % 1000000L;
|
||||||
|
#else
|
||||||
|
if (getrusage(who, (struct rusage*) &usage) != 0)
|
||||||
|
{
|
||||||
|
BLT_ERROR("Failed to get rusage %d", errno);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<system::rusage> system::get_resources_process()
|
||||||
|
{
|
||||||
|
return get_resources(RUSAGE_SELF);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<system::rusage> system::get_resources_thread()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return get_resources(RUSAGE_SELF);
|
||||||
|
#else
|
||||||
|
return get_resources(RUSAGE_THREAD);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
system::memory_info_t system::get_memory_process()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
BLT_WARN("Unsupported OS");
|
||||||
|
return {};
|
||||||
|
#else
|
||||||
|
|
||||||
|
return process_proc();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue