[infinispan-dev] Avoid Collections.emptySet() / emptyMap() / emptyList

David M. Lloyd david.lloyd at redhat.com
Tue Oct 23 09:55:28 EDT 2012


On 10/23/2012 07:39 AM, Galder Zamarreño wrote:
>
> On Oct 22, 2012, at 3:40 PM, David M. Lloyd <david.lloyd at redhat.com> wrote:
>
>> On 10/22/2012 01:41 AM, Galder Zamarreño wrote:
>>>
>>> On Oct 19, 2012, at 7:20 PM, David M. Lloyd <david.lloyd at redhat.com> wrote:
>>>
>>>> Also be aware that JBMAR has specific optimizations for the JDK empty
>>>> collections - they are represented by a single byte in the stream.
>>>
>>> Well, it's actually 3 bytes that you use to represent empty collections (at least in 1.3.15ga):
>>>
>>> write(ID_NEW_OBJECT);
>>> write(ID_CLASS_CLASS);
>>> write(classByte);
>>>
>>> Whereas with our externalizers, these get resolved via object writer (which gets called before your code to detect empty collections) and it only writes 1 byte:
>>>
>>> write(externalizerId);
>>
>> No, that's inaccurate; they are singletons and do not use ID_NEW_OBJECT.
>
> Really?
>
> https://github.com/dmlloyd/jboss-marshalling/blob/1.3.15.GA/river/src/main/java/org/jboss/marshalling/river/RiverMarshaller.java#L169

That code is the code path that is executed if you write, for example. 
Collections.emptySet().getClass().  The code you're interested in is:

https://github.com/dmlloyd/jboss-marshalling/blob/1.3.15.GA/river/src/main/java/org/jboss/marshalling/river/RiverMarshaller.java#L713

>
>>   They're done as instances so it is one of:
>>
>>      public static final int ID_EMPTY_LIST_OBJECT        = 0x5d;
>>      public static final int ID_EMPTY_SET_OBJECT         = 0x62;
>>      public static final int ID_EMPTY_MAP_OBJECT         = 0x69;
>>
>> Your externalizers on the other hand take multiple bytes even in the
>> simplest case.  If it is that important, you could use an ObjectResolver
>> to swap in the JDK instance instead of using yet another externalizer
>> (which has several bytes of overhead of its own).
>
> Well, to be completely precise, our version will write two bytes:
>
> 1st byte: https://github.com/dmlloyd/jboss-marshalling/blob/1.3.15.GA/river/src/main/java/org/jboss/marshalling/river/RiverMarshaller.java#L140
> 2nd byte: https://github.com/galderz/infinispan/blob/t_memory/core/src/main/java/org/infinispan/marshall/jboss/ExternalizerTable.java#L397
>
> I still see 3 bytes written in your case:
>
> 1st byte:  https://github.com/dmlloyd/jboss-marshalling/blob/1.3.15.GA/river/src/main/java/org/jboss/marshalling/river/RiverMarshaller.java#L169
> 2nd byte: https://github.com/dmlloyd/jboss-marshalling/blob/1.3.15.GA/river/src/main/java/org/jboss/marshalling/river/RiverMarshaller.java#L1133
> 3rd byte: class byte, as indicated in https://github.com/dmlloyd/jboss-marshalling/blob/1.3.15.GA/river/src/main/java/org/jboss/marshalling/river/RiverMarshaller.java#L167
>
> Not sure if you remember but we have ObjectTable.Writer in what we call ExternalizerTable, which given a type, it resolves into an Infinispan Externalizer.
>
> Now, given Collections.Empty<Set>, it will resolve to an adapter that writes the ID of the externalizer (in this case InfinsipanCollections.EmptySet.Externalizer), and then will delegate to its writeObject, which does nothing.
>
>>
>> --
>> - DML
>> _______________________________________________
>> infinispan-dev mailing list
>> infinispan-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/infinispan-dev
>
>
> --
> Galder Zamarreño
> galder at redhat.com
> twitter.com/galderz
>
> Project Lead, Escalante
> http://escalante.io
>
> Engineer, Infinispan
> http://infinispan.org
>
>
> _______________________________________________
> infinispan-dev mailing list
> infinispan-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/infinispan-dev
>


-- 
- DML


More information about the infinispan-dev mailing list