📄 gclisteningdelaycache.java
字号:
// You can redistribute this software and/or modify it under the terms of// the Ozone Core License version 1 published by ozone-db.org.//// Copyright (C) 2003-@year@, Leo Mekenkamp. All rights reserved.//// $Id: GcListeningDelayCache.java,v 1.3.2.1 2004/03/28 16:40:04 per_nyfelt Exp $package org.ozoneDB.core.storage;import java.lang.ref.ReferenceQueue;import java.lang.ref.WeakReference;import java.util.Properties;import java.util.logging.Level;import java.util.logging.Logger;import org.ozoneDB.core.ConfigurationException;import org.ozoneDB.core.storage.DelayCache.TimedEntry;/** * @author <a href="mailto:leoATmekenkampD0Tcom">Leo Mekenkamp (mind the anti sp@m)</a> * @version $Id: GcListeningDelayCache.java,v 1.3.2.1 2004/03/28 16:40:04 per_nyfelt Exp $ */public class GcListeningDelayCache extends DelayCache { private static Logger log = Logger.getLogger(GcListeningDelayCache.class.getName()); public static final PropertyInfo HIGHTHRESHOLD = new PropertyInfo( ".highThreshold", "int", "10000000", "when free memory falls below this threshold this cache will start throwing out elements", new String[] {"10000", "50000000"} ); public static final PropertyInfo LOWTHRESHOLD = new PropertyInfo( ".lowThreshold", "int", "-1000000", "when free memory falls below this threshold this cache will throw out all elements (may be < 0)", new String[] {"1000", "-500000"} ); /** * gets cleared every time the jvm gc runs */ private WeakReference gcIndicator; private ReferenceQueue gcQueue = new ReferenceQueue(); private Thread gcIndicatorThread = new GcIndicatorThread(); private long lowThreshold; private long highThreshold; public GcListeningDelayCache(Properties properties, String prefix) { super(properties, prefix); gcIndicatorThread.start(); try { lowThreshold = Integer.parseInt(properties.getProperty(prefix + LOWTHRESHOLD.getKey(), LOWTHRESHOLD.getDefaultValue())); log.config(getPrefix() + " using a low threshold of " + lowThreshold); highThreshold = Integer.parseInt(properties.getProperty(prefix + HIGHTHRESHOLD.getKey(), HIGHTHRESHOLD.getDefaultValue())); log.config(getPrefix() + " using a high threshold of " + highThreshold); } catch (NumberFormatException e) { throw new ConfigurationException(e); } } /** * Creates an object that is only weakly referenced. There is a 1 on 1 * correspondance between this weak reference getting enqueued and a * jvm gc run */ private final void resetGcIndicator() { gcIndicator = new WeakReference(new Object(), gcQueue); } private void ourGC() { synchronized(getSynchronizer()) { if (size() > 0) { long freeMemory = Runtime.getRuntime().freeMemory(); if (freeMemory < getHighThreshold()) { // y == ax + b // 1 == a * low + b // 0 == a * high + b // // b == -a * high // // 1 == a * low - a * high // // a == 1 / (low - high) // // b == -high / (low - high) // // y == x / (low - high) - high / (low - high) // y == (x - high) / (low - high) float clearRatio = (float) (freeMemory - getHighThreshold()) / (float) (getLowThreshold() - getHighThreshold()); if (clearRatio > 0) { if (clearRatio > 1) { clearRatio = 1; } if (log.isLoggable(Level.FINE)) log.fine("removing " + clearRatio + " from cache"); int numToClear = (int) (size() * clearRatio); if (numToClear < 1) { numToClear = 1; } for (;numToClear > 0; numToClear--) { TimedEntry last = (TimedEntry) getEntries().last(); if (getTrimHandler() != null) { getTrimHandler().trimming(last.key, last.value); } getEntries().remove(last); getKeysToEntries().remove(last.key); } } } } } } /** * value in range <max(0,lowThreshold), 1] indicating when caches should * start throwing away entries. */ public void setHighThreshold(long highThreshold) { synchronized(getSynchronizer()) { if (highThreshold <= getLowThreshold()) { String msg = "could not set highThreshold to " + highThreshold + "; must be > lowThreshold (" + getLowThreshold() + ")"; log.severe(msg); throw new IllegalArgumentException(msg); } this.highThreshold = highThreshold; } } /** * value in range <0, min(1,highThreshold)] indicating when cache should * throw away all its entries. */ public void setLowThreshold(long lowThreshold) { synchronized(getSynchronizer()) { if (lowThreshold < 0 || lowThreshold >= getHighThreshold()) { String msg = "could not set lowThreshold to " + lowThreshold + "; must be >= 0 and <= highThreshold (" + getHighThreshold() + ")"; log.severe(msg); throw new IllegalArgumentException(msg); } this.lowThreshold = lowThreshold; } } public long getHighThreshold() { synchronized(getSynchronizer()) { return highThreshold; } } public synchronized long getLowThreshold() { synchronized(getSynchronizer()) { return lowThreshold; } } /** * Is woken up every time the gc has completed a run, or is in the process * of a run. The javadocs are a bit sketchy on this. Empirical data seems * to suggest the first. */ private class GcIndicatorThread extends Thread { GcIndicatorThread() { super(Thread.currentThread().getThreadGroup(), "gc indicator"); setDaemon(true); // setting priority to high to lessen the chance that another // thread does a lot of object creating during our run() setPriority(Thread.MAX_PRIORITY - 1); } public void run() { for (;;) { try { resetGcIndicator(); // only interested in 'when', not 'what', no 'Reference ref =' gcQueue.remove(); if (log.isLoggable(Level.FINE)) { Runtime runtime = Runtime.getRuntime(); log.fine("gc has kicked in (free mem: " + runtime.freeMemory() + ", total mem: " + runtime.totalMemory()); } ourGC(); } catch (InterruptedException ignore) { } } } } // DEBUG AND BUGTEST CODE ONLY FOLLOWING; not needed for normal operation static class Item { byte[] filling = new byte[100]; private Object key; Item(Object key) { this.key = key; } public String toString() { return key.toString(); } } public static void main(String[] args) { Properties properties = new Properties(); String prefix = "dbg"; properties.setProperty(prefix + LOWTHRESHOLD.getKey(), "-32000000"); properties.setProperty(prefix + HIGHTHRESHOLD.getKey(), "1000000"); properties.setProperty(prefix + DELAY.getKey(), "2000"); GcListeningDelayCache cache = new GcListeningDelayCache(properties, prefix); for (int i = 0; ; i++ ) { Object key = new Integer(i); Item item = new Item(key); // System.out.println("creating " + key + ", free: " + Runtime.getRuntime().freeMemory()); cache.put(key, item); if (i > 10) { // System.out.println("get(10): " + cache.get(new Integer(10))); } if (cache.size() % 100 == 0) { System.out.println("references in map: " + cache.size() + ", free: " + Runtime.getRuntime().freeMemory()); } } // System.out.println("completed sucessfully"); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -