!53 I2AOPS: add-integerCache-feature.patch
From: @kuenking Reviewed-by: @jvmboy Signed-off-by: @jvmboy
This commit is contained in:
commit
2673fd2998
413
add-integerCache-feature.patch
Executable file
413
add-integerCache-feature.patch
Executable file
@ -0,0 +1,413 @@
|
||||
diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp
|
||||
index d8f1679b4..18ea89b85 100644
|
||||
--- a/src/hotspot/share/prims/unsafe.cpp
|
||||
+++ b/src/hotspot/share/prims/unsafe.cpp
|
||||
@@ -1018,7 +1018,11 @@ UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleAr
|
||||
return ret;
|
||||
} UNSAFE_END
|
||||
|
||||
+UNSAFE_ENTRY(jboolean, Unsafe_GetUseHashMapIntegerCache(JNIEnv *env, jobject unsafe)) {
|
||||
+ return UseHashMapIntegerCache;
|
||||
+}
|
||||
+UNSAFE_END
|
||||
|
||||
UNSAFE_ENTRY(jboolean, Unsafe_GetUseFastSerializer(JNIEnv *env, jobject unsafe)) {
|
||||
return UseFastSerializer;
|
||||
}
|
||||
@@ -1108,6 +1113,7 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
|
||||
{CC "fullFence", CC "()V", FN_PTR(Unsafe_FullFence)},
|
||||
|
||||
{CC "isBigEndian0", CC "()Z", FN_PTR(Unsafe_isBigEndian0)},
|
||||
+ {CC "getUseHashMapIntegerCache", CC "()Z", FN_PTR(Unsafe_GetUseHashMapIntegerCache)},
|
||||
{CC "getUseFastSerializer", CC "()Z", FN_PTR(Unsafe_GetUseFastSerializer)},
|
||||
{CC "unalignedAccess0", CC "()Z", FN_PTR(Unsafe_unalignedAccess0)}
|
||||
};
|
||||
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
|
||||
index 47458b6c1..b8c0bec40 100644
|
||||
--- a/src/hotspot/share/runtime/globals.hpp
|
||||
+++ b/src/hotspot/share/runtime/globals.hpp
|
||||
@@ -2677,6 +2677,11 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G);
|
||||
JFR_ONLY(product(ccstr, StartFlightRecording, NULL, \
|
||||
"Start flight recording with options")) \
|
||||
\
|
||||
+ experimental(bool, UseHashMapIntegerCache, false, \
|
||||
+ "The integer cache is an array of references to objects of" \
|
||||
+ "the HashMap Value type, indexed by the unboxed int key value." \
|
||||
+ "faster in execution, higher in memory consumption.") \
|
||||
+ \
|
||||
experimental(bool, UseFastSerializer, false, \
|
||||
"Cache-based serialization.It is extremely fast, but it can only" \
|
||||
"be effective in certain scenarios.") \
|
||||
diff --git a/src/java.base/share/classes/java/util/HashMap.java b/src/java.base/share/classes/java/util/HashMap.java
|
||||
index df303031a..c260b61fd 100644
|
||||
--- a/src/java.base/share/classes/java/util/HashMap.java
|
||||
+++ b/src/java.base/share/classes/java/util/HashMap.java
|
||||
@@ -35,6 +35,7 @@ import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
+import jdk.internal.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* Hash table based implementation of the {@code Map} interface. This
|
||||
@@ -272,6 +273,28 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
*/
|
||||
static final int MIN_TREEIFY_CAPACITY = 64;
|
||||
|
||||
+ /**
|
||||
+ * Used to get the commandline option: UseHashMapIntegerCache.
|
||||
+ */
|
||||
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
+
|
||||
+ /**
|
||||
+ * Indicate integerCache can be performed. disable if HashMap.Node.setValue
|
||||
+ * is directly used to update Node value.
|
||||
+ */
|
||||
+ private static boolean enableIntegerCache = UNSAFE.getUseHashMapIntegerCache();
|
||||
+
|
||||
+ /**
|
||||
+ * The smallest table size for create integer cache.
|
||||
+ */
|
||||
+ private static final int MIN_INTEGER_CACHE = 2048;
|
||||
+
|
||||
+ /**
|
||||
+ * The factor used in create integer cache to guarantee most Key are
|
||||
+ * Integer and in range.
|
||||
+ */
|
||||
+ private static final float INTEGER_CACHE_FACTOR = 0.95f;
|
||||
+
|
||||
/**
|
||||
* Basic hash bin node, used for most entries. (See below for
|
||||
* TreeNode subclass, and in LinkedHashMap for its Entry subclass.)
|
||||
@@ -298,6 +321,10 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
}
|
||||
|
||||
public final V setValue(V newValue) {
|
||||
+ // Disable integerCache in all HashMap instance.
|
||||
+ if (key != null && key instanceof Integer) {
|
||||
+ enableIntegerCache = false;
|
||||
+ }
|
||||
V oldValue = value;
|
||||
value = newValue;
|
||||
return oldValue;
|
||||
@@ -390,6 +417,12 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
*/
|
||||
transient Node<K,V>[] table;
|
||||
|
||||
+ /**
|
||||
+ * Cache <Integer key -> Value> Map
|
||||
+ * integerCache[key->intValue] = V
|
||||
+ */
|
||||
+ transient Object[] integerCache;
|
||||
+
|
||||
/**
|
||||
* Holds cached entrySet(). Note that AbstractMap fields are used
|
||||
* for keySet() and values().
|
||||
@@ -547,7 +580,20 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
*
|
||||
* @see #put(Object, Object)
|
||||
*/
|
||||
+ @SuppressWarnings("unchecked")
|
||||
public V get(Object key) {
|
||||
+ if (integerCache != null) {
|
||||
+ if (enableIntegerCache == false) {
|
||||
+ integerCache = null;
|
||||
+ }
|
||||
+ else if (key != null && key instanceof Integer) {
|
||||
+ int val = ((Integer)key).intValue();
|
||||
+ if (val >= 0 && val < integerCache.length) {
|
||||
+ return (V)integerCache[val];
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
Node<K,V> e;
|
||||
return (e = getNode(hash(key), key)) == null ? null : e.value;
|
||||
}
|
||||
@@ -588,6 +634,17 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
* key.
|
||||
*/
|
||||
public boolean containsKey(Object key) {
|
||||
+ if (integerCache != null) {
|
||||
+ if (enableIntegerCache == false) {
|
||||
+ integerCache = null;
|
||||
+ }
|
||||
+ else if (key != null && key instanceof Integer) {
|
||||
+ int val = ((Integer)key).intValue();
|
||||
+ if (val >= 0 && val < integerCache.length && integerCache[val] != null) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
return getNode(hash(key), key) != null;
|
||||
}
|
||||
|
||||
@@ -620,6 +677,11 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
|
||||
boolean evict) {
|
||||
Node<K,V>[] tab; Node<K,V> p; int n, i;
|
||||
+
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, value, onlyIfAbsent);
|
||||
+ }
|
||||
+
|
||||
if ((tab = table) == null || (n = tab.length) == 0)
|
||||
n = (tab = resize()).length;
|
||||
if ((p = tab[i = (n - 1) & hash]) == null)
|
||||
@@ -740,6 +802,8 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ createIntegerCache();
|
||||
return newTab;
|
||||
}
|
||||
|
||||
@@ -839,6 +903,10 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
p.next = node.next;
|
||||
++modCount;
|
||||
--size;
|
||||
+
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(node.key, null, false);
|
||||
+ }
|
||||
afterNodeRemoval(node);
|
||||
return node;
|
||||
}
|
||||
@@ -858,6 +926,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
for (int i = 0; i < tab.length; ++i)
|
||||
tab[i] = null;
|
||||
}
|
||||
+ integerCache = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -882,6 +951,82 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
return false;
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * 1. iterator all Keys and statistic
|
||||
+ * Integer Key count, total count is size
|
||||
+ * Integer Key count in range [0, table.length], get Max value.
|
||||
+ *
|
||||
+ * 2. Create integer cache
|
||||
+ */
|
||||
+ @SuppressWarnings({"unchecked"})
|
||||
+ private final void createIntegerCache() {
|
||||
+ int n = table.length;
|
||||
+ int intKeyCount = 0;
|
||||
+ int intKeyCountInrange = 0;
|
||||
+ int maxIntKey = 0;
|
||||
+ if (n < MIN_INTEGER_CACHE || (enableIntegerCache == false)) {
|
||||
+ integerCache = null;
|
||||
+ return;
|
||||
+ }
|
||||
+ Iterator<K> it = this.keySet().iterator();
|
||||
+ while (it.hasNext()) {
|
||||
+ K key = it.next();
|
||||
+ if (key != null && key instanceof Integer) {
|
||||
+ intKeyCount++;
|
||||
+ int val = ((Integer)key).intValue();
|
||||
+ if (val >= 0 && val < n) {
|
||||
+ intKeyCountInrange++;
|
||||
+ if (val > maxIntKey)
|
||||
+ maxIntKey = val;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ float keyIntRation = ((float)intKeyCount) / size;
|
||||
+ float keyIntInRangeRation = ((float)intKeyCountInrange) / size;
|
||||
+ if (keyIntRation >= INTEGER_CACHE_FACTOR &&
|
||||
+ keyIntInRangeRation >= INTEGER_CACHE_FACTOR) {
|
||||
+ // compute integerCache size
|
||||
+ int cacheMapSize = n < (2 * maxIntKey) ? n : (2 * maxIntKey);
|
||||
+ integerCache = new Object[cacheMapSize];
|
||||
+ Iterator<Map.Entry<K,V>> entries = this.entrySet().iterator();
|
||||
+ while (entries.hasNext()) {
|
||||
+ Map.Entry<K,V> thisEntry = entries.next();
|
||||
+ K key = thisEntry.getKey();
|
||||
+ V value = thisEntry.getValue();
|
||||
+ if (key != null && key instanceof Integer) {
|
||||
+ int val = ((Integer)key).intValue();
|
||||
+ if (val >= 0 && val < integerCache.length) {
|
||||
+ integerCache[val] = value;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ integerCache = null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * put if integerCache null check outside of this call
|
||||
+ * JIT will not inline this method (not hot) when HashMap is not Integer Key intensive.
|
||||
+ * Otherwise it will always inline updateIntegerCache method.
|
||||
+ *
|
||||
+ */
|
||||
+ private final void updateIntegerCache(K key, V value, boolean onlyIfAbsent) {
|
||||
+ if (enableIntegerCache == false) {
|
||||
+ integerCache = null;
|
||||
+ return;
|
||||
+ }
|
||||
+ if (key != null && key instanceof Integer) {
|
||||
+ int val = ((Integer)key).intValue();
|
||||
+ if (val >= 0 && val < integerCache.length) {
|
||||
+ if (onlyIfAbsent && integerCache[val] != null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ integerCache[val] = value;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Returns a {@link Set} view of the keys contained in this map.
|
||||
* The set is backed by the map, so changes to the map are
|
||||
@@ -1047,7 +1192,19 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
// Overrides of JDK8 Map extension methods
|
||||
|
||||
@Override
|
||||
+ @SuppressWarnings("unchecked")
|
||||
public V getOrDefault(Object key, V defaultValue) {
|
||||
+ if (integerCache != null) {
|
||||
+ if (enableIntegerCache == false) {
|
||||
+ integerCache = null;
|
||||
+ } else if (key != null && key instanceof Integer) {
|
||||
+ V value;
|
||||
+ int val = ((Integer)key).intValue();
|
||||
+ if (val >= 0 && val < integerCache.length && (value = (V)integerCache[val]) != null) {
|
||||
+ return value;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
Node<K,V> e;
|
||||
return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
|
||||
}
|
||||
@@ -1068,6 +1225,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
if ((e = getNode(hash(key), key)) != null &&
|
||||
((v = e.value) == oldValue || (v != null && v.equals(oldValue)))) {
|
||||
e.value = newValue;
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, newValue, false);
|
||||
+ }
|
||||
afterNodeAccess(e);
|
||||
return true;
|
||||
}
|
||||
@@ -1080,6 +1240,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
if ((e = getNode(hash(key), key)) != null) {
|
||||
V oldValue = e.value;
|
||||
e.value = value;
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, value, false);
|
||||
+ }
|
||||
afterNodeAccess(e);
|
||||
return oldValue;
|
||||
}
|
||||
@@ -1136,6 +1299,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
return null;
|
||||
} else if (old != null) {
|
||||
old.value = v;
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, v, false);
|
||||
+ }
|
||||
afterNodeAccess(old);
|
||||
return v;
|
||||
}
|
||||
@@ -1146,6 +1312,11 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
if (binCount >= TREEIFY_THRESHOLD - 1)
|
||||
treeifyBin(tab, hash);
|
||||
}
|
||||
+
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, v, false);
|
||||
+ }
|
||||
+
|
||||
modCount = mc + 1;
|
||||
++size;
|
||||
afterNodeInsertion(true);
|
||||
@@ -1176,6 +1347,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
if (mc != modCount) { throw new ConcurrentModificationException(); }
|
||||
if (v != null) {
|
||||
e.value = v;
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, v, false);
|
||||
+ }
|
||||
afterNodeAccess(e);
|
||||
return v;
|
||||
}
|
||||
@@ -1230,6 +1404,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
if (old != null) {
|
||||
if (v != null) {
|
||||
old.value = v;
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, v, false);
|
||||
+ }
|
||||
afterNodeAccess(old);
|
||||
}
|
||||
else
|
||||
@@ -1243,6 +1420,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
if (binCount >= TREEIFY_THRESHOLD - 1)
|
||||
treeifyBin(tab, hash);
|
||||
}
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, v, false);
|
||||
+ }
|
||||
modCount = mc + 1;
|
||||
++size;
|
||||
afterNodeInsertion(true);
|
||||
@@ -1303,6 +1483,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
}
|
||||
if (v != null) {
|
||||
old.value = v;
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, v, false);
|
||||
+ }
|
||||
afterNodeAccess(old);
|
||||
}
|
||||
else
|
||||
@@ -1317,6 +1500,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
if (binCount >= TREEIFY_THRESHOLD - 1)
|
||||
treeifyBin(tab, hash);
|
||||
}
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(key, value, false);
|
||||
+ }
|
||||
++modCount;
|
||||
++size;
|
||||
afterNodeInsertion(true);
|
||||
@@ -1350,6 +1536,9 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
for (Node<K,V> e : tab) {
|
||||
for (; e != null; e = e.next) {
|
||||
e.value = function.apply(e.key, e.value);
|
||||
+ if (integerCache != null) {
|
||||
+ updateIntegerCache(e.key, e.value, false);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
if (modCount != mc)
|
||||
@@ -1823,6 +2012,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||
modCount = 0;
|
||||
threshold = 0;
|
||||
size = 0;
|
||||
+ integerCache = null;
|
||||
}
|
||||
|
||||
// Callbacks to allow LinkedHashMap post-actions
|
||||
diff --git a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
|
||||
index d78caabdc..4d71e671e 100644
|
||||
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
|
||||
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
|
||||
@@ -3702,7 +3702,7 @@ public final class Unsafe {
|
||||
private static int convEndian(boolean big, int n) { return big == BE ? n : Integer.reverseBytes(n) ; }
|
||||
private static long convEndian(boolean big, long n) { return big == BE ? n : Long.reverseBytes(n) ; }
|
||||
|
||||
-
|
||||
+ public native boolean getUseHashMapIntegerCache();
|
||||
public native boolean getUseFastSerializer();
|
||||
private native long allocateMemory0(long bytes);
|
||||
private native long reallocateMemory0(long address, long bytes);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -735,7 +735,7 @@ Provides: java-src%{?1} = %{epoch}:%{version}-%{release}
|
||||
|
||||
Name: java-%{javaver}-%{origin}
|
||||
Version: %{newjavaver}.%{buildver}
|
||||
Release: 8
|
||||
Release: 9
|
||||
# java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons
|
||||
# and this change was brought into RHEL-4. java-1.5.0-ibm packages
|
||||
# also included the epoch in their virtual provides. This created a
|
||||
@ -841,6 +841,7 @@ Patch54: 8207160-ClassReader-adjustMethodParams-can-potentially-return-null-if-t
|
||||
Patch55: 8215047-Task-terminators-do-not-complete-termination-in-consistent-state.patch
|
||||
Patch56: 8247766-aarch64-guarantee-val-1U--nbits-failed-Field-too-big-for-insn.patch
|
||||
Patch57: add-zgc-parameter-adaptation-feature.patch
|
||||
Patch58: add-integerCache-feature.patch
|
||||
|
||||
BuildRequires: autoconf
|
||||
BuildRequires: alsa-lib-devel
|
||||
@ -1111,6 +1112,7 @@ pushd %{top_level_dir_name}
|
||||
%patch55 -p1
|
||||
%patch56 -p1
|
||||
%patch57 -p1
|
||||
%patch58 -p1
|
||||
popd # openjdk
|
||||
|
||||
%patch1000
|
||||
@ -1613,6 +1615,9 @@ require "copy_jdk_configs.lua"
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Dec 24 2020 kuenking <wangkun49@huawei.com> - 1:11.0.9.11-9
|
||||
- add add-integerCache-feature.patch
|
||||
|
||||
* Thu Dec 24 2020 kuenking <wangkun49@huawei.com> - 1:11.0.9.11-8
|
||||
- add add-zgc-parameter-adaptation-feature.patch
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user