diff options
author | Mark Spruiell <mes@zeroc.com> | 2016-02-26 10:43:37 -0800 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2016-02-26 10:43:37 -0800 |
commit | b42452eb0c569e1c72b2dcc83b53bfd26195fdfc (patch) | |
tree | 4d08a20c2e7326558ccb842b252d8c1e3b1334e7 | |
parent | Slice/generation test needs to clean up generated files in Java (diff) | |
download | ice-b42452eb0c569e1c72b2dcc83b53bfd26195fdfc.tar.bz2 ice-b42452eb0c569e1c72b2dcc83b53bfd26195fdfc.tar.xz ice-b42452eb0c569e1c72b2dcc83b53bfd26195fdfc.zip |
ICE-6844 - Slow Java performance when unmarshaling Ice objects that use compact type IDs
-rw-r--r-- | CHANGELOG-3.6.md | 11 | ||||
-rw-r--r-- | java/src/Ice/src/main/java/IceInternal/BasicStream.java | 154 |
2 files changed, 120 insertions, 45 deletions
diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md index 44de903603a..bb48ca87424 100644 --- a/CHANGELOG-3.6.md +++ b/CHANGELOG-3.6.md @@ -49,15 +49,20 @@ These are the changes since Ice 3.6.1. - Fixed El Capitan build issues caused by a new security feature that no longer exports DYLD_LIBRARY_PATH to child processes. -- Fixed potential deadlock that could occur when using collocation - optimization and serialized server thread pools. +- Fixed potential deadlock that could occur when using collocation optimization and + serialized server thread pools. ## C# Changes - Minor fixes to release the memory used by the transports to send and receive - data sooner. This garbage collector can therefore collect this memory sooner + data sooner. The garbage collector can therefore collect this memory sooner as well. +## Java Changes + +- Fixed a bug where unmarshaling Ice objects was really slow when using + compact type IDs. + # Changes in Ice 3.6.1 These are the changes since Ice 3.6.0. diff --git a/java/src/Ice/src/main/java/IceInternal/BasicStream.java b/java/src/Ice/src/main/java/IceInternal/BasicStream.java index 9394638f3cb..f2048e63732 100644 --- a/java/src/Ice/src/main/java/IceInternal/BasicStream.java +++ b/java/src/Ice/src/main/java/IceInternal/BasicStream.java @@ -2730,27 +2730,6 @@ public class BasicStream _buf.expand(n); } - private Ice.Object - createObject(String id) - { - Ice.Object obj = null; - - try - { - Class<?> c = findClass(id); - if(c != null) - { - obj = (Ice.Object)c.newInstance(); - } - } - catch(java.lang.Exception ex) - { - throw new Ice.NoObjectFactoryException("no object factory", id, ex); - } - - return obj; - } - private String getTypeId(int compactId) { @@ -3007,6 +2986,39 @@ public class BasicStream } } + protected Class<?> + resolveClass(String typeId) + { + Class<?> cls = null; + if(_typeIdCache == null) + { + _typeIdCache = new java.util.HashMap<String, Class<?> >(); // Lazy initialization. + } + else + { + cls = _typeIdCache.get(typeId); + } + + if(cls == EncapsDecoder.class) // Marker for non-existent class. + { + cls = null; + } + else if(cls == null) + { + try + { + cls = _stream.findClass(typeId); + _typeIdCache.put(typeId, cls != null ? cls : EncapsDecoder.class); + } + catch(java.lang.Exception ex) + { + throw new Ice.NoObjectFactoryException("no object factory", typeId, ex); + } + } + + return cls; + } + protected Ice.Object newInstance(String typeId) { @@ -3038,7 +3050,19 @@ public class BasicStream // if(v == null) { - v = _stream.createObject(typeId); + Class<?> cls = resolveClass(typeId); + + if(cls != null) + { + try + { + v = (Ice.Object)cls.newInstance(); + } + catch(java.lang.Exception ex) + { + throw new Ice.NoObjectFactoryException("no object factory", typeId, ex); + } + } } return v; @@ -3184,6 +3208,8 @@ public class BasicStream private java.util.TreeMap<Integer, String> _typeIdMap; private int _typeIdIndex; private java.util.List<Ice.Object> _objectList; + + private java.util.HashMap<String, Class<?> > _typeIdCache; } private static final class EncapsDecoder10 extends EncapsDecoder @@ -3905,45 +3931,88 @@ public class BasicStream final Ice.CompactIdResolver compactIdResolver = _stream.instance().initializationData().compactIdResolver; while(true) { + boolean updateCache = false; + if(_current.compactId >= 0) { + updateCache = true; + // - // Translate a compact (numeric) type ID into a string type ID. + // Translate a compact (numeric) type ID into a class. // - _current.typeId = ""; - if(compactIdResolver != null) + if(_compactIdCache == null) { - try + _compactIdCache = new java.util.TreeMap<Integer, Class<?> >(); // Lazy initialization. + } + else + { + // + // Check the cache to see if we've already translated the compact type ID into a class. + // + Class<?> cls = _compactIdCache.get(_current.compactId); + if(cls != null) { - _current.typeId = compactIdResolver.resolve(_current.compactId); + try + { + v = (Ice.Object)cls.newInstance(); + updateCache = false; + } + catch(java.lang.Exception ex) + { + throw new Ice.NoObjectFactoryException("no object factory", "compact ID " + + _current.compactId, ex); + } } - catch(Ice.LocalException ex) + } + + // + // If we haven't already cached a class for the compact ID, then try to translate the + // compact ID into a type ID. + // + if(v == null) + { + _current.typeId = ""; + if(compactIdResolver != null) { - throw ex; + try + { + _current.typeId = compactIdResolver.resolve(_current.compactId); + } + catch(Ice.LocalException ex) + { + throw ex; + } + catch(Throwable ex) + { + throw new Ice.MarshalException("exception in CompactIdResolver for ID " + + _current.compactId, ex); + } } - catch(Throwable ex) + + if(_current.typeId.isEmpty()) { - throw new Ice.MarshalException("exception in CompactIdResolver for ID " + - _current.compactId, ex); + _current.typeId = _stream.getTypeId(_current.compactId); } } - if(_current.typeId.length() == 0) - { - _current.typeId = _stream.getTypeId(_current.compactId); - } } - if(_current.typeId.length() > 0) + if(v == null && !_current.typeId.isEmpty()) { v = newInstance(_current.typeId); + } - // - // We found a factory, we get out of this loop. - // - if(v != null) + if(v != null) + { + if(updateCache) { - break; + assert(_current.compactId >= 0); + _compactIdCache.put(_current.compactId, v.getClass()); } + + // + // We have an instance, get out of this loop. + // + break; } // @@ -4091,6 +4160,7 @@ public class BasicStream private InstanceData _current; private int _objectIdIndex; // The ID of the next object to un-marshal. + private java.util.TreeMap<Integer, Class<?> > _compactIdCache; // Cache of compact type IDs. } abstract private static class EncapsEncoder |