Fix testShardsAreSomewhatBalanced to only check for shards that are too big, and avoid nondeterministic behavior due to garbage collection. (If there are any more platform-specific failures, they will be due to differences in String.hashCode().)
Review at http://gwt-code-reviews.appspot.com/1578810
Review by: rdayal@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10732 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/util/StringInterner.java b/dev/core/src/com/google/gwt/dev/util/StringInterner.java
index 106e0e9..ee4fbf0 100644
--- a/dev/core/src/com/google/gwt/dev/util/StringInterner.java
+++ b/dev/core/src/com/google/gwt/dev/util/StringInterner.java
@@ -53,20 +53,14 @@
* Returns a string equal to the input string, but not always the same.
*/
public String intern(String original) {
- int hashCode = original.hashCode();
- int shardId = (hashCode ^ (hashCode >> SHARD_BITS)) & SHARD_MASK;
+ int shardId = getShardId(original);
return shards[shardId].intern(original);
}
- /**
- * Returns the size of each shard, for testing shard balance.
- */
- int[] getShardSizes() {
- int[] result = new int[SHARD_COUNT];
- for (int i = 0; i < shards.length; i++) {
- result[i] = shards[i].map.size();
- }
- return result;
+ /* visible for testing */
+ int getShardId(String original) {
+ int hashCode = original.hashCode();
+ return (hashCode ^ (hashCode >> SHARD_BITS)) & SHARD_MASK;
}
private static class Shard {
diff --git a/dev/core/test/com/google/gwt/dev/util/StringInternerTest.java b/dev/core/test/com/google/gwt/dev/util/StringInternerTest.java
index c17104a..ab98ee4 100644
--- a/dev/core/test/com/google/gwt/dev/util/StringInternerTest.java
+++ b/dev/core/test/com/google/gwt/dev/util/StringInternerTest.java
@@ -51,28 +51,33 @@
}
public void testShardsAreSomewhatBalanced() throws Exception {
- for (int i = 0; i < 1000000; i++) {
- interner.intern("foo" + i);
+
+ // Simulate adding a million strings. We use the production algorithm to choose the shard,
+ // but increment a counter instead. This avoids the WeakHashMap's nondeterministic
+ // behavior due to garbage collection.
+ int meanShardSize = 1000;
+ int shardSizes[] = new int[StringInterner.SHARD_COUNT];
+ int stringsToAdd = StringInterner.SHARD_COUNT * meanShardSize;
+ for (int i = 0; i < stringsToAdd; i++) {
+ int shardId = interner.getShardId("foo" + i);
+ shardSizes[shardId]++;
}
- int[] shardSizes = interner.getShardSizes();
- assertEquals(StringInterner.SHARD_COUNT, shardSizes.length);
+ // Verify that no shards are too big. (A shard that's oversized could create lock contention.)
- int minShardSize = Integer.MAX_VALUE;
+ int expectedMaxShardSize = meanShardSize * 2;
int maxShardSize = 0;
- int total = 0;
- for (int candidate : shardSizes) {
- minShardSize = Math.min(minShardSize, candidate);
- maxShardSize = Math.max(maxShardSize, candidate);
- total += candidate;
+ int tooBigShardCount = 0;
+ for (int shardSize : shardSizes) {
+ maxShardSize = Math.max(maxShardSize, shardSize);
+ if (shardSize > expectedMaxShardSize) {
+ tooBigShardCount++;
+ }
}
- int meanShardSize = total / shardSizes.length;
- int expectedMinShardSize = meanShardSize / 5;
- int expectedMaxShardSize = meanShardSize * 5;
- if (minShardSize < expectedMinShardSize || maxShardSize > expectedMaxShardSize) {
- fail("unbalanced shards: [" + minShardSize + "," + maxShardSize + "] not within [" +
- expectedMinShardSize + ", " + expectedMaxShardSize + "]");
+ if (tooBigShardCount > 0) {
+ fail(tooBigShardCount + " of " + shardSizes.length + " shards are too big (more than " +
+ expectedMaxShardSize + " entries); largest shard has " + maxShardSize + " entries.");
}
}