From 18d848f218c6457c09d0daef6b65e4e939537743 Mon Sep 17 00:00:00 2001 From: Adrien Grand Date: Thu, 15 Mar 2018 16:39:02 +0100 Subject: [PATCH] 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 --- .../index/engine/LiveVersionMapTests.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/index/engine/LiveVersionMapTests.java b/server/src/test/java/org/elasticsearch/index/engine/LiveVersionMapTests.java index 8bfe256fe0b..8c5973e8750 100644 --- a/server/src/test/java/org/elasticsearch/index/engine/LiveVersionMapTests.java +++ b/server/src/test/java/org/elasticsearch/index/engine/LiveVersionMapTests.java @@ -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(); - // less than 25% off - assertEquals(actualRamBytesUsed, estimatedRamBytesUsed, actualRamBytesUsed / 4); + 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 + tolerance = actualRamBytesUsed / 4; + } + assertEquals(actualRamBytesUsed, estimatedRamBytesUsed, tolerance); } private BytesRef uid(String string) {