You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2022/06/20 02:31:08 UTC

[dubbo] branch 3.0 updated: Improve: enhance scheduled executor for MemoryLimitCalculator (#10178)

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.0 by this push:
     new 23f517a904 Improve: enhance scheduled executor for MemoryLimitCalculator (#10178)
23f517a904 is described below

commit 23f517a904fcf1554b78f22dfa13dd53ab7a3a19
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Mon Jun 20 10:31:02 2022 +0800

    Improve: enhance scheduled executor for MemoryLimitCalculator (#10178)
---
 .../common/threadpool/MemoryLimitCalculator.java   | 35 ++++++++++++++++------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/MemoryLimitCalculator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/MemoryLimitCalculator.java
index 31db9e0508..1be3d6c5a1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/MemoryLimitCalculator.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/MemoryLimitCalculator.java
@@ -17,9 +17,13 @@
 
 package org.apache.dubbo.common.threadpool;
 
+import org.apache.dubbo.common.resource.GlobalResourcesRepository;
+import org.apache.dubbo.common.utils.NamedThreadFactory;
+
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * {@link java.lang.Runtime#freeMemory()} technology is used to calculate the
@@ -33,26 +37,37 @@ public class MemoryLimitCalculator {
 
     private static volatile long maxAvailable;
 
-    private static final ScheduledExecutorService SCHEDULER = Executors.newSingleThreadScheduledExecutor();
-
-    static {
-        // immediately refresh when this class is loaded to prevent maxAvailable from being 0
-        refresh();
-        // check every 50 ms to improve performance
-        SCHEDULER.scheduleWithFixedDelay(MemoryLimitCalculator::refresh, 50, 50, TimeUnit.MILLISECONDS);
-        Runtime.getRuntime().addShutdownHook(new Thread(SCHEDULER::shutdown));
-    }
+    private static final AtomicBoolean refreshStarted = new AtomicBoolean(false);
 
     private static void refresh() {
         maxAvailable = Runtime.getRuntime().freeMemory();
     }
 
+    private static void checkAndScheduleRefresh() {
+        if (!refreshStarted.get()) {
+            // immediately refresh when first call to prevent maxAvailable from being 0
+            // to ensure that being refreshed before refreshStarted being set as true
+            // notice: refresh may be called for more than once because there is no lock
+            refresh();
+            if (refreshStarted.compareAndSet(false, true)) {
+                ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Dubbo-Memory-Calculator"));
+                // check every 50 ms to improve performance
+                scheduledExecutorService.scheduleWithFixedDelay(MemoryLimitCalculator::refresh, 50, 50, TimeUnit.MILLISECONDS);
+                GlobalResourcesRepository.registerGlobalDisposable(() -> {
+                    refreshStarted.set(false);
+                    scheduledExecutorService.shutdown();
+                });
+            }
+        }
+    }
+
     /**
      * Get the maximum available memory of the current JVM.
      *
      * @return maximum available memory
      */
     public static long maxAvailable() {
+        checkAndScheduleRefresh();
         return maxAvailable;
     }
 
@@ -67,6 +82,7 @@ public class MemoryLimitCalculator {
         if (percentage <= 0 || percentage > 1) {
             throw new IllegalArgumentException();
         }
+        checkAndScheduleRefresh();
         return (long) (maxAvailable() * percentage);
     }
 
@@ -76,6 +92,7 @@ public class MemoryLimitCalculator {
      * @return available memory
      */
     public static long defaultLimit() {
+        checkAndScheduleRefresh();
         return (long) (maxAvailable() * 0.8);
     }
 }