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 <[email protected]> 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
