[Json-rpc-java] registerSerializer
Michael Clark
michael at metaparadigm.com
Fri Apr 27 10:34:03 SGT 2007
Raziel Alvarez wrote:
> I'm facing what seems to me as a big performance issue in the
> JSONSerializer
> code.
>
> My application uses a considerable amount of custom serializers. Some of
> them need to be updated with some contextual information in order to
> perform
> a proper serialization. Everytime a serialization is needed, and that
> contextual information changes, we create new serializer instances and
> re-register them (in the existing JSONSerializer instance) using the
> registerSerializer(Serializer s) method in JSONSerializer class.
perhaps an unregsiterSerializer(Serializer s) would help? (we have this
method for most of the items that can be registered against the bridge).
> The problem is that this method verifies if a serializer already exists
> checking for an instance (instead of a class, for example):
>
> if(!serializerSet.contains(s))
>
> Thus, every time a new serializer instance is registered, the
> serializerSet
> and serializerList grow, even if there was already a serializer
> instance of
> that class. In that case, the correct behaviour (at least that's what I
> think) should be replace the old instance with the new one.
We didn't yet have a case where we wanted to replace a serializer.
One option is to use the existing setSerializer() method on the Bridge
and give it a new JSONSerializer instance with your stateful serializers
- this problem should then go away.
Another way around would be to hold a reference to your custom
serializer and instead of re-registering it, update it's state.
> With this logic it's basically impossible to re-register a new
> serializer:
> if the passed instance is the same that the one already registered
> then it
> won't pass the contains check, and won't be registered; if (like in my
> case)
> the passed serializer is a completely new instance then it will be
> registered but the old one will remain in the serializerSet and
> serializerList. This currently works because the new instance is added to
> the beginning of the list, and that's the place where we start to look
> for
> serializers in the getSerializer method. The problem then is that these
> objects (the list and the set) will be always growing, and performance
> will
> degrade every time.
>
unregsiterSerializer(Serializer s) sounds like a good idea then (as
there could be cases where you register multiple instances of a
Serializer class configured in a different ways). The current interface
takes an instance not a class so a symmetrical interface (in line with
the current unregister*() methods) would be to remove the instance.
> My proposal is to replace the serializerSet with a Map
> (serializerMap), that
> indexes the serializers by class, keeping the serializer instance as the
> value of that entry. The instance can then be used to avoid
> re-registering
> the same instance twice, but will still enable registering new
> instances and
> removing the old one, keeping the serializerList containing only those
> serializers that are useful.
>
> private HashMap serializerMap = new HashMap();
>
> public void registerSerializer(Serializer s)
> throws Exception
> {
> Class classes[] = s.getSerializableClasses();
> Serializer exists;
> synchronized (serializerMap) {
> for(int i=0; i < classes.length; i++) {
> exists = (Serializer)serializableMap.get(classes[i]);
> if(exists != null && exists.getClass() != s.getClass())
> throw new Exception
> ("different serializer already registered for " +
> classes[i].getName());
> }
>
> if(serializerMap.get(s.getClass()) != s) {
> if(isDebug())
> log.info("registered serializer " +
> s.getClass().getName());
> for(int i=0; i < classes.length; i++) {
> serializableMap.put(classes[i], s);
> }
> s.setOwner(this);
> Object old = serializerMap.put(s.getClass(), s);
> serializerList.remove(old);
> serializerList.add(0, s);
> }
> }
> }
>
> The only caveat I see is that the current code lets you register two
> serializer instances of the same class, each one being able to
> serialize a
> different set of classes. With the proposed change that would not
> work; and
> probably, to account for this case, it'll be necessary to update the
> serializableMap, removing the mappings of the old serializer prior to
> adding
> those for the new one.
Yes. I'm not sure if anybody is using that but my suggestion would be an
unregisterSerializer as per the other interfaces.
> Please let me know if this makes sense, or the current behavior is
> as-design. In such case I guess my solution would be to create a new
> JSONSerializer instance every time I need to re-register a serializer
> because my contextual information changed?
Yup. or hold references to your custom serializer and update its state
directly without re-registering it.
Michael.
More information about the Json-rpc-java
mailing list