1 /* 2 * Copyright (c) 2017, 2018 Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 /* 25 * @test TestShenandoahStringDedup.java 26 * @summary Test Shenandoah string deduplication implementation 27 * @key gc 28 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 29 * -DtargetStrings=3000000 30 * ShenandoahStrDedupStress 31 * 32 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 33 * -XX:ShenandoahGCHeuristics=aggressive -DtargetStrings=2000000 34 * ShenandoahStrDedupStress 35 * 36 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 37 * -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahOOMDuringEvacALot -DtargetStrings=2000000 38 * ShenandoahStrDedupStress 39 * 40 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 41 * -XX:ShenandoahGCHeuristics=static -DtargetStrings=4000000 42 * ShenandoahStrDedupStress 43 * 44 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 45 * -XX:ShenandoahGCHeuristics=compact 46 * ShenandoahStrDedupStress 47 * 48 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx1024M 49 * -XX:ShenandoahGCHeuristics=passive -XX:+ShenandoahDegeneratedGC -DtargetOverwrites=40000000 50 * ShenandoahStrDedupStress 51 * 52 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx1024M 53 * -XX:ShenandoahGCHeuristics=passive -XX:-ShenandoahDegeneratedGC -DtargetOverwrites=40000000 54 * ShenandoahStrDedupStress 55 * 56 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 57 * -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=3000000 58 * ShenandoahStrDedupStress 59 * 60 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 61 * -XX:ShenandoahGCHeuristics=compact -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=2000000 62 * ShenandoahStrDedupStress 63 * 64 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 65 * -XX:ShenandoahGCHeuristics=aggressive -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=2000000 66 * ShenandoahStrDedupStress 67 * 68 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 69 * -XX:ShenandoahGCHeuristics=static -XX:ShenandoahUpdateRefsEarly=off -DtargetOverwrites=4000000 70 * ShenandoahStrDedupStress 71 * 72 * @run main/othervm -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -Xmx512M 73 * -XX:ShenandoahGCHeuristics=aggressive -XX:ShenandoahUpdateRefsEarly=off -XX:+ShenandoahOOMDuringEvacALot -DtargetStrings=2000000 74 * ShenandoahStrDedupStress 75 */ 76 77 import java.lang.reflect.*; 78 import java.util.*; 79 import sun.misc.*; 80 81 public class ShenandoahStrDedupStress { 82 private static Field valueField; 83 private static Unsafe unsafe; 84 85 private static long TARGET_STRINGS = Long.getLong("targetStrings", 2_500_000); 86 private static long TARGET_OVERWRITES = Long.getLong("targetOverwrites", 600_000); 87 88 private static final int UNIQUE_STRINGS = 20; 89 static { 90 try { 91 Field field = Unsafe.class.getDeclaredField("theUnsafe"); 92 field.setAccessible(true); 93 unsafe = (Unsafe)field.get(null); 94 95 valueField = String.class.getDeclaredField("value"); 96 valueField.setAccessible(true); 97 } catch (Exception e) { 98 throw new RuntimeException(e); 99 } 100 } 101 102 private static Object getValue(String string) { 103 try { 104 return valueField.get(string); 105 } catch (Exception e) { 106 throw new RuntimeException(e); 107 } 108 } 109 110 static class StringAndId { 111 private String str; 112 private int id; 113 public StringAndId(String str, int id) { 114 this.str = str; 115 this.id = id; 116 } 117 118 public String str() { return str; } 119 public int id() { return id; } 120 } 121 122 private static void generateStrings(ArrayList<StringAndId> strs, int unique_strs) { 123 Random rn = new Random(); 124 for (int u = 0; u < unique_strs; u ++) { 125 int n = Math.abs(rn.nextInt() % 2); 126 for (int index = 0; index < n; index ++) { 127 strs.add(new StringAndId("Unique String " + u, u)); 128 } 129 } 130 } 131 132 private static int verifyDedepString(ArrayList<StringAndId> strs) { 133 HashMap<Object, StringAndId> seen = new HashMap<>(); 134 int total = 0; 135 int dedup = 0; 136 137 for (StringAndId item : strs) { 138 total ++; 139 StringAndId existing_item = seen.get(getValue(item.str())); 140 if (existing_item == null) { 141 seen.put(getValue(item.str()), item); 142 } else { 143 if (item.id() != existing_item.id() || 144 !item.str().equals(existing_item.str())) { 145 System.out.println("StringDedup error:"); 146 System.out.println("id: " + item.id() + " != " + existing_item.id()); 147 System.out.println("or String: " + item.str() + " != " + existing_item.str()); 148 throw new RuntimeException("StringDedup Test failed"); 149 } else { 150 dedup ++; 151 } 152 } 153 } 154 System.out.println("Dedup: " + dedup + "/" + total + " unique: " + (total - dedup)); 155 return (total - dedup); 156 } 157 158 static volatile ArrayList<StringAndId> astrs = new ArrayList<>(); 159 public static void main(String[] args) { 160 Random rn = new Random(); 161 162 long gen_iterations = TARGET_STRINGS * 2 / UNIQUE_STRINGS; 163 164 for(long index = 0; index < gen_iterations; index ++) { 165 generateStrings(astrs, UNIQUE_STRINGS); 166 } 167 168 for (long loop = 1; loop < TARGET_OVERWRITES; loop ++) { 169 int arr_size = astrs.size(); 170 int index = Math.abs(rn.nextInt()) % arr_size; 171 StringAndId item = astrs.get(index); 172 int n = Math.abs(rn.nextInt() % UNIQUE_STRINGS); 173 item.str = "Unique String " + n; 174 item.id = n; 175 } 176 177 verifyDedepString(astrs); 178 } 179 }