From 9a065ead487d1d655b8a73e84ee68e2c51ee21b0 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Fri, 31 Oct 2014 17:25:24 +1000 Subject: os_mon: cpu_sup should use native sysctl/libkvm calls on BSD This avoids forking off with os:cmd every time we just want to collect the load averages. riak does this every second, which results in a lot of unnecessary load. --- erts/configure.in | 9 ++++ lib/os_mon/c_src/cpu_sup.c | 108 ++++++++++++++++++++++++++++++++++++++++++++- lib/os_mon/src/cpu_sup.erl | 84 +++++++---------------------------- 3 files changed, 130 insertions(+), 71 deletions(-) diff --git a/erts/configure.in b/erts/configure.in index 1676d3d216..c41a5bec5a 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -4705,9 +4705,18 @@ AC_CHECK_LIB(kstat, kstat_open, [ CPU_SUP_LIBS="$CPU_SUP_LIBS -lkstat" ]) +AC_CHECK_LIB(kvm, kvm_open, [ + os_mon_programs="$os_mon_programs cpu_sup" + CPU_SUP_LIBS="$CPU_SUP_LIBS -lkvm" + ]) + case $host_os in solaris2*) os_mon_programs="$os_mon_programs ferrule mod_syslog" ;; + darwin*) + os_mon_programs="$os_mon_programs cpu_sup" ;; + openbsd*) + os_mon_programs="$os_mon_programs cpu_sup" ;; linux*) os_mon_programs="$os_mon_programs cpu_sup" ;; esac diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c index e9fd75a32c..4198cc73f3 100644 --- a/lib/os_mon/c_src/cpu_sup.c +++ b/lib/os_mon/c_src/cpu_sup.c @@ -31,13 +31,27 @@ #include #include +#if (defined(__APPLE__) && defined(__MACH__)) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) +#include +#include +#include +#include +#endif +#if defined(__FreeBSD__) || defined(__DragonFly__) +#include +#include +#endif + #if defined(__sun__) #include #endif -#include #include +#if defined(__sun__) || defined(__linux__) +#include +#endif + #if defined(__linux__) #include /* strlen */ @@ -128,6 +142,11 @@ static void send(unsigned int data); static void sendv(unsigned int data[], int ints); static void error(char* err_msg); +#if (defined(__APPLE__) && defined(__MACH__)) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) +static void bsd_count_procs(void); +static void bsd_loadavg(int); +#endif + #if defined(__sun__) static kstat_ctl_t *kstat_ctl; #endif @@ -179,14 +198,98 @@ int main(int argc, char** argv) { case AVG1: send(misc_measure("avenrun_1min")); break; case AVG5: send(misc_measure("avenrun_5min")); break; case AVG15: send(misc_measure("avenrun_15min")); break; +#elif defined(__OpenBSD__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__DragonFly__) + case NPROCS: bsd_count_procs(); break; + case AVG1: bsd_loadavg(0); break; + case AVG5: bsd_loadavg(1); break; + case AVG15: bsd_loadavg(2); break; #endif +#if defined(__sun__) || defined(__linux__) case UTIL: util_measure(&rv,&sz); sendv(rv, sz); break; +#endif case QUIT: free((void*)rv); return 0; default: error("Bad command"); break; } } return 0; /* supress warnings */ } + +/* ---------------------------- * + * BSD stat functions * + * ---------------------------- */ +#if defined(__OpenBSD__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__DragonFly__) + +static void bsd_loadavg(int idx) { + double avgs[3]; + if (getloadavg(avgs, 3) < 0) { + error(strerror(errno)); + return; + } + send((unsigned int)(avgs[idx] * 256)); +} + +#endif + +#if defined(__OpenBSD__) + +static void bsd_count_procs(void) { + int err, nproc; + size_t len = sizeof(nproc); + int mib[] = { CTL_KERN, KERN_NPROCS }; + + err = sysctl(mib, sizeof(mib) / sizeof(mib[0]), &nproc, &len, NULL, 0); + if (err) { + error(strerror(errno)); + return; + } + + send((unsigned int)nproc); +} + +#elif defined(__FreeBSD__) || defined(__DragonFly__) + +static void bsd_count_procs(void) { + kvm_t *kd; + struct kinfo_proc *kp; + char err[_POSIX2_LINE_MAX]; + int cnt = 0; + + if ((kd = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, err)) == NULL) { + error(err); + return; + } + +#if defined(KERN_PROC_PROC) + if ((kp = kvm_getprocs(kd, KERN_PROC_PROC, 0, &cnt)) == NULL) { +#else + if ((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &cnt)) == NULL) { +#endif + error(strerror(errno)); + return; + } + + (void)kvm_close(kd); + send((unsigned int)cnt); +} + +#elif (defined(__APPLE__) && defined(__MACH__)) + +static void bsd_count_procs(void) { + int err; + size_t len = 0; + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + + err = sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0); + if (err) { + error(strerror(errno)); + return; + } + + send((unsigned int)(len / sizeof(struct kinfo_proc))); +} + +#endif + /* ---------------------------- * * Linux stat functions * * ---------------------------- */ @@ -474,7 +577,8 @@ static void error(char* err_msg) { buffer[i++] = '\n'; /* try to use one write only */ - if(write(FD_ERR, buffer, i)); + if(write(FD_ERR, buffer, i)) + ; exit(-1); } diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl index 1f088ecbde..75d31ef703 100644 --- a/lib/os_mon/src/cpu_sup.erl +++ b/lib/os_mon/src/cpu_sup.erl @@ -217,8 +217,6 @@ code_change(_OldVsn, State, _Extra) -> %% internal functions %%---------------------------------------------------------------------- -get_uint32_measurement(Request, #internal{port = P, os_type = {unix, sunos}}) -> - port_server_call(P, Request); get_uint32_measurement(Request, #internal{os_type = {unix, linux}}) -> {ok,F} = file:open("/proc/loadavg",[read,raw]), {ok,D} = file:read(F,24), @@ -231,67 +229,13 @@ get_uint32_measurement(Request, #internal{os_type = {unix, linux}}) -> ?ping -> 4711; ?nprocs -> PTotal end; -get_uint32_measurement(Request, #internal{os_type = {unix, freebsd}}) -> - D = os:cmd("/sbin/sysctl -n vm.loadavg") -- "\n", - {ok,[Load1,Load5,Load15],_} = io_lib:fread("{ ~f ~f ~f }", D), - %% We could count the lines from the ps command as well - case Request of - ?avg1 -> sunify(Load1); - ?avg5 -> sunify(Load5); - ?avg15 -> sunify(Load15); - ?ping -> 4711; - ?nprocs -> - Ps = os:cmd("/bin/ps -ax | /usr/bin/wc -l"), - {ok, [N], _} = io_lib:fread("~d", Ps), - N-1 - end; -get_uint32_measurement(Request, #internal{os_type = {unix, dragonfly}}) -> - D = os:cmd("/sbin/sysctl -n vm.loadavg") -- "\n", - {ok,[Load1,Load5,Load15],_} = io_lib:fread("{ ~f ~f ~f }", D), - %% We could count the lines from the ps command as well - case Request of - ?avg1 -> sunify(Load1); - ?avg5 -> sunify(Load5); - ?avg15 -> sunify(Load15); - ?ping -> 4711; - ?nprocs -> - Ps = os:cmd("/bin/ps -ax | /usr/bin/wc -l"), - {ok, [N], _} = io_lib:fread("~d", Ps), - N-1 - end; -get_uint32_measurement(Request, #internal{os_type = {unix, openbsd}}) -> - D = os:cmd("/sbin/sysctl -n vm.loadavg") -- "\n", - {ok, [L1, L5, L15], _} = io_lib:fread("~f ~f ~f", D), - case Request of - ?avg1 -> sunify(L1); - ?avg5 -> sunify(L5); - ?avg15 -> sunify(L15); - ?ping -> 4711; - ?nprocs -> - Ps = os:cmd("/bin/ps -ax | /usr/bin/wc -l"), - {ok, [N], _} = io_lib:fread("~d", Ps), - N-1 - end; -get_uint32_measurement(Request, #internal{os_type = {unix, darwin}}) -> - %% Get the load average using uptime, overriding Locale setting. - D = os:cmd("LANG=C LC_ALL=C uptime") -- "\n", - %% Here is a sample uptime string from Mac OS 10.3.8 (C Locale): - %% "11:17 up 12 days, 20:39, 2 users, load averages: 1.07 0.95 0.66" - %% The safest way to extract the load averages seems to be grab everything - %% after the last colon and then do an fread on that. - Avg = lists:reverse(hd(string:tokens(lists:reverse(D), ":"))), - {ok,[L1,L5,L15],_} = io_lib:fread("~f ~f ~f", Avg), - - case Request of - ?avg1 -> sunify(L1); - ?avg5 -> sunify(L5); - ?avg15 -> sunify(L15); - ?ping -> 4711; - ?nprocs -> - Ps = os:cmd("/bin/ps -ax | /usr/bin/wc -l"), - {ok, [N], _} = io_lib:fread("~d", Ps), - N-1 - end; +get_uint32_measurement(Request, #internal{port = P, os_type = {unix, Sys}}) when + Sys == sunos; + Sys == dragonfly; + Sys == openbsd; + Sys == freebsd; + Sys == darwin -> + port_server_call(P, Request); get_uint32_measurement(Request, #internal{os_type = {unix, Sys}}) when Sys == irix64; Sys == irix -> %% Get the load average using uptime. @@ -541,14 +485,16 @@ measurement_server_init() -> process_flag(trap_exit, true), OS = os:type(), Server = case OS of - {unix, Flavor} when Flavor==sunos; - Flavor==linux -> - {ok, Pid} = port_server_start_link(), - Pid; - {unix, Flavor} when Flavor==darwin; + {unix, Flavor} when + Flavor==sunos; + Flavor==linux; + Flavor==darwin; Flavor==freebsd; Flavor==dragonfly; - Flavor==openbsd; + Flavor==openbsd -> + {ok, Pid} = port_server_start_link(), + Pid; + {unix, Flavor} when Flavor==irix64; Flavor==irix -> not_used; -- cgit v1.2.3 From a13e075a25d27e690e68f9205e9d546559f3a294 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Mon, 3 Nov 2014 09:31:43 +1000 Subject: os_mon: rename send() to sendi() in cpu_sup.c Without this, cpu_sup.c won't compile on FreeBSD, as the name overlaps with the send() socket call. --- lib/os_mon/c_src/cpu_sup.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c index 4198cc73f3..20bb9ce391 100644 --- a/lib/os_mon/c_src/cpu_sup.c +++ b/lib/os_mon/c_src/cpu_sup.c @@ -138,7 +138,7 @@ static void util_measure(unsigned int **result_vec, int *result_sz); #if defined(__sun__) static unsigned int misc_measure(char* name); #endif -static void send(unsigned int data); +static void sendi(unsigned int data); static void sendv(unsigned int data[], int ints); static void error(char* err_msg); @@ -192,12 +192,12 @@ int main(int argc, char** argv) { error("Erlang has closed"); switch(cmd) { - case PING: send(4711); break; + case PING: sendi(4711); break; #if defined(__sun__) - case NPROCS: send(misc_measure("nproc")); break; - case AVG1: send(misc_measure("avenrun_1min")); break; - case AVG5: send(misc_measure("avenrun_5min")); break; - case AVG15: send(misc_measure("avenrun_15min")); break; + case NPROCS: sendi(misc_measure("nproc")); break; + case AVG1: sendi(misc_measure("avenrun_1min")); break; + case AVG5: sendi(misc_measure("avenrun_5min")); break; + case AVG15: sendi(misc_measure("avenrun_15min")); break; #elif defined(__OpenBSD__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__DragonFly__) case NPROCS: bsd_count_procs(); break; case AVG1: bsd_loadavg(0); break; @@ -225,7 +225,7 @@ static void bsd_loadavg(int idx) { error(strerror(errno)); return; } - send((unsigned int)(avgs[idx] * 256)); + sendi((unsigned int)(avgs[idx] * 256)); } #endif @@ -243,7 +243,7 @@ static void bsd_count_procs(void) { return; } - send((unsigned int)nproc); + sendi((unsigned int)nproc); } #elif defined(__FreeBSD__) || defined(__DragonFly__) @@ -269,7 +269,7 @@ static void bsd_count_procs(void) { } (void)kvm_close(kd); - send((unsigned int)cnt); + sendi((unsigned int)cnt); } #elif (defined(__APPLE__) && defined(__MACH__)) @@ -285,7 +285,7 @@ static void bsd_count_procs(void) { return; } - send((unsigned int)(len / sizeof(struct kinfo_proc))); + sendi((unsigned int)(len / sizeof(struct kinfo_proc))); } #endif @@ -523,7 +523,7 @@ static void util_measure(unsigned int **result_vec, int *result_sz) { * Generic functions * * ---------------------------- */ -static void send(unsigned int data) { sendv(&data, 1); } +static void sendi(unsigned int data) { sendv(&data, 1); } static void sendv(unsigned int data[], int ints) { static unsigned char *buf = NULL; -- cgit v1.2.3 From 428492feee831f610a7651fd98c9f4d75e34e726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 5 May 2015 16:40:41 +0200 Subject: erts: Fix configure.in Don't repeat cpu_sup in os_mon_programs - some OS gets confused, i.e. illumos. --- erts/configure.in | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/erts/configure.in b/erts/configure.in index c41a5bec5a..e6ba48f169 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -4701,12 +4701,12 @@ AC_SUBST(os_mon_programs) AC_SUBST(CPU_SUP_LIBS) AC_CHECK_LIB(kstat, kstat_open, [ - os_mon_programs="$os_mon_programs cpu_sup" + use_cpu_sup=yes CPU_SUP_LIBS="$CPU_SUP_LIBS -lkstat" ]) AC_CHECK_LIB(kvm, kvm_open, [ - os_mon_programs="$os_mon_programs cpu_sup" + use_cpu_sup=yes CPU_SUP_LIBS="$CPU_SUP_LIBS -lkvm" ]) @@ -4714,14 +4714,17 @@ case $host_os in solaris2*) os_mon_programs="$os_mon_programs ferrule mod_syslog" ;; darwin*) - os_mon_programs="$os_mon_programs cpu_sup" ;; + use_cpu_sup=yes ;; openbsd*) - os_mon_programs="$os_mon_programs cpu_sup" ;; + use_cpu_sup=yes ;; linux*) - os_mon_programs="$os_mon_programs cpu_sup" ;; + use_cpu_sup=yes ;; esac - +if test "$use_cpu_sup" = "yes"; then + os_mon_programs="$os_mon_programs cpu_sup" +fi + AC_ARG_WITH(javac, AS_HELP_STRING([--with-javac=JAVAC], [specify Java compiler to use]) AS_HELP_STRING([--with-javac], [use a Java compiler if found (default)]) -- cgit v1.2.3