Skip to content

Commit 69d91a6

Browse files
committed
slightly faster Properties comparison
1 parent e4f6c13 commit 69d91a6

File tree

2 files changed

+85
-11
lines changed
  • compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/parsing/model
  • visualizer/IdealGraphVisualizer/Data/src/main/java/jdk/graal/compiler/graphio/parsing/model

2 files changed

+85
-11
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/parsing/model/Properties.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,48 @@ public int size() {
303303
return map.size();
304304
}
305305

306+
@Override
307+
public boolean equals(Object o) {
308+
if (o instanceof LinkedHashMapProperties hash) {
309+
if (size() != hash.size()) {
310+
return false;
311+
}
312+
/*
313+
* Most Properties comparisons are for cases where they are the same or very similar
314+
* so efficiency is fairly important to loading speed. They are commonly ordered in
315+
* the same fashion so take advantage of that in the comparison
316+
*/
317+
Set<Map.Entry<String, Object>> set1 = map.entrySet();
318+
Iterator<Map.Entry<String, Object>> iter1 = set1.iterator();
319+
320+
Set<Map.Entry<String, Object>> set2 = hash.map.entrySet();
321+
Iterator<Map.Entry<String, Object>> iter2 = set2.iterator();
322+
while (iter1.hasNext()) {
323+
var entry = iter1.next();
324+
// They are the same length so hasNext must be true
325+
Map.Entry<String, Object> next = iter2.next();
326+
if (entry.getKey().equals(next.getKey())) {
327+
if (!Objects.deepEquals(entry.getValue(), next.getValue())) {
328+
return false;
329+
}
330+
continue;
331+
}
332+
// Different key encountered so must resort to contains for all following values
333+
if (!Objects.deepEquals(entry.getValue(), hash.map.get(entry.getKey()))) {
334+
return false;
335+
}
336+
while (iter1.hasNext()) {
337+
entry = iter1.next();
338+
if (!Objects.deepEquals(entry.getValue(), hash.map.get(entry.getKey()))) {
339+
return false;
340+
}
341+
}
342+
}
343+
return true;
344+
}
345+
return super.equals(o);
346+
}
347+
306348
@Override
307349
public Property<?> atIndex(int index) {
308350
if (index >= size() || index < 0) {

visualizer/IdealGraphVisualizer/Data/src/main/java/jdk/graal/compiler/graphio/parsing/model/Properties.java

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ public Map<String, Object> toMap(Map<String, Object> props, Set<String> excludeN
114114
props.put(names[i], values[i]);
115115
}
116116
} else {
117-
P: for (int i = 0; i < size; ++i) {
117+
P:
118+
for (int i = 0; i < size; ++i) {
118119
String n = names[i];
119120
if (!excludes.contains(n)) {
120121
for (String p : excludePrefixes) {
@@ -313,7 +314,37 @@ public boolean equals(Object o) {
313314
if (size() != hash.size()) {
314315
return false;
315316
}
316-
return map.equals(hash.map);
317+
// Most Properties comparisons are for cases where they are the same or very similar
318+
// so efficiency is fairly important to loading speed. They are commonly ordered in the
319+
// same fashion so take advantage of that in the comparison
320+
Set<Map.Entry<String, Object>> set1 = map.entrySet();
321+
Iterator<Map.Entry<String, Object>> iter1 = set1.iterator();
322+
323+
Set<Map.Entry<String, Object>> set2 = hash.map.entrySet();
324+
Iterator<Map.Entry<String, Object>> iter2 = set2.iterator();
325+
while (iter1.hasNext()) {
326+
var entry = iter1.next();
327+
// They are the same length so hasNext must be true
328+
Map.Entry<String, Object> next = iter2.next();
329+
if (entry.getKey().equals(next.getKey())) {
330+
if (!Objects.deepEquals(entry.getValue(), next.getValue())) {
331+
return false;
332+
}
333+
continue;
334+
}
335+
// Different key encountered so must resort to contains for all following values
336+
if (!Objects.deepEquals(entry.getValue(), hash.map.get(entry.getKey()))) {
337+
return false;
338+
}
339+
while (iter1.hasNext()) {
340+
entry = iter1.next();
341+
if (!Objects.deepEquals(entry.getValue(), hash.map.get(entry.getKey()))) {
342+
return false;
343+
}
344+
}
345+
return true;
346+
}
347+
return true;
317348
}
318349
return super.equals(o);
319350
}
@@ -347,7 +378,8 @@ public Map<String, Object> toMap(Map<String, Object> props, Set<String> excludeN
347378
if (excludes.isEmpty() && excludePrefixes.length == 0) {
348379
props.putAll(map);
349380
} else {
350-
P: for (Map.Entry<String, Object> entry : map.entrySet()) {
381+
P:
382+
for (Map.Entry<String, Object> entry : map.entrySet()) {
351383
String n = entry.getKey();
352384
if (!excludes.contains(n)) {
353385
for (String p : excludePrefixes) {
@@ -484,10 +516,10 @@ protected final int makeHash() {
484516
int hash = 5;
485517
for (Property<?> prop : this) {
486518
hash = hash ^ (Property.makeHash(prop.getName(), prop.getValue())); // position affected
487-
// hash would
488-
// violate
489-
// equal/hash
490-
// contract
519+
// hash would
520+
// violate
521+
// equal/hash
522+
// contract
491523
}
492524
return hash;
493525
}
@@ -737,10 +769,10 @@ public RegexpPropertyMatcher(String name, String value) {
737769
/**
738770
* Constructs a regular expression based matcher.
739771
*
740-
* @param name name of the property to search
741-
* @param value pattern
772+
* @param name name of the property to search
773+
* @param value pattern
742774
* @param entireMatch whether the matcher should only accept full matches
743-
* @param flags flags to use to compile the pattern defined by {@code value}
775+
* @param flags flags to use to compile the pattern defined by {@code value}
744776
*/
745777
public RegexpPropertyMatcher(String name, String value, boolean entireMatch, int flags) {
746778
if (name == null) {
@@ -857,7 +889,7 @@ public <T> T get(String key, Class<T> clazz) {
857889
* {@link #get(java.lang.String, java.lang.Class)} will throw an exception/assertion on
858890
* non-String values.
859891
*
860-
* @param key property key
892+
* @param key property key
861893
* @param defValue value to be returned if the property is not defined or is {@code null}
862894
* @return String representation
863895
*/

0 commit comments

Comments
 (0)