Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Potential use for SoftReference with value (equals) equality

I previously come to the conclusion that if you need a SoftReference with value (equals) based equality then one had a bad design, excepting an interner from this. This is following Google Collections and Guava not including such a class. But I've come across an issue that I think could use such an object.

We have an asset management system in a visual effects render farm with 100's of processes running the same job that only differ in the frame number it renders. We have an Oracle database that needs to record all the assets used. Instead of pounding Oracle with identical inserts where only one will succeed from all the jobs, in the middle-tier asset management system we can use a HashSet to record if the object that would be inserted into Oracle.

I could use a Google MapMaker with an expiration, but I don't want to have to worry about getting the expiration correct, we have renders that run in hours and some over days. Using a SoftReference with equals equality sounds like a much better way so the JVM will manage garbage collection automatically.

For other problems that I want to solve with a ConcurrentHashMap with garbage collection, I would use a strong reference in the HashMap as the key to get equals() equality and a SoftReference as the value so the JVM can garbage collect something, but in this case, the value doesn't matter and I don't have a value to wrap in a SoftReference to put there. So it seems like using a SoftReference with equals() would do the trick.

Any other suggestions on this?

like image 266
Blair Zajac Avatar asked Feb 12 '10 07:02

Blair Zajac


2 Answers

In most cases when you want to use soft references with Google Collections, you should call

MapMaker.softValues()

With strong keys but soft values, lookups will use equality and key-value pairs will be garbage collected when memory is tight.

like image 169
Jared Levy Avatar answered Nov 07 '22 14:11

Jared Levy


Since there is no ConcurrentHashSet using soft references, there are only two approaches:

1.) Your approach with the ConcurrentHashMap

  • Override equals and hashCode in the SoftReference
  • Inside of equals and hashCode only access the object using SoftReference#get
  • Put SoftReference as key, and any object as value (only null is not permitted)
  • If the Reference goes stale while accessing hashCode or equals, add the reference to a deletion queue to frequently remove the keys which are dead.
  • Check for contains via containsKey

2.) Use a ConcurrentMultimap<Integer, Set<SoftReference<RepLookupEntry>> and use hashCode as key, and a synchronized set of SoftReferences as values. When you get a hashCode hit, then check the contents of all SoftReferences for equality. Not very pretty, I agree and tricky to synchronize.

If I were in your position, I would not use SoftReferences at all, but rather a ConcurrentHashMap to keep strong references to your POJOs. Each time a new element arrives also put it in a ConcurrentLinkQueue. If the queue grows beyond a certain limit start removing elements from the HashMap.

like image 24
Christopher Oezbek Avatar answered Nov 07 '22 15:11

Christopher Oezbek