/kernel/src/main/java/org/neo4j/kernel/impl/cache/AdaptiveCacheManager.java
https://github.com/boyaxxx/community · Java · 377 lines · 314 code · 37 blank · 26 comment · 39 complexity · 9cf772f4c684225272745a265ebfd62c MD5 · raw file
- /**
- * Copyright (c) 2002-2011 "Neo Technology,"
- * Network Engine for Objects in Lund AB [http://neotechnology.com]
- *
- * This file is part of Neo4j.
- *
- * Neo4j is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package org.neo4j.kernel.impl.cache;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Map;
- import java.util.logging.Logger;
- public class AdaptiveCacheManager
- {
- private static final Logger log = Logger
- .getLogger( AdaptiveCacheManager.class.getName() );
- private float decreaseRatio = 1.15f;
- private float increaseRatio = 1.1f;
- private final List<AdaptiveCacheElement> caches =
- new LinkedList<AdaptiveCacheElement>();
- private final List<ReferenceCache<?,?>> referenceCaches =
- new ArrayList<ReferenceCache<?,?>>();
-
- private AdaptiveCacheWorker workerThread;
- public synchronized void registerCache( Cache<?,?> cache, float ratio,
- int minSize )
- {
- if ( cache == null || ratio >= 1 || ratio <= 0 || minSize < 0 )
- {
- throw new IllegalArgumentException( " cache=" + cache + " ratio ="
- + ratio + " minSize=" + minSize );
- }
-
- if ( cache instanceof ReferenceCache<?,?> )
- {
- referenceCaches.add( (ReferenceCache<?,?>) cache );
- return;
- }
-
- for ( AdaptiveCacheElement element : caches )
- {
- if ( element.getCache() == cache )
- {
- log.fine( "Cache[" + cache.getName() +
- "] already registered." );
- return;
- }
-
- }
- AdaptiveCacheElement element = new AdaptiveCacheElement( cache, ratio,
- minSize );
- caches.add( element );
- cache.setAdaptiveStatus( true );
- log.fine( "Cache[" + cache.getName() + "] threshold=" + ratio
- + "minSize=" + minSize + " registered." );
- }
- public synchronized void unregisterCache( Cache<?,?> cache )
- {
- if ( cache == null )
- {
- throw new IllegalArgumentException( "Null cache" );
- }
- if ( cache instanceof SoftLruCache<?,?> )
- {
- referenceCaches.remove( cache );
- return;
- }
- Iterator<AdaptiveCacheElement> itr = caches.iterator();
- while ( itr.hasNext() )
- {
- AdaptiveCacheElement element = itr.next();
- if ( element.getCache() == cache )
- {
- itr.remove();
- break;
- }
- }
- log.fine( "Cache[" + cache.getName() + "] removed." );
- }
- synchronized AdaptiveCacheElement getAdaptiveCacheElementIndex(
- Cache<?,?> cache )
- {
- for ( AdaptiveCacheElement element : caches )
- {
- if ( element.getCache() == cache )
- {
- return element;
- }
- }
- return null;
- }
- private void parseParams( Map<Object,Object> params )
- {
- if ( params == null )
- {
- return;
- }
- if ( params.containsKey( "adaptive_cache_worker_sleep_time" ) )
- {
- Object value = params.get( "adaptive_cache_worker_sleep_time" );
- int sleepTime = 3000;
- try
- {
- sleepTime = Integer.parseInt( (String) value );
- }
- catch ( NumberFormatException e )
- {
- log.warning(
- "Unable to parse apdaptive_cache_worker_sleep_time " +
- value );
- }
- workerThread.setSleepTime( sleepTime );
- }
- if ( params.containsKey( "adaptive_cache_manager_decrease_ratio" ) )
- {
- Object value = params.get(
- "adaptive_cache_manager_decrease_ratio" );
- try
- {
- decreaseRatio = Float.parseFloat( (String) value );
- }
- catch ( NumberFormatException e )
- {
- log.warning(
- "Unable to parse adaptive_cache_manager_decrease_ratio " +
- value );
- }
- if ( decreaseRatio < 1 )
- {
- decreaseRatio = 1.0f;
- }
- }
- if ( params.containsKey( "adaptive_cache_manager_increase_ratio" ) )
- {
- Object value = params.get(
- "adaptive_cache_manager_increase_ratio" );
- try
- {
- increaseRatio = Float.parseFloat( (String) value );
- }
- catch ( NumberFormatException e )
- {
- log.warning(
- "Unable to parse adaptive_cache_manager_increase_ratio " +
- value );
- }
- if ( increaseRatio < 1 )
- {
- increaseRatio = 1.0f;
- }
- }
- }
- public void start( Map<Object,Object> params )
- {
- workerThread = new AdaptiveCacheWorker();
- parseParams( params );
- workerThread.start();
- }
- public void stop()
- {
- workerThread.markDone();
- workerThread = null;
- }
- Collection<AdaptiveCacheElement> getCaches()
- {
- return caches;
- }
- private class AdaptiveCacheWorker extends Thread
- {
- private boolean done = false;
- private int sleepTime = 3000;
- AdaptiveCacheWorker()
- {
- super( "AdaptiveCacheWorker" );
- }
- void setSleepTime( int sleepTime )
- {
- this.sleepTime = sleepTime;
- }
- public synchronized void run()
- {
- while ( !done )
- {
- try
- {
- adaptReferenceCaches();
- adaptCaches();
- this.wait( sleepTime );
- }
- catch ( InterruptedException e )
- {
- Thread.interrupted();
- }
- }
- }
- void markDone()
- {
- done = true;
- }
- }
-
- public void adaptCaches()
- {
- List<AdaptiveCacheElement> copy =
- new LinkedList<AdaptiveCacheElement>();
- synchronized ( this )
- {
- copy.addAll( caches );
- }
- for ( AdaptiveCacheElement element : copy )
- {
- adaptCache( element );
- }
- }
- public synchronized void adaptReferenceCaches()
- {
- for ( ReferenceCache<?,?> cache : referenceCaches )
- {
- cache.pollClearedValues();
- }
- }
-
- public void adaptCache( Cache<?,?> cache )
- {
- if ( cache == null )
- {
- throw new IllegalArgumentException( "Null cache" );
- }
-
- AdaptiveCacheElement element = getAdaptiveCacheElementIndex( cache );
- if ( element != null )
- {
- adaptCache( element );
- }
- }
-
- private void adaptCache( AdaptiveCacheElement element )
- {
- long max = Runtime.getRuntime().maxMemory();
- long total = Runtime.getRuntime().totalMemory();
- long free = Runtime.getRuntime().freeMemory();
- float ratio = (float) (max - free) / max;
- float allocationRatio = (float) total / max;
- if ( allocationRatio < element.getRatio() )
- {
- // allocation ratio < 1 means JVM can still increase heap size
- // we won't decrease caches until element ratio is less
- // then allocationRatio
- ratio = 0;
- }
- if ( ratio > element.getRatio() )
- {
- // decrease cache size
- // after decrease we resize again with +1000 to avoid
- // spam of this method
- Cache<?,?> cache = element.getCache();
- int newCacheSize = (int) ( cache.maxSize() / decreaseRatio /
- (1 + (ratio - element.getRatio())) );
- int minSize = element.minSize();
- if ( newCacheSize < minSize )
- {
- log.fine( "Cache[" + cache.getName() +
- "] cannot decrease under " + minSize +
- " (allocation ratio=" + allocationRatio +
- " threshold status=" + ratio + ")" );
- cache.resize( minSize );
- cache.resize( minSize + 1000 );
- return;
- }
- if ( newCacheSize + 1200 > cache.size() )
- {
- if ( cache.size() - 1200 >= minSize )
- {
- newCacheSize = cache.size() - 1200;
- }
- else
- {
- newCacheSize = minSize;
- }
- }
- log.fine( "Cache[" + cache.getName() + "] decreasing from " +
- cache.size() + " to " + newCacheSize + " (allocation ratio=" +
- allocationRatio + " threshold status=" + ratio + ")" );
- if ( newCacheSize <= 1000 )
- {
- cache.clear();
- }
- else
- {
- cache.resize( newCacheSize );
- }
- cache.resize( newCacheSize + 1000 );
- }
- else
- {
- // increase cache size
- Cache<?,?> cache = element.getCache();
- if ( cache.size() / (float) cache.maxSize() < 0.9f )
- {
- return;
- }
- int newCacheSize = (int) (cache.maxSize() * increaseRatio);
- log.fine( "Cache[" + cache.getName() + "] increasing from " +
- cache.size() + " to " + newCacheSize + " (allocation ratio=" +
- allocationRatio + " threshold status=" + ratio + ")" );
- cache.resize( newCacheSize );
- }
- }
- private static class AdaptiveCacheElement
- {
- private final Cache<?,?> cache;
- private final float ratio;
- private final int minSize;
- AdaptiveCacheElement( Cache<?,?> cache, float ratio, int minSize )
- {
- this.cache = cache;
- this.ratio = ratio;
- this.minSize = minSize;
- }
- Cache<?,?> getCache()
- {
- return cache;
- }
- float getRatio()
- {
- return ratio;
- }
- int minSize()
- {
- return minSize;
- }
- }
- }