Skip to content

Instantly share code, notes, and snippets.

@jnorthrup
Forked from automenta/FuzzyReference.java
Created November 5, 2021 08:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jnorthrup/7320b48fa8cd23899c691d94fd667f7e to your computer and use it in GitHub Desktop.
Save jnorthrup/7320b48fa8cd23899c691d94fd667f7e to your computer and use it in GitHub Desktop.
/**
* Numerically re-prioritizable reference.
* Repurposes SoftReference.timestamp field as a priority value.
* <p>
* Intended to re-use all SoftReference-related VM features
* except its time-as-priority behavior.
*
* TODO this requires some modifications to internal JVM GC behavior.
*/
public class FuzzyReference<T> extends SoftReference<T> {
private static final VarHandle PRI = VAR(SoftReference.class, "timestamp", long.class);
private static final VarHandle REF = VAR(Reference.class, "referent", Object.class);
/**
* default constructor. priority initialized to 0
*
* @param referent reference
*/
public FuzzyReference(T referent) {
this(referent, 0);
}
/**
* default constructor
*
* @param referent reference
* @param pri initial priority
*/
public FuzzyReference(T referent, long pri) {
super(referent);
pri(pri);
}
/**
* default constructor, with ReferenceQueue. see SoftReference constructor for details
*
* @param referent reference
* @param q queue
*/
public FuzzyReference(T referent, ReferenceQueue<T> q) {
super(referent, q);
pri(0);
}
/**
* @return reference priority
*/
public final long pri() {
return (long) PRI.get(this);
}
/**
* sets reference priority
*
* @param p new priority value
*/
public final void pri(long p) {
PRI.set(this, p);
}
/**
* @return reference, without triggering: SoftReference.timestamp=clock
*/
@Override
public T get() {
return (T) REF.get(this);
}
public static VarHandle VAR(Class c, String field, Class<?> type) {
try {
return MethodHandles.privateLookupIn(c, lookup())
.findVarHandle(c, field, type)
.withInvokeExactBehavior();
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
@Disabled
class FuzzyReferenceTest {
long BASE = Long.MAX_VALUE - Integer.MAX_VALUE*2L;
@Test
public void test1() {
int n = 24*1024;
List<FuzzyReference> l = new Lst<>(n);
Random rng =
new XoRoShiRo128PlusRandom();
// new XorShift128PlusRandom();
//new Random();
// List<String> held = new Lst<>(n);
//for (int i = 0; i < n; i++) {
for (int i = n-1; i >= 0; i--) {
int k = rng.nextInt(Integer.MAX_VALUE);
l.add(new FuzzyReference(new Object[256], k + BASE));
// held.add(I);
}
// count(l);
// held.clear(); System.gc();
System.gc();
count(l);
}
private void count(List<FuzzyReference> l) {
int collected = 0;
long minPri = Integer.MAX_VALUE, maxPri = Integer.MIN_VALUE;
Histogram c = new Histogram(5);
Histogram r = new Histogram(5);
for (FuzzyReference x : l) {
long p = x.pri() - BASE;
if (x.get()==null) {
//System.out.println(x.pri());
collected++;
assert(p < Integer.MAX_VALUE);
minPri = Math.min(p, minPri);
maxPri = Math.max(p, maxPri);
c.recordValue(p);
} else
r.recordValue(p);
}
System.out.println("collected: " + collected + " / " + l.size() + " (" + n4(collected/((float)l.size())*100f) + "%)");
// System.out.println(" min: " + minPri);
// System.out.println(" max: " + maxPri);
// Str.histogramPrint(c, System.out);
System.out.println("mean collected: " + c.getMean() /Integer.MAX_VALUE);
System.out.println(" mean remain: " + r.getMean() /Integer.MAX_VALUE);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment