You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2010/09/15 13:57:27 UTC
svn commit: r997297 - in /camel/trunk/camel-core/src:
main/java/org/apache/camel/impl/converter/
test/java/org/apache/camel/converter/
Author: davsclaus
Date: Wed Sep 15 11:57:26 2010
New Revision: 997297
URL: http://svn.apache.org/viewvc?rev=997297&view=rev
Log:
CAMEL-3123: Improved performance of PropertyEditorTypeConverter.
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/converter/PropertyEditorTypeConverterIssueTest.java
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java?rev=997297&r1=997296&r2=997297&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java Wed Sep 15 11:57:26 2010
@@ -38,6 +38,7 @@ import org.apache.camel.spi.PackageScanC
import org.apache.camel.spi.TypeConverterAware;
import org.apache.camel.spi.TypeConverterRegistry;
import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
import org.apache.camel.util.StopWatch;
import org.apache.camel.util.TimeUtils;
import org.apache.commons.logging.Log;
@@ -57,6 +58,7 @@ public class DefaultTypeConverter extend
private final List<FallbackTypeConverter> fallbackConverters = new ArrayList<FallbackTypeConverter>();
private Injector injector;
private final FactoryFinder factoryFinder;
+ private final PropertyEditorTypeConverter propertyEditorTypeConverter = new PropertyEditorTypeConverter();
public DefaultTypeConverter(PackageScanClassResolver resolver, Injector injector, FactoryFinder factoryFinder) {
this.injector = injector;
@@ -68,7 +70,7 @@ public class DefaultTypeConverter extend
// ToStringTypeConverter should NOT allow to be promoted
addFallbackTypeConverter(new ToStringTypeConverter(), false);
// do not assume property editor as it has a String converter
- addFallbackTypeConverter(new PropertyEditorTypeConverter(), false);
+ addFallbackTypeConverter(propertyEditorTypeConverter, false);
// enum is okay to be promoted
addFallbackTypeConverter(new EnumTypeConverter(), true);
// arrays is okay to be promoted
@@ -415,6 +417,7 @@ public class DefaultTypeConverter extend
@Override
protected void doStart() throws Exception {
+ ServiceHelper.startService(propertyEditorTypeConverter);
loadTypeConverters();
}
@@ -422,6 +425,8 @@ public class DefaultTypeConverter extend
protected void doStop() throws Exception {
typeMappings.clear();
misses.clear();
+ // let property editor type converter stop and cleanup resources
+ ServiceHelper.stopService(propertyEditorTypeConverter);
}
/**
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java?rev=997297&r1=997296&r2=997297&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java Wed Sep 15 11:57:26 2010
@@ -18,9 +18,13 @@ package org.apache.camel.impl.converter;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
+import java.util.HashMap;
+import java.util.Map;
import org.apache.camel.Exchange;
+import org.apache.camel.Service;
import org.apache.camel.TypeConverter;
+import org.apache.camel.util.LRUCache;
import org.apache.camel.util.ObjectHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -31,9 +35,14 @@ import org.apache.commons.logging.LogFac
*
* @version $Revision$
*/
-public class PropertyEditorTypeConverter implements TypeConverter {
+public class PropertyEditorTypeConverter implements TypeConverter, Service {
private static final Log LOG = LogFactory.getLog(PropertyEditorTypeConverter.class);
+ // use a bound cache to avoid using too much memory in case a lot of different classes
+ // is being converted to string
+ private final Map<Class, Class> misses = new LRUCache<Class, Class>(1000);
+ // we don't anticipate so many property editors so we have unbounded map
+ private final Map<Class, PropertyEditor> cache = new HashMap<Class, PropertyEditor>();
public <T> T convertTo(Class<T> type, Object value) {
// We can't convert null values since we can't figure out a property
@@ -48,21 +57,13 @@ public class PropertyEditorTypeConverter
return ObjectHelper.cast(type, value);
}
- // TODO: findEditor is synchronized so we want to avoid calling it
- // we should have a local hit cache
- PropertyEditor editor = PropertyEditorManager.findEditor(type);
- if (LOG.isTraceEnabled()) {
- LOG.trace("Finding property editor for type: " + type + " -> " + editor);
- }
+ PropertyEditor editor = lookupEditor(type, value);
if (editor != null) {
editor.setAsText(value.toString());
return ObjectHelper.cast(type, editor.getValue());
}
} else if (type == String.class) {
- PropertyEditor editor = PropertyEditorManager.findEditor(value.getClass());
- if (LOG.isTraceEnabled()) {
- LOG.trace("Finding property editor for type: " + type + " -> " + editor);
- }
+ PropertyEditor editor = lookupEditor(type, value);
if (editor != null) {
editor.setValue(value);
return ObjectHelper.cast(type, editor.getAsText());
@@ -72,6 +73,42 @@ public class PropertyEditorTypeConverter
return null;
}
+ private <T> PropertyEditor lookupEditor(Class<T> type, Object value) {
+ Class key = value.getClass();
+
+ // check misses first
+ if (misses.containsKey(key)) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("No previously found property editor for type: " + type);
+ }
+ return null;
+ }
+
+ synchronized (cache) {
+ // not a miss then try to lookup the editor
+ PropertyEditor editor = cache.get(key);
+ if (editor == null) {
+ // findEditor is synchronized and very slow so we want to only lookup once for a given key
+ // and then we use our own local cache for faster lookup
+ editor = PropertyEditorManager.findEditor(key);
+
+ // either we found an editor, or if not then register it as a miss
+ if (editor != null) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Found property editor for type: " + type + " -> " + editor);
+ }
+ cache.put(key, editor);
+ } else {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Cannot find property editor for type: " + type);
+ }
+ misses.put(key, key);
+ }
+ }
+ return editor;
+ }
+ }
+
public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
return convertTo(type, value);
}
@@ -84,4 +121,12 @@ public class PropertyEditorTypeConverter
return convertTo(type, value);
}
+ public void start() throws Exception {
+ }
+
+ public void stop() throws Exception {
+ cache.clear();
+ misses.clear();
+ }
+
}
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/PropertyEditorTypeConverterIssueTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/converter/PropertyEditorTypeConverterIssueTest.java?rev=997297&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/converter/PropertyEditorTypeConverterIssueTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/converter/PropertyEditorTypeConverterIssueTest.java Wed Sep 15 11:57:26 2010
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.util.StopWatch;
+
+/**
+ * @version $Revision$
+ */
+public class PropertyEditorTypeConverterIssueTest extends ContextTestSupport {
+
+ public void testPropertyEditorTypeConverter() throws Exception {
+ // test that converters a custom object (MyBean) to a String which causes
+ // PropertyEditorTypeConverter to be used. And this test times how fast
+ // this is. As we want to optimize PropertyEditorTypeConverter to be faster
+ MyBean bean = new MyBean();
+ bean.setBar("Hello");
+
+ StopWatch watch = new StopWatch();
+ for (int i = 0; i < 500; i++) {
+ assertNotNull(context.getTypeConverter().convertTo(String.class, bean));
+ }
+ log.info("Time taken: " + watch.stop());
+ }
+
+}