You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ratis.apache.org by dr...@apache.org on 2022/08/22 12:12:14 UTC

[ratis] 01/03: RATIS-1586. Set useCacheForAllThreads default to false. (#651)

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

dragonyliu pushed a commit to branch branch-2
in repository https://gitbox.apache.org/repos/asf/ratis.git

commit ef3b9b1248052bac2c58d780f04e3a39f0cbd835
Author: Tsz-Wo Nicholas Sze <sz...@apache.org>
AuthorDate: Thu Aug 18 08:45:02 2022 -0700

    RATIS-1586. Set useCacheForAllThreads default to false. (#651)
    
    
    (cherry picked from commit e5ee38ab0d38f5e785880a504d39c671c1b4d533)
---
 .../main/java/org/apache/ratis/util/JavaUtils.java | 47 +++++++++++++++++++++-
 .../java/org/apache/ratis/grpc/GrpcFactory.java    | 24 ++++++++---
 .../org/apache/ratis/grpc/TestGrpcFactory.java     | 33 +++++++++++++++
 3 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/ratis-common/src/main/java/org/apache/ratis/util/JavaUtils.java b/ratis-common/src/main/java/org/apache/ratis/util/JavaUtils.java
index b3a8f7e99..80162e101 100644
--- a/ratis-common/src/main/java/org/apache/ratis/util/JavaUtils.java
+++ b/ratis-common/src/main/java/org/apache/ratis/util/JavaUtils.java
@@ -25,6 +25,8 @@ import org.slf4j.LoggerFactory;
 import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadInfo;
 import java.lang.management.ThreadMXBean;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Date;
@@ -49,7 +51,7 @@ import java.util.function.Supplier;
 public interface JavaUtils {
   Logger LOG = LoggerFactory.getLogger(JavaUtils.class);
 
-  CompletableFuture[] EMPTY_COMPLETABLE_FUTURE_ARRAY = {};
+  CompletableFuture<?>[] EMPTY_COMPLETABLE_FUTURE_ARRAY = {};
 
   ConcurrentMap<Class<?>, String> CLASS_SIMPLE_NAMES = new ConcurrentHashMap<>();
   static String getClassSimpleName(Class<?> clazz) {
@@ -120,6 +122,49 @@ public interface JavaUtils {
     }
   }
 
+  static <T> T doPrivileged(Supplier<T> action, Function<SecurityException, T> exceptionHandler) {
+    try {
+      return System.getSecurityManager() == null? action.get()
+          : AccessController.doPrivileged((PrivilegedAction<T>) action::get);
+    } catch (SecurityException e) {
+      return exceptionHandler.apply(e);
+    }
+  }
+
+  static <T> T doPrivileged(Supplier<T> action, Supplier<String> name) {
+    return doPrivileged(action, e -> {
+      LOG.warn("Failed to " + name.get(), e);
+      return null;
+    });
+  }
+
+  /**
+   * Similar to {@link System#getProperty(String)}
+   * except that this method may invoke {@link AccessController#doPrivileged(PrivilegedAction)}
+   * if there is a {@link SecurityManager}.
+   *
+   * @return null if either the property is not set or there is a {@link SecurityException};
+   *         otherwise, return system property value.
+   */
+  static String getSystemProperty(final String key) {
+    Preconditions.assertNotNull(key, "key");
+    Preconditions.assertTrue(!key.isEmpty(), "key is empty.");
+    return doPrivileged(() -> System.getProperty(key), () -> "get system property " + key);
+  }
+
+  /**
+   * Similar to {@link System#setProperty(String, String)}
+   * except that this method may invoke {@link AccessController#doPrivileged(PrivilegedAction)}
+   * if there is a {@link SecurityManager}.
+   * When there is a {@link SecurityException}, this becomes a NOOP.
+   */
+  static void setSystemProperty(String key, String value) {
+    Preconditions.assertNotNull(key, "key");
+    Preconditions.assertTrue(!key.isEmpty(), "key is empty.");
+    Preconditions.assertNotNull(value, "value");
+    doPrivileged(() -> System.setProperty(key, value), () -> "set system property " + key + " to " + value);
+  }
+
   /**
    * Create a memoized supplier which gets a value by invoking the initializer once
    * and then keeps returning the same value as its supplied results.
diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java
index 5da5fc5c9..75eb34a2d 100644
--- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java
+++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java
@@ -31,6 +31,7 @@ import org.apache.ratis.server.ServerFactory;
 import org.apache.ratis.server.leader.FollowerInfo;
 import org.apache.ratis.server.leader.LeaderState;
 import org.apache.ratis.thirdparty.io.netty.buffer.PooledByteBufAllocator;
+import org.apache.ratis.util.JavaUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -40,16 +41,27 @@ public class GrpcFactory implements ServerFactory, ClientFactory {
 
   public static final Logger LOG = LoggerFactory.getLogger(GrpcFactory.class);
 
-  private void checkPooledByteBufAllocatorUseCacheForAllThreads(Consumer<String> log) {
-    final String name = "useCacheForAllThreads";
-    final String key = "org.apache.ratis.thirdparty.io.netty.allocator." + name;
+  static final String USE_CACHE_FOR_ALL_THREADS_NAME = "useCacheForAllThreads";
+  static final String USE_CACHE_FOR_ALL_THREADS_KEY = "org.apache.ratis.thirdparty.io.netty.allocator."
+      + USE_CACHE_FOR_ALL_THREADS_NAME;
+  static {
+    // see org.apache.ratis.thirdparty.io.netty.buffer.PooledByteBufAllocator.DEFAULT_USE_CACHE_FOR_ALL_THREADS
+    final String value = JavaUtils.getSystemProperty(USE_CACHE_FOR_ALL_THREADS_KEY);
+    if (value == null) {
+      // Set the property to false, when it is not set.
+      JavaUtils.setSystemProperty(USE_CACHE_FOR_ALL_THREADS_KEY, Boolean.FALSE.toString());
+    }
+  }
+
+  static boolean checkPooledByteBufAllocatorUseCacheForAllThreads(Consumer<String> log) {
     final boolean value = PooledByteBufAllocator.defaultUseCacheForAllThreads();
     if (value) {
-      log.accept("PERFORMANCE WARNING: " + name + " is " + value
+      log.accept("PERFORMANCE WARNING: " + USE_CACHE_FOR_ALL_THREADS_NAME + " is " + true
           + " that may cause Netty to create a lot garbage objects and, as a result, trigger GC.\n"
-          + "\tIt is recommended to disable " + name + " by setting -D" + key
-          + "=" + !value + " in command line.");
+          + "\tIt is recommended to disable " + USE_CACHE_FOR_ALL_THREADS_NAME
+          + " by setting -D" + USE_CACHE_FOR_ALL_THREADS_KEY + "=" + false + " in command line.");
     }
+    return value;
   }
 
   private final GrpcTlsConfig tlsConfig;
diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestGrpcFactory.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestGrpcFactory.java
new file mode 100644
index 000000000..76fbcee5e
--- /dev/null
+++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestGrpcFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.apache.ratis.grpc;
+
+import org.apache.ratis.BaseTest;
+import org.apache.ratis.util.JavaUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestGrpcFactory extends BaseTest {
+  @Test
+  public void testUseCacheForAllThreads() {
+    // trigger GrpcFactory static initializer
+    final boolean value = GrpcFactory.checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::info);
+    Assert.assertFalse(value);
+    LOG.info("value is {}", value);
+  }
+}
\ No newline at end of file