Reenable LiveVersionMapTests.testRamBytesUsed on Java 9. (#29063)

I also had to make the test more lenient. This is due to the fact that
Lucene's RamUsageTester was changed in order not to reflect `java.*`
classes and the way that it estimates ram usage of maps is by assuming
it has similar memory usage to an `Object[]` array that stores all keys
and values. The implementation in `LiveVersionMap` tries to be slightly
more realistic by taking the load factor and linked lists into account,
so it usually gives a higher estimate which happens to be closer to
reality.

Closes #22548
This commit is contained in:
Adrien Grand 2018-03-15 16:39:02 +01:00 committed by GitHub
parent 85933161d4
commit 18d848f218
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 18 additions and 5 deletions

View File

@ -21,10 +21,9 @@ package org.elasticsearch.index.engine;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
import org.apache.lucene.util.Constants;
import org.apache.lucene.util.RamUsageTester;
import org.apache.lucene.util.TestUtil;
import org.elasticsearch.Assertions;
import org.elasticsearch.bootstrap.JavaVersion;
import org.elasticsearch.common.lease.Releasable;
import org.elasticsearch.test.ESTestCase;
@ -43,7 +42,6 @@ import java.util.stream.StreamSupport;
public class LiveVersionMapTests extends ESTestCase {
public void testRamBytesUsed() throws Exception {
assumeTrue("Test disabled for JDK 9", JavaVersion.current().compareTo(JavaVersion.parse("9")) < 0);
LiveVersionMap map = new LiveVersionMap();
for (int i = 0; i < 100000; ++i) {
BytesRefBuilder uid = new BytesRefBuilder();
@ -72,8 +70,23 @@ public class LiveVersionMapTests extends ESTestCase {
}
actualRamBytesUsed = RamUsageTester.sizeOf(map);
estimatedRamBytesUsed = map.ramBytesUsed();
long tolerance;
if (Constants.JRE_IS_MINIMUM_JAVA9) {
// With Java 9, RamUsageTester computes the memory usage of maps as
// the memory usage of an array that would contain exactly all keys
// and values. This is an under-estimation of the actual memory
// usage since it ignores the impact of the load factor and of the
// linked list/tree that is used to resolve collisions. So we use a
// bigger tolerance.
// less than 50% off
tolerance = actualRamBytesUsed / 2;
} else {
// Java 8 is more accurate by doing reflection into the actual JDK classes
// so we give it a lower error bound.
// less than 25% off
assertEquals(actualRamBytesUsed, estimatedRamBytesUsed, actualRamBytesUsed / 4);
tolerance = actualRamBytesUsed / 4;
}
assertEquals(actualRamBytesUsed, estimatedRamBytesUsed, tolerance);
}
private BytesRef uid(String string) {