hg: lambda/lambda/jdk: - ensure null values are retained

Paul Sandoz paul.sandoz at oracle.com
Wed Dec 5 01:43:54 PST 2012


On Dec 5, 2012, at 9:46 AM, Remi Forax <forax at univ-mlv.fr> wrote:

> On 12/04/2012 02:53 PM, Paul Sandoz wrote:
>> On Dec 4, 2012, at 2:26 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>> 
>>> On 12/04/2012 11:44 AM, Paul Sandoz wrote:
>>>> Hi Remi,
>>>> 
>>>> Many thanks, that is just the kind of VM-perspective advice i was looking for. I was assuming that the VM would be able to somehow inline the hot path to the else block.
>>> yes, but you don't need a supplementary field for that.
>>> 
>> Right, but subjectively i think it is marginally clearer code.
>> 
>> 
>>>> So you are suggesting something like this:
>>>> 
>>>>                     T _t = (T) maskNull(t);
>>>>                     if (lastSeen == null || !lastSeen.equals(_t)) {
>>>>                         lastSeen = _t;
>>>>                         downstream.accept(t);
>>>>                     }
>>> I was thinking to something like this:
>>> 
>>>             return new Sink.ChainedReference<T>(sink) {
>>>                 private Object lastSeen;
>>> 
>>>                 @Override
>>>                 public void begin(long size) {
>>>                     lastSeen = null;            // not needed if end() is called in a finally ?
>> It's not needed.
>> 
>> 
>>>                     downstream.begin(-1);
>>>                 }
>>> 
>>>                 @Override
>>>                 public void end() {
>>>                     lastSeen = null;
>>>                     downstream.end();
>>>                 }
>>> 
>>>                 @Override
>>>                 public void accept(T t) {
>>>                     if (t == null) {
>>>                         if (lastSeen != NULL_OBJECT) {
>>>                             lastSeen = NULL_OBJECT
>>>                             downstream.accept(null);
>>>                         }
>>>                     } else if (lastSeen == null || !t.equals(lastSeen)) {
>>>                         lastSeen = t;
>>>                         downstream.accept((T)t);
>>>                     }
>>>                 }
>>>             };
>>> 
>> If one assumes nulls are rare is there any performance advantage (beyond the extra field not being used) to using the null object design pattern in this context?
> 
> Not for this code, but remember that I've sent the mail for the whole patch.

I realize that :-) just confused on the context of some of your comments.

 
> I believe that that an holistic approach should be used in all ops, 
> because all ops need to deal with null.
> 

Agreed. I think a little helper class may be in order to avoid peppering static final Object NULL/NONE = new Object() and mask methods all over the place.


>> 
>> I am trying and failing to correlate what you say below with the code base:
>> 
>> "Your solution require to load/store value from the RAM because the VM will not able to optimize this code (inlining is often  defeated due to the fact that the call between ops is a virtual call)."
> 
> I've written this sentence when I've read the last lines of your patch, 
> the one that use an AtomicInteger because you can't store null in a CHM.
> Masking null in that case avoid multiple accesses to the RAM.
> 

Thanks,
Paul.


More information about the lambda-dev mailing list