Created
November 4, 2021 23:57
-
-
Save automenta/298cb8b81cb41edec967c72d64177218 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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