| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the License. You may obtain a |
| * copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package org.apache.geode.cache.lucene.internal.repository; |
| |
| |
| import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.INDEX_NAME; |
| |
| import java.nio.charset.Charset; |
| import java.util.Random; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.apache.logging.log4j.Logger; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| import org.springframework.shell.converters.AvailableCommandsConverter; |
| |
| import org.apache.geode.cache.Region; |
| import org.apache.geode.cache.RegionShortcut; |
| import org.apache.geode.cache.lucene.LuceneIntegrationTest; |
| import org.apache.geode.cache.lucene.test.TestObject; |
| import org.apache.geode.cache.partition.PartitionRegionHelper; |
| import org.apache.geode.internal.cache.InternalCache; |
| import org.apache.geode.internal.cache.TombstoneService; |
| import org.apache.geode.internal.size.ObjectGraphSizer; |
| import org.apache.geode.logging.internal.log4j.api.LogService; |
| import org.apache.geode.test.junit.categories.LuceneTest; |
| import org.apache.geode.test.junit.categories.PerformanceTest; |
| |
| @Category({PerformanceTest.class, LuceneTest.class}) |
| @Ignore("Tests have no assertions") |
| public class LuceneIndexMemoryOverheadTest extends LuceneIntegrationTest { |
| private static final String REGION_NAME = "index"; |
| private static int NUM_BATCHES = 30; |
| private static int NUM_ENTRIES = 10000; |
| private Random random = new Random(0); |
| |
| private static final Logger logger = LogService.getLogger(); |
| private Callable flush = |
| () -> luceneService.waitUntilFlushed(INDEX_NAME, REGION_NAME, 60000, TimeUnit.MILLISECONDS); |
| protected static ObjectGraphSizer.ObjectFilter filter = |
| (parent, object) -> !(object instanceof AvailableCommandsConverter); |
| |
| @Test |
| public void perEntryNonIndexMemoryWithTombstoneGC() throws Exception { |
| measureOverhead(((InternalCache) cache).getTombstoneService(), () -> true); |
| } |
| |
| @Test |
| public void perEntryNonIndexMemoryWithoutTombstoneGC() throws Exception { |
| measureOverhead(null, () -> true); |
| } |
| |
| @Test |
| public void perEntryIndexMemoryWithTombstoneGC() throws Exception { |
| luceneService.createIndexFactory().setFields("field1", "field2").create(INDEX_NAME, |
| REGION_NAME); |
| |
| measureOverhead(((InternalCache) cache).getTombstoneService(), flush); |
| } |
| |
| @Test |
| public void perEntryIndexMemoryWithoutTombstoneGC() throws Exception { |
| luceneService.createIndexFactory().setFields("field1", "field2").create(INDEX_NAME, |
| REGION_NAME); |
| |
| measureOverhead(null, flush); |
| } |
| |
| private void waitForFlush(Callable flush) throws Exception { |
| while (flush.call().equals(false)) { |
| logger.info("Flush returned false. Waiting for flush to return true..."); |
| } |
| } |
| |
| private void measureOverhead(TombstoneService service, Callable flush) throws Exception { |
| |
| Region region = cache.createRegionFactory(RegionShortcut.PARTITION).create(REGION_NAME); |
| PartitionRegionHelper.assignBucketsToPartitions(region); |
| |
| long emptySize = ObjectGraphSizer.size(cache, filter, false); |
| waitForFlush(flush); |
| |
| long size; |
| int numEntries = 0; |
| |
| for (int batch = 0; batch < NUM_BATCHES; batch++) { |
| |
| size = |
| addEntriesAndGetMemorySize(region, numEntries, NUM_ENTRIES, service, flush) - emptySize; |
| numEntries = region.size(); |
| |
| logger.info( |
| numEntries + " entries take up " + size + ", per entry overhead " + size / numEntries); |
| } |
| } |
| |
| private long addEntriesAndGetMemorySize(Region region, int start, int count, |
| TombstoneService service, Callable flush) throws Exception { |
| int c = 0; |
| for (int i = start; i < start + count; i++) { |
| byte[] field1 = new byte[3]; |
| byte[] field2 = new byte[5]; |
| random.nextBytes(field1); |
| random.nextBytes(field2); |
| TestObject test = new TestObject(new String(field1, Charset.forName("ASCII")), |
| new String(field2, Charset.forName("ASCII"))); |
| region.put(i, test); |
| } |
| |
| waitForFlush(flush); |
| if (service != null) |
| service.forceBatchExpirationForTests((int) service.getScheduledTombstoneCount()); |
| |
| return ObjectGraphSizer.size(cache, filter, false); |
| } |
| } |