8227006: [linux] Runtime.availableProcessors execution time increased by factor of 100
authorbobv
Thu, 31 Oct 2019 19:32:41 +0000
changeset 58874 c440a6b4e096
parent 58873 5f1fe5971ff9
child 58875 8c0e8cff877f
8227006: [linux] Runtime.availableProcessors execution time increased by factor of 100 Reviewed-by: dholmes, sgehwolf, redestad
src/hotspot/os/linux/osContainer_linux.cpp
src/hotspot/os/linux/osContainer_linux.hpp
--- 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<mtInternal> {
  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;
 }
 
--- 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: