# HG changeset patch # User bobv # Date 1572550361 0 # Node ID c440a6b4e096616d41f74f7c7c2a627ab7445eb5 # Parent 5f1fe5971ff9d47f2bb460fa3b64967bfa2cc052 8227006: [linux] Runtime.availableProcessors execution time increased by factor of 100 Reviewed-by: dholmes, sgehwolf, redestad diff -r 5f1fe5971ff9 -r c440a6b4e096 src/hotspot/os/linux/osContainer_linux.cpp --- a/src/hotspot/os/linux/osContainer_linux.cpp Thu Oct 31 19:31:03 2019 +0000 +++ b/src/hotspot/os/linux/osContainer_linux.cpp Thu Oct 31 19:32:41 2019 +0000 @@ -54,12 +54,16 @@ bool OSContainer::_is_initialized = false; bool OSContainer::_is_containerized = false; +int OSContainer::_active_processor_count = 1; julong _unlimited_memory; class CgroupSubsystem: CHeapObj { friend class OSContainer; + private: + volatile jlong _next_check_counter; + /* mountinfo contents */ char *_root; char *_mount_point; @@ -72,6 +76,7 @@ _root = os::strdup(root); _mount_point = os::strdup(mountpoint); _path = NULL; + _next_check_counter = min_jlong; } /* @@ -121,6 +126,14 @@ } char *subsystem_path() { return _path; } + + bool cache_has_expired() { + return os::elapsed_counter() > _next_check_counter; + } + + void set_cache_expiry_time(jlong timeout) { + _next_check_counter = os::elapsed_counter() + timeout; + } }; class CgroupMemorySubsystem: CgroupSubsystem { @@ -132,31 +145,26 @@ * file if everything else seems unlimited */ bool _uses_mem_hierarchy; volatile jlong _memory_limit_in_bytes; - volatile jlong _next_check_counter; public: CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) { _uses_mem_hierarchy = false; _memory_limit_in_bytes = -1; - _next_check_counter = min_jlong; } bool is_hierarchical() { return _uses_mem_hierarchy; } void set_hierarchical(bool value) { _uses_mem_hierarchy = value; } - bool should_check_memory_limit() { - return os::elapsed_counter() > _next_check_counter; - } jlong memory_limit_in_bytes() { return _memory_limit_in_bytes; } void set_memory_limit_in_bytes(jlong value) { _memory_limit_in_bytes = value; // max memory limit is unlikely to change, but we want to remain - // responsive to configuration changes. A very short (20ms) grace time + // responsive to configuration changes. A very short grace time // between re-read avoids excessive overhead during startup without // significantly reducing the VMs ability to promptly react to reduced // memory availability - _next_check_counter = os::elapsed_counter() + (NANOSECS_PER_SEC/50); + set_cache_expiry_time(OSCONTAINER_CACHE_TIMEOUT); } }; @@ -481,7 +489,7 @@ * OSCONTAINER_ERROR for not supported */ jlong OSContainer::memory_limit_in_bytes() { - if (!memory->should_check_memory_limit()) { + if (!memory->cache_has_expired()) { return memory->memory_limit_in_bytes(); } jlong memory_limit = read_memory_limit_in_bytes(); @@ -617,6 +625,14 @@ int cpu_count, limit_count; int result; + // We use a cache with a timeout to avoid performing expensive + // computations in the event this function is called frequently. + // [See 8227006]. + if (!cpu->cache_has_expired()) { + log_trace(os, container)("OSContainer::active_processor_count (cached): %d", OSContainer::_active_processor_count); + return OSContainer::_active_processor_count; + } + cpu_count = limit_count = os::Linux::active_processor_count(); int quota = cpu_quota(); int period = cpu_period(); @@ -649,6 +665,11 @@ result = MIN2(cpu_count, limit_count); log_trace(os, container)("OSContainer::active_processor_count: %d", result); + + // Update the value and reset the cache timeout + OSContainer::_active_processor_count = result; + cpu->set_cache_expiry_time(OSCONTAINER_CACHE_TIMEOUT); + return result; } diff -r 5f1fe5971ff9 -r c440a6b4e096 src/hotspot/os/linux/osContainer_linux.hpp --- a/src/hotspot/os/linux/osContainer_linux.hpp Thu Oct 31 19:31:03 2019 +0000 +++ b/src/hotspot/os/linux/osContainer_linux.hpp Thu Oct 31 19:32:41 2019 +0000 @@ -31,11 +31,16 @@ #define OSCONTAINER_ERROR (-2) +// 20ms timeout between re-reads of memory limit and _active_processor_count. +#define OSCONTAINER_CACHE_TIMEOUT (NANOSECS_PER_SEC/50) + class OSContainer: AllStatic { private: static bool _is_initialized; static bool _is_containerized; + static int _active_processor_count; + static jlong read_memory_limit_in_bytes(); public: