diff --git a/contrib/csnippets/config.h.in b/contrib/csnippets/config.h.in index 0690bb6..970d94a 100644 --- a/contrib/csnippets/config.h.in +++ b/contrib/csnippets/config.h.in @@ -4,7 +4,6 @@ #ifndef CSNIPPETS_CONFIG_H #define CSNIPPETS_CONFIG_H -#cmakedefine01 HAVE_CLOCK_GETTIME #cmakedefine01 HAVE_SYSLOG #cmakedefine01 HAVE_LOCALTIME_R diff --git a/contrib/csnippets/utils/buffer.h b/contrib/csnippets/utils/buffer.h index 94e1302..62ea3d8 100644 --- a/contrib/csnippets/utils/buffer.h +++ b/contrib/csnippets/utils/buffer.h @@ -267,18 +267,18 @@ static inline bool vbuf_boundcheck(struct vbuffer *vbuf) /** * @brief Adjust vbuffer allocation while preserving data. * @param vbuf If NULL, new buffer may be allocated. - * @param want Expected vbuffer overall size in bytes. + * @param want Expected vbuffer overall capacity in bytes. * @return If failed, the allocation remains unchanged. * @details usage: `vbuf = VBUF_RESIZE(vbuf, 0); // shrink the buffer to fit` */ #define VBUF_RESIZE(vbuf, want) \ (VBUF_ASSERT_BOUND(vbuf), \ - vbuf_alloc((vbuf), MAX(VBUF_LEN(vbuf), (want)))) + vbuf_alloc((vbuf), MAX((vbuf) != NULL ? (vbuf)->len : 0, (want)))) /** * @brief Expand vbuffer allocation. * @param vbuf If NULL, new buffer may be allocated. - * @param want Expected vbuffer overall size in bytes. + * @param want Expected minimum vbuffer overall capacity in bytes. * @return If failed, the allocation remains unchanged. * @details usage: `vbuf = VBUF_RESERVE(vbuf, 100);` */ @@ -301,7 +301,7 @@ static inline bool vbuf_boundcheck(struct vbuffer *vbuf) /** * @brief Append literal string to vbuffer. - * @param vbuf If NULL, the minimum required size is allocated. + * @param vbuf If NULL, new buffer is allocated. * @return If the allocation fails, the data is truncated. * @see VBUF_APPEND * @details usage: `vbuf = VBUF_APPENDSTR(vbuf, "some string");` @@ -312,7 +312,7 @@ static inline bool vbuf_boundcheck(struct vbuffer *vbuf) /** * @brief Append formatted string to vbuffer. - * @param vbuf If NULL, the minimum required size is allocated. + * @param vbuf If NULL, new buffer is allocated. * @return If the allocation fails, the data is truncated. * @see VBUF_APPEND * @details usage: vbuf = VBUF_APPENDF(vbuf, "%s: %s\r\n", "Content-Type", "text/plain"); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 84c3199..21501a4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,7 +18,6 @@ else() endif() include(CheckSymbolExists) -check_symbol_exists(clock_gettime "time.h" HAVE_CLOCK_GETTIME) check_symbol_exists(sendmmsg "sys/socket.h" HAVE_API_SENDMMSG) check_symbol_exists(SYS_sendmmsg "sys/syscall.h" HAVE_SYS_SENDMMSG) check_symbol_exists(recvmmsg "sys/socket.h" HAVE_API_RECVMMSG) diff --git a/src/server.c b/src/server.c index 30c71a5..8649cad 100644 --- a/src/server.c +++ b/src/server.c @@ -398,7 +398,8 @@ server_new(struct ev_loop *loop, const struct config *restrict conf) conf->keepalive * 3.0 + ping_timeout, 10.0, 1800.0), .ping_timeout = ping_timeout, .time_wait = conf->time_wait, - .last_clock = -1, + .last_cputime = TSTAMP_NIL, + .last_monotime = TSTAMP_NIL, }; { @@ -772,36 +773,31 @@ static struct vbuffer *append_traffic_stats( /* total */ tcp_rx, tcp_tx, kcp_rx, kcp_tx, pkt_rx, pkt_tx); } -static double clock_cputime(void) -{ -#if HAVE_CLOCK_GETTIME - struct timespec t; - if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t)) { - return NAN; - } - return t.tv_sec + t.tv_nsec * 1e-9; -#else - const clock_t clk = clock(); - if (clk == (clock_t)-1) { - return NAN; - } - return (double)clk / CLOCKS_PER_SEC; -#endif -} - -static bool update_load( +static const char *format_load( struct server *restrict s, char *buf, const size_t bufsize, - const double dt) + const char *fail) { - const double last = s->last_clock; - const double now = clock_cputime(); - s->last_clock = now; - if (!isfinite(now) || !isfinite(last) || now < last) { - return false; + const char *load_str = fail; + double monotime, cputime; + struct timespec t; + if (clock_gettime(CLOCK_MONOTONIC, &t)) { + return load_str; } - const double load = (now - last) / dt * 100.0; - (void)snprintf(buf, bufsize, "%.03f%%", load); - return true; + monotime = t.tv_sec + t.tv_nsec * 1e-9; + if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t)) { + return load_str; + } + cputime = t.tv_sec + t.tv_nsec * 1e-9; + if (s->last_cputime != TSTAMP_NIL && s->last_monotime != TSTAMP_NIL) { + const double busy = cputime - s->last_cputime; + const double total = monotime - s->last_monotime; + const double load = busy / total * 100.0; + (void)snprintf(buf, bufsize, "%.03f%%", load); + load_str = buf; + } + s->last_cputime = cputime; + s->last_monotime = monotime; + return load_str; } struct vbuffer * @@ -864,18 +860,13 @@ struct vbuffer *server_stats( buf = append_traffic_stats(buf, &s->stats); - { - char load_buf[16]; - const char *load_str = "(unknown)"; - if (update_load(s, load_buf, sizeof(load_buf), dt)) { - load_str = load_buf; - } - FORMAT_BYTES(dpkt_rx, dstats.pkt_rx / dt); - FORMAT_BYTES(dpkt_tx, dstats.pkt_tx / dt); - buf = VBUF_APPENDF( - buf, " = load: %s; pkt: %s/s, %s/s; uptime: %s\n", - load_str, dpkt_rx, dpkt_tx, uptime_str); - } + FORMAT_BYTES(dpkt_rx, dstats.pkt_rx / dt); + FORMAT_BYTES(dpkt_tx, dstats.pkt_tx / dt); + char load_buf[16]; + buf = VBUF_APPENDF( + buf, " = load: %s; pkt: %s/s, %s/s; uptime: %s\n", + format_load(s, load_buf, sizeof(load_buf), "(unknown)"), + dpkt_rx, dpkt_tx, uptime_str); #undef FORMAT_BYTES /* rotate stats */ diff --git a/src/server.h b/src/server.h index 423dc48..4be8215 100644 --- a/src/server.h +++ b/src/server.h @@ -85,7 +85,7 @@ struct server { ev_tstamp started; ev_tstamp last_stats_time; ev_tstamp last_resolve_time; - double last_clock; + double last_cputime, last_monotime; }; };