<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Bryan,<div><br></div><div><div><div>On 2010-02-02, at 7:49 PM, Bryan Thompson wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">
<div style="WORD-WRAP: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space">
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">Vladimir,</font></span></div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4"></font></span> </div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">I now have a workload where I have a hotspot on our cache
which is 8% of the total time. I am going to use this to test BCHM under a
realistic workload.</font></span></div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4"></font></span> </div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">One thing which I like about your design is that by placing
the array buffering the operations for a thread within the Segment, you are
using the lock guarding the Segment to control updates to that array.
While this has less potential throughput than a truely thread-local design
(which is non-blocking until the thread-local array is full), it seems that the
array buffering the updates can not "escape" under your design. Was this
intentional?</font></span></div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4"></font></span></div></div></blockquote><div><br></div><div>Yes. Escaping could also potentially be handled by shared pool of array buffers. Ideally shared pool would be some lock free structure since there would be a lot of contention among threads for these array buffers (that record accesses)</div><div> </div><div><br></div><br><blockquote type="cite"><div style="WORD-WRAP: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space"><div dir="ltr" align="left"> </div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">The danger with a true thread-local design is that a thread
can come in and do some work, get some updates buffered in its thread-local
array, and then never visit again. In this case those updates would remain
buffered on the thread and would not in fact cause the access order to be
updated in a timely manner. Worse, if you are relying on WeakReference
semantics, the buffered updates would remain strongly reachable and the
corresponding objects would be wired into the cache.</font></span></div></div></blockquote><div><br></div><div>Not if you return updates into above mentioned pool as the thread unwinds from call into cache (container). </div><br><blockquote type="cite"><div style="WORD-WRAP: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space">
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4"></font></span> </div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">I've worked around this issue in a different context where
it made sense to scope the buffers to an owning object (a B+Tree
instance). In that case, when the B+Tree container was closed, all
buffered updates were discarded. This nicely eliminated the problems with
"escaping" threads.</font></span></div></div></blockquote><div><br></div>Yes, there has to be some container boundary! In Infinispan this would be a cache instance, DataContainer to be exact. </div><div><br><blockquote type="cite"><div style="WORD-WRAP: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space">
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4"></font></span> </div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">However, I like your approach better.</font></span></div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4"></font></span> </div>
<div dir="ltr" align="left"><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">Bryan</font></span></div>
<div><font face="Courier New" color="#0000ff" size="4"></font> </div>
<div><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">PS: I see a comment on LRU#onEntryHit() indicating that it is invoked
without holding the Segment lock. Is that true only when BCHM#get() is
invoked?</font></span></div></div></blockquote><div><br></div><div>Yes, I'll change javadoc to say : "is potentially invoked without holding a lock".</div><br><blockquote type="cite"><div style="WORD-WRAP: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space">
<div><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4"></font></span> </div>
<div><span class="131211200-03022010"><font face="Courier New" color="#0000ff" size="4">PPS: Also, can you expand on the role of the LRU#accessQueue vs
LRU#lruQueue? Is there anything which corresponds to the total LRU order
(after batching updates through the Segment)?</font></span></div></div></blockquote><div><br></div><div><br></div><div>LRU#accessQueue records hits on a Segment. This is the batching FIFO queue from BP-Wrapper paper except it is not per thread but rather per Segment. Notice that LRU#accessQueue is lock free but thread safe since we expect a lot of threads recording accesses per Segment. Ideal collection for this use case is <span class="Apple-style-span" style="font-family: 'Lucida Grande'; font-size: 11px; ">ConcurrentLinkedQueue. </span></div><div><br></div><div>LRU#lruQueue is simply just a simple LRU stack implementation with one end of the queue holding most recently accessed entries and the other end of the queue with least recently accessed entries.</div><div><br></div><div><br></div><div>Regards,</div><div>Vladimir</div><div><br></div><div><br></div></div></div></body></html>