This is an automated email from the ASF dual-hosted git repository.
kgiusti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
The following commit(s) were added to refs/heads/master by this push:
new 7e7e8a0 DISPATCH-1572: (partial fix) heuristic to determine available
RAM
7e7e8a0 is described below
commit 7e7e8a0f7f588870538c492a296cb397feaf8e4f
Author: Kenneth Giusti <[email protected]>
AuthorDate: Wed Feb 12 09:36:58 2020 -0500
DISPATCH-1572: (partial fix) heuristic to determine available RAM
The patch merely implements a form of memory detection. Additional
work remains to implement low memory mitigation.
---
.../qpid/dispatch/platform.h | 27 ++++-
src/CMakeLists.txt | 4 +
src/config.h.in | 1 +
src/platform.c | 113 +++++++++++++++++++++
src/server.c | 35 +++++++
5 files changed, 176 insertions(+), 4 deletions(-)
diff --git a/src/config.h.in b/include/qpid/dispatch/platform.h
similarity index 55%
copy from src/config.h.in
copy to include/qpid/dispatch/platform.h
index 7947506..5e1a149 100644
--- a/src/config.h.in
+++ b/include/qpid/dispatch/platform.h
@@ -1,3 +1,5 @@
+#ifndef __dispatch_platform_h__
+#define __dispatch_platform_h__ 1
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -17,7 +19,24 @@
* under the License.
*/
-#define QPID_DISPATCH_VERSION "${QPID_DISPATCH_VERSION}"
-#define QPID_DISPATCH_LIB
"$<$<BOOL:${APPLE}>:@rpath/>$<TARGET_FILE_NAME:qpid-dispatch>"
-#define QPID_CONSOLE_STAND_ALONE_INSTALL_DIR
"${CONSOLE_STAND_ALONE_INSTALL_DIR}"
-#cmakedefine01 QD_MEMORY_STATS
+#include <stdint.h>
+
+/**
+ * Platform specific utility functions
+ */
+
+/**
+ * Determine the amount of usable 'fast' memory (RAM only, not including swap)
+ * installed. If resource constraints are in use (e.g setrlimit(),
+ * containerization, etc) for the qdrouterd process this routine should return
+ * the minimum of (physical memory, memory resource limit).
+ *
+ * This value is used by the router to detect and react to low memory
+ * conditions.
+ *
+ * Returns the size of fast memory in bytes or zero if the size cannot be
+ * determined.
+ */
+uintmax_t qd_platform_memory_size(void);
+
+#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0a01d43..4257d95 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -65,6 +65,7 @@ set(qpid_dispatch_SOURCES
router_agent.c
router_config.c
address_lookup_utils.c
+ platform.c
router_core/agent.c
router_core/agent_address.c
router_core/agent_config_address.c
@@ -157,6 +158,9 @@ set_target_properties(qpid-dispatch PROPERTIES
install(TARGETS qpid-dispatch
LIBRARY DESTINATION ${QPID_DISPATCH_HOME})
+# check for various function availability
+check_symbol_exists(getrlimit sys/resource.h QD_HAVE_GETRLIMIT)
+
#
https://stackoverflow.com/questions/54771452/expanding-a-variable-cmakedefine-and-generator-expression-in-template-file
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" CONFIG_H_IN)
string(CONFIGURE "${CONFIG_H_IN}" CONFIG_H_TMP)
diff --git a/src/config.h.in b/src/config.h.in
index 7947506..21ea9e1 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -21,3 +21,4 @@
#define QPID_DISPATCH_LIB
"$<$<BOOL:${APPLE}>:@rpath/>$<TARGET_FILE_NAME:qpid-dispatch>"
#define QPID_CONSOLE_STAND_ALONE_INSTALL_DIR
"${CONSOLE_STAND_ALONE_INSTALL_DIR}"
#cmakedefine01 QD_MEMORY_STATS
+#cmakedefine01 QD_HAVE_GETRLIMIT
diff --git a/src/platform.c b/src/platform.c
new file mode 100644
index 0000000..b1cd61b
--- /dev/null
+++ b/src/platform.c
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <qpid/dispatch/platform.h>
+#include <qpid/dispatch/ctools.h>
+
+
+uintmax_t qd_platform_memory_size(void)
+{
+ bool found = false;
+ uintmax_t rlimit = UINTMAX_MAX;
+
+#if QD_HAVE_GETRLIMIT
+ {
+ // determine if this process has a hard or soft limit set for its total
+ // virtual address space
+ struct rlimit rl = {0};
+ // note rlim_max >= rlim_cur (see man getrlimit) use smallest value
+ if (getrlimit(RLIMIT_AS, &rl) == 0) {
+ if (rl.rlim_cur != RLIM_INFINITY) {
+ rlimit = (uintmax_t)rl.rlim_cur;
+ found = true;
+ } else if (rl.rlim_max != RLIM_INFINITY) {
+ rlimit = (uintmax_t)rl.rlim_max;
+ found = true;
+ }
+ }
+ }
+#endif // QD_HAVE_GETRLIMIT
+
+ // although a resource limit may be set be sure it does not exceed the
+ // available "fast" memory.
+
+ // @TODO(kgiusti) this is linux-specific (see man proc)
+ uintmax_t mlimit = UINTMAX_MAX;
+ FILE *minfo_fp = fopen("/proc/meminfo", "r");
+ if (minfo_fp) {
+ size_t buflen = 0;
+ char *buffer = 0;
+ uintmax_t tmp;
+ while (getline(&buffer, &buflen, minfo_fp) != -1) {
+ if (sscanf(buffer, "MemTotal: %"SCNuMAX, &tmp) == 1) {
+ mlimit = tmp * 1024; // MemTotal is in KiB
+ found = true;
+ break;
+ }
+ }
+ free(buffer); // allocated by getline
+ fclose(minfo_fp);
+ }
+
+ // and if qdrouterd is running within a container check the cgroups memory
+ // controller. Hard and soft memory limits can be set.
+
+ uintmax_t climit = UINTMAX_MAX;
+ {
+ uintmax_t soft = UINTMAX_MAX;
+ uintmax_t hard = UINTMAX_MAX;
+ bool c_set = false;
+
+ FILE *cg_fp = fopen("/sys/fs/cgroup/memory/memory.limit_in_bytes",
"r");
+ if (cg_fp) {
+ if (fscanf(cg_fp, "%"SCNuMAX, &hard) == 1) {
+ c_set = true;
+ }
+ fclose(cg_fp);
+ }
+
+ cg_fp = fopen("/sys/fs/cgroup/memory/memory.soft_limit_in_bytes", "r");
+ if (cg_fp) {
+ if (fscanf(cg_fp, "%"SCNuMAX, &soft) == 1) {
+ c_set = true;
+ }
+ fclose(cg_fp);
+ }
+
+ if (c_set) {
+ climit = MIN(soft, hard);
+ found = true;
+ }
+ }
+
+ if (found) {
+ uintmax_t tmp = MIN(mlimit, climit);
+ return MIN(rlimit, tmp);
+ }
+
+ return 0;
+}
diff --git a/src/server.c b/src/server.c
index 8644ef5..4bc78fd 100644
--- a/src/server.c
+++ b/src/server.c
@@ -28,6 +28,7 @@
#include <qpid/dispatch/server.h>
#include <qpid/dispatch/failoverlist.h>
#include <qpid/dispatch/alloc.h>
+#include <qpid/dispatch/platform.h>
#include <proton/event.h>
#include <proton/listener.h>
@@ -1318,6 +1319,27 @@ void qd_server_trace_all_connections()
}
}
+
+static double normalize_memory_size(const uint64_t bytes, const char **suffix)
+{
+ static const char * const units[] = {"B", "KiB", "MiB", "GiB", "TiB"};
+ const int units_ct = 5;
+ const double base = 1024.0;
+
+ double value = (double)bytes;
+ for (int i = 0; i < units_ct; ++i) {
+ if (value < base) {
+ if (suffix)
+ *suffix = units[i];
+ return value;
+ }
+ value /= base;
+ }
+ if (suffix)
+ *suffix = units[units_ct - 1];
+ return value;
+}
+
void qd_server_run(qd_dispatch_t *qd)
{
qd_server_t *qd_server = qd->server;
@@ -1327,6 +1349,19 @@ void qd_server_run(qd_dispatch_t *qd)
qd_log(qd_server->log_source,
QD_LOG_NOTICE, "Operational, %d Threads Running (process ID %ld)",
qd_server->thread_count, (long)getpid());
+
+ const uintmax_t ram_size = qd_platform_memory_size();
+ const uint64_t vm_size = qd_router_memory_usage();
+ if (ram_size && vm_size) {
+ const char *suffix_vm = 0;
+ const char *suffix_ram = 0;
+ double vm = normalize_memory_size(vm_size, &suffix_vm);
+ double ram = normalize_memory_size(ram_size, &suffix_ram);
+ qd_log(qd_server->log_source, QD_LOG_NOTICE,
+ "Process VmSize %.2f %s (%.2f %s available memory)",
+ vm, suffix_vm, ram, suffix_ram);
+ }
+
#ifndef NDEBUG
qd_log(qd_server->log_source, QD_LOG_INFO, "Running in DEBUG Mode");
#endif
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]