All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.internal.cache.lru.HeapLRUCapacityController Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed 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. See accompanying
 * LICENSE file.
 */
package com.gemstone.gemfire.internal.cache.lru;

import java.util.Properties;

import com.gemstone.gemfire.StatisticDescriptor;
import com.gemstone.gemfire.StatisticsFactory;
import com.gemstone.gemfire.StatisticsType;
import com.gemstone.gemfire.StatisticsTypeFactory;
import com.gemstone.gemfire.cache.EvictionAction;
import com.gemstone.gemfire.cache.EvictionAlgorithm;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.util.ObjectSizer;
import com.gemstone.gemfire.internal.StatisticsTypeFactoryImpl;
import com.gemstone.gemfire.internal.cache.AbstractRegion;
import com.gemstone.gemfire.internal.cache.BucketRegion;
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
import com.gemstone.gemfire.internal.cache.LocalRegion;
import com.gemstone.gemfire.internal.cache.Token;
import com.gemstone.gemfire.internal.cache.control.InternalResourceManager;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;

/**
 * A HeapLRUCapacityController controls the contents of
 * {@link Region} based on the percentage of memory that is
 * currently being used. If the percentage of memory in use exceeds
 * the given percentage, then the least recently used entry of the region is
 * evicted.
 * 
 * 

* * For heap regions: * GemStone has found that the HeapLRUCapacityController has the * most effect on a VM that is lauched with both the -Xmx and * -Xms switches used. Many virtual machine implementations have * additional VM switches to control the behavior of the garbage collector. We * suggest that you investigate tuning the garbage collector when using a * HeapLRUCapacityController. In particular, we have found that * when running with Sun's HotSpot VM, the * -XX:+UseConcMarkSweepGC and -XX:+UseParNewGC * options improve the behavior of the HeapLRUCapacityController. * * @author David Whitlock * * @since 3.2 */ @SuppressWarnings("synthetic-access") public class HeapLRUCapacityController extends LRUAlgorithm { private static final long serialVersionUID = 4970685814429530675L; /** * The default percentage of VM heap usage over which LRU eviction occurs */ public static final String TOP_UP_HEAP_EVICTION_PERCENTAGE_PROPERTY = "gemfire.topUpHeapEvictionPercentage"; public static final float DEFAULT_TOP_UP_HEAP_EVICTION_PERCENTAGE = 4.0f; public static final int DEFAULT_HEAP_PERCENTAGE = 75; public static final int PER_ENTRY_OVERHEAD = 250; private int perEntryOverhead = PER_ENTRY_OVERHEAD; /** * The default number of milliseconds the evictor thread should wait before * evicting the LRU entry. */ public static final int DEFAULT_EVICTOR_INTERVAL = 500; protected static final StatisticsType statType; static { // create the stats type for MemLRU. StatisticsTypeFactory f = StatisticsTypeFactoryImpl.singleton(); final String entryBytesDesc = "The amount of memory currently used by regions configured for eviction."; final String lruEvictionsDesc = "Number of total entry evictions triggered by LRU."; final String lruDestroysDesc = "Number of entries destroyed in the region through both destroy cache operations and eviction. Reset to zero each time it exceeds lruDestroysLimit."; final String lruDestroysLimitDesc = "Maximum number of entry destroys triggered by LRU before scan occurs."; final String lruEvaluationsDesc = "Number of entries evaluated during LRU operations."; final String lruGreedyReturnsDesc = "Number of non-LRU entries evicted during LRU operations"; statType = f .createType( "HeapLRUStatistics", "Statistics about byte based Least Recently Used region entry disposal", new StatisticDescriptor[] { f.createLongGauge("entryBytes", entryBytesDesc, "bytes"), f.createLongCounter("lruEvictions", lruEvictionsDesc, "entries"), f.createLongCounter("lruDestroys", lruDestroysDesc, "entries"), f.createLongGauge("lruDestroysLimit", lruDestroysLimitDesc, "entries"), f.createLongCounter("lruEvaluations", lruEvaluationsDesc, "entries"), f.createLongCounter("lruGreedyReturns", lruGreedyReturnsDesc, "entries"), }); } // //////////////////// Instance Fields ///////////////////// // ////////////////////// Constructors /////////////////////// /** * Creates a new HeapLRUCapacityController with the given eviction action. * * @param evictionAction * The action that will occur when an entry is evicted * */ public HeapLRUCapacityController(EvictionAction evictionAction, Region region) { super(evictionAction, region); } public HeapLRUCapacityController(ObjectSizer sizerImpl,EvictionAction evictionAction, Region region) { super(evictionAction, region); setSizer(sizerImpl); } // ///////////////////// Instance Methods /////////////////////// @Override public void setLimit(int maximum) { } // Candidate for removal since capacity controller is no longer part of // cache.xml @Override public Properties getProperties() { throw new IllegalStateException("Unused properties"); } @Override public void close() { super.close(); } @Override public long getLimit() { return 0; } @Override public boolean equals(Object cc) { if (!super.equals(cc)) return false; return true; } /* * (non-Javadoc) * @see java.lang.Object#hashCode() * * Note that we just need to make sure that equal objects return equal * hashcodes; nothing really elaborate is done here. */ @Override public int hashCode() { int result = super.hashCode(); return result; } /** * Returns a brief description of this eviction controller. * * @since 4.0 */ @Override public String toString() { return LocalizedStrings.HeapLRUCapacityController_HEAPLRUCAPACITYCONTROLLER_WITH_A_CAPACITY_OF_0_OF_HEAP_AND_AN_THREAD_INTERVAL_OF_1_AND_EVICTION_ACTION_2.toLocalizedString(new Object[] { Long.valueOf(this.getLimit()), this.getEvictionAction()}); } /** * Sets the {@link ObjectSizer} used to calculate the size of * objects placed in the cache. * * @param sizer * The name of the sizer class */ private void setSizer(ObjectSizer sizer) { this.sizer = sizer; } @Override protected EnableLRU createLRUHelper() { return new AbstractEnableLRU() { /** * Indicate what kind of EvictionAlgorithm this helper * implements */ public EvictionAlgorithm getEvictionAlgorithm() { return EvictionAlgorithm.LRU_HEAP; } /** * As far as we're concerned all entries have the same size */ public int entrySize(Object key, Object value) throws IllegalArgumentException { // value is null only after eviction occurs. A change in size is // required for eviction stats, bug 30974 /* * if (value != null) { return 1; } else { return 0; } */ if (value == Token.TOMBSTONE) { return 0; } int size = HeapLRUCapacityController.this.getPerEntryOverhead(); size += sizeof(key); size += sizeof(value); return size; } /** * In addition to initializing the statistics, create an evictor thread to * periodically evict the LRU entry. */ @Override public LRUStatistics initStats(Object region, StatisticsFactory sf) { setRegionName(region); final LRUStatistics stats = new HeapLRUStatistics(sf, getRegionName(), this); setStats(stats); return stats; } public StatisticsType getStatisticsType() { return statType; } public String getStatisticsName() { return "HeapLRUStatistics"; } public int getLimitStatId() { throw new UnsupportedOperationException("Limit not used with this LRU type"); } public int getCountStatId() { return statType.nameToId("entryBytes"); } public int getEvictionsStatId() { return statType.nameToId("lruEvictions"); } public int getDestroysStatId() { return statType.nameToId("lruDestroys"); } public int getDestroysLimitStatId() { return statType.nameToId("lruDestroysLimit"); } public int getEvaluationsStatId() { return statType.nameToId("lruEvaluations"); } public int getGreedyReturnsStatId() { return statType.nameToId("lruGreedyReturns"); } /** * Okay, deep breath. Instead of basing the LRU calculation on the number * of entries in the region or on their "size" (which turned out to be * incorrectly estimated in the general case), we use the amount of * memory currently in use. If the amount of memory current in use * {@linkplain Runtime#maxMemory max memory} - * {@linkplain Runtime#freeMemory free memory} is greater than the * overflow threshold, then we evict the LRU entry. */ public boolean mustEvict(LRUStatistics stats, Region region, int delta) { final GemFireCacheImpl cache; if (region != null) { cache = (GemFireCacheImpl) region.getRegionService(); } else { cache = GemFireCacheImpl.getInstance(); } InternalResourceManager resourceManager = cache.getResourceManager(); if (region == null) { return resourceManager.getHeapMonitor().getState().isEviction(); } final boolean monitorStateIsEviction; if (!((AbstractRegion) region).getEnableOffHeapMemory()) { monitorStateIsEviction = resourceManager.getHeapMonitor().getState().isEviction(); } else { monitorStateIsEviction = resourceManager.getOffHeapMonitor().getState().isEviction(); } if (region instanceof BucketRegion) { return monitorStateIsEviction && ((BucketRegion) region).getSizeForEviction() > 0; } return monitorStateIsEviction && ((LocalRegion) region).getRegionMap().sizeInVM() > 0; } }; } // ////////////////////// Inner Classes //////////////////////// private ObjectSizer sizer; /** * Return the size of an object as stored in GemFire... Typically this is the * serialized size in bytes.. This implementation is slow.... Need to add * Sizer interface and call it for customer objects. */ protected int sizeof(Object o) throws IllegalArgumentException { return MemLRUCapacityController.basicSizeof(o, this.sizer); } public int getPerEntryOverhead() { return perEntryOverhead; } public void setEntryOverHead(int entryOverHead) { this.perEntryOverhead = entryOverHead; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy