mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8259886: Improve SSL session cache performance and scalability
Reviewed-by: erikj, xuelei
This commit is contained in:
parent
3844ce400d
commit
18fc35053c
3 changed files with 150 additions and 1 deletions
|
@ -84,6 +84,7 @@ $(eval $(call SetupJavaCompilation, BUILD_INDIFY, \
|
|||
#### Compile Targets
|
||||
|
||||
# Building microbenchmark requires the jdk.unsupported and java.management modules.
|
||||
# sun.security.util is required to compile Cache benchmark
|
||||
|
||||
# Build microbenchmark suite for the current JDK
|
||||
$(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
|
||||
|
@ -93,6 +94,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
|
|||
DISABLED_WARNINGS := processing rawtypes cast serial, \
|
||||
SRC := $(MICROBENCHMARK_SRC), \
|
||||
BIN := $(MICROBENCHMARK_CLASSES), \
|
||||
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED, \
|
||||
JAVA_FLAGS := --add-modules jdk.unsupported --limit-modules java.management, \
|
||||
))
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -248,6 +248,7 @@ class MemoryCache<K,V> extends Cache<K,V> {
|
|||
private final Map<K, CacheEntry<K,V>> cacheMap;
|
||||
private int maxSize;
|
||||
private long lifetime;
|
||||
private long nextExpirationTime = Long.MAX_VALUE;
|
||||
|
||||
// ReferenceQueue is of type V instead of Cache<K,V>
|
||||
// to allow SoftCacheEntry to extend SoftReference<V>
|
||||
|
@ -317,12 +318,18 @@ class MemoryCache<K,V> extends Cache<K,V> {
|
|||
}
|
||||
int cnt = 0;
|
||||
long time = System.currentTimeMillis();
|
||||
if (nextExpirationTime > time) {
|
||||
return;
|
||||
}
|
||||
nextExpirationTime = Long.MAX_VALUE;
|
||||
for (Iterator<CacheEntry<K,V>> t = cacheMap.values().iterator();
|
||||
t.hasNext(); ) {
|
||||
CacheEntry<K,V> entry = t.next();
|
||||
if (entry.isValid(time) == false) {
|
||||
t.remove();
|
||||
cnt++;
|
||||
} else if (nextExpirationTime > entry.getExpirationTime()) {
|
||||
nextExpirationTime = entry.getExpirationTime();
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
|
@ -356,6 +363,9 @@ class MemoryCache<K,V> extends Cache<K,V> {
|
|||
emptyQueue();
|
||||
long expirationTime = (lifetime == 0) ? 0 :
|
||||
System.currentTimeMillis() + lifetime;
|
||||
if (expirationTime < nextExpirationTime) {
|
||||
nextExpirationTime = expirationTime;
|
||||
}
|
||||
CacheEntry<K,V> newEntry = newEntry(key, value, expirationTime, queue);
|
||||
CacheEntry<K,V> oldEntry = cacheMap.put(key, newEntry);
|
||||
if (oldEntry != null) {
|
||||
|
@ -470,6 +480,7 @@ class MemoryCache<K,V> extends Cache<K,V> {
|
|||
|
||||
V getValue();
|
||||
|
||||
long getExpirationTime();
|
||||
}
|
||||
|
||||
private static class HardCacheEntry<K,V> implements CacheEntry<K,V> {
|
||||
|
@ -492,6 +503,10 @@ class MemoryCache<K,V> extends Cache<K,V> {
|
|||
return value;
|
||||
}
|
||||
|
||||
public long getExpirationTime() {
|
||||
return expirationTime;
|
||||
}
|
||||
|
||||
public boolean isValid(long currentTime) {
|
||||
boolean valid = (currentTime <= expirationTime);
|
||||
if (valid == false) {
|
||||
|
@ -529,6 +544,10 @@ class MemoryCache<K,V> extends Cache<K,V> {
|
|||
return get();
|
||||
}
|
||||
|
||||
public long getExpirationTime() {
|
||||
return expirationTime;
|
||||
}
|
||||
|
||||
public boolean isValid(long currentTime) {
|
||||
boolean valid = (currentTime <= expirationTime) && (get() != null);
|
||||
if (valid == false) {
|
||||
|
|
128
test/micro/org/openjdk/bench/java/security/CacheBench.java
Normal file
128
test/micro/org/openjdk/bench/java/security/CacheBench.java
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Dynatrace LLC. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package org.openjdk.bench.java.security;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Level;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Param;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.TearDown;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import sun.security.util.Cache;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@Fork(jvmArgsAppend = {"--add-exports", "java.base/sun.security.util=ALL-UNNAMED", "-Xmx1g"})
|
||||
public class CacheBench {
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public static class SharedState {
|
||||
Cache<Integer, Integer> cache;
|
||||
|
||||
@Param({"20480", "204800", "5120000"})
|
||||
int size;
|
||||
|
||||
@Param({"86400", "0"})
|
||||
int timeout;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
cache = Cache.newSoftMemoryCache(size, timeout);
|
||||
IntStream.range(0, size).boxed().forEach(i -> cache.put(i, i));
|
||||
}
|
||||
}
|
||||
|
||||
@State(Scope.Thread)
|
||||
public static class GetPutState {
|
||||
Integer[] intArray;
|
||||
int index;
|
||||
|
||||
@Setup
|
||||
public void setup(SharedState benchState) {
|
||||
intArray = IntStream.range(0, benchState.size + 1).boxed().toArray(Integer[]::new);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@TearDown(Level.Invocation)
|
||||
public void tearDown() {
|
||||
index++;
|
||||
if (index >= intArray.length) {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void put(SharedState benchState, GetPutState state) {
|
||||
Integer i = state.intArray[state.index];
|
||||
benchState.cache.put(i, i);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public Integer get(SharedState benchState, GetPutState state) {
|
||||
Integer i = state.intArray[state.index];
|
||||
return benchState.cache.get(i);
|
||||
}
|
||||
|
||||
@State(Scope.Thread)
|
||||
public static class RemoveState {
|
||||
Integer[] intArray;
|
||||
int index;
|
||||
SharedState benchState;
|
||||
|
||||
@Setup
|
||||
public void setup(SharedState benchState) {
|
||||
this.benchState = benchState;
|
||||
intArray = IntStream.range(0, benchState.size).boxed().toArray(Integer[]::new);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@TearDown(Level.Invocation)
|
||||
public void tearDown() {
|
||||
// add back removed item
|
||||
Integer i = intArray[index];
|
||||
benchState.cache.put(i, i);
|
||||
|
||||
index++;
|
||||
if (index >= intArray.length) {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void remove(SharedState benchState, RemoveState state) {
|
||||
Integer i = state.intArray[state.index];
|
||||
benchState.cache.remove(i);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue