Unsafe convergent cache for traces#1101
Unsafe convergent cache for traces#1101RaasAhsan wants to merge 4 commits intotypelevel:series/2.xfrom
Conversation
| return this.array[hash]; | ||
| } | ||
|
|
||
| public Buffer grow() { |
There was a problem hiding this comment.
TODO: pass the key value pair that caused the original collision here to insert
| } | ||
|
|
||
| public Node<K, V> put(K k, V v) { | ||
| int hash = k.hashCode() & this.mask; |
There was a problem hiding this comment.
CHM and HM have another way of generating the hash, will look into that
|
Storing strong references to the lambda classes as the key of the frame cache smells like a potential classloader leak when the lambda class is loaded from a classloader with a shorter lifecycle than cats-eval's classloader.
|
TIL! |
Didn't know that either, thanks! We've also noticed that |
That doesn't sound right to me, it statically resolves to |
|
I'll take a look at those! We did a bit of digging and arrived at the same conclusion about the |
|
I forgot to mention, the likely implementation for this cache actually won't retain any class references. We're acknowledging that tracing is an imprecise approximation, so in order to speed up reads, we'll only keep one value per array index. This means that we're effectively ignoring collisions, and to lower collision probability, we can grow the size of the array. |
|
Going to do this on CE3 |
This should be the last PR to have tracing ready for 2.2.0. The current version of tracing relies on
ConcurrentHashMapto keep a cache of traces. As described in #1076,ConcurrentHashMapoffers thread safety at the cost of synchronization via read barriers on the hot read path. Because the cache will eventually converge to an optimal set, it's OK if we don't have safe publication (different threads may not see the same cache), as long as the objects we do see are all safely initialized. Safe initialization means that an object values initialized in a constructor are visible to threads who observe a shared reference to the object. This property is implicitly guaranteed with the usual synchronization primitives that offer thread safety.The Java memory model offers another method of achieving safe initialization that is much cheaper than synchronization: final fields. The semantics of final fields dictate that as long as
thisdoesn't escape during the constructor of an object and that its final fields are set before the constructor completes, then any thread who observes a shared reference of the initialized object will observe fully initialized values for its final fields, and that guarantee extends transitively.We leverage these semantics to build a thread-unsafe, convergent cache that achieves a higher read throughput than
ConcurrentHashMap.TODO:
maskCloses #1076.