Author: davsclaus
Date: Wed Jan  5 15:32:33 2011
New Revision: 1055489

URL: http://svn.apache.org/viewvc?rev=1055489&view=rev
Log:
CAMEL-3500: Headers on message is now using string interning for Camel keys, to 
reduce memory consumption.

Modified:
    
camel/trunk/camel-core/src/main/java/org/apache/camel/util/CaseInsensitiveMap.java
    
camel/trunk/camel-core/src/test/java/org/apache/camel/util/CaseInsensitiveMapTest.java

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/util/CaseInsensitiveMap.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/CaseInsensitiveMap.java?rev=1055489&r1=1055488&r2=1055489&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/util/CaseInsensitiveMap.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/util/CaseInsensitiveMap.java
 Wed Jan  5 15:32:33 2011
@@ -65,7 +65,7 @@ public class CaseInsensitiveMap extends 
 
     @Override
     public Object get(Object key) {
-        String s = key.toString().toLowerCase();
+        String s = assembleKey(key);
         Object answer = super.get(s);
         if (answer == null) {
             // fallback to lookup by original key
@@ -79,7 +79,7 @@ public class CaseInsensitiveMap extends 
     public synchronized Object put(String key, Object value) {
         // invalidate views as we mutate
         entrySetView = null;
-        String s = key.toLowerCase();
+        String s = assembleKey(key);
         originalKeys.put(s, key);
         return super.put(s, value);
     }
@@ -101,7 +101,7 @@ public class CaseInsensitiveMap extends 
 
         // invalidate views as we mutate
         entrySetView = null;
-        String s = key.toString().toLowerCase();
+        String s = assembleKey(key);
         originalKeys.remove(s);
         return super.remove(s);
     }
@@ -120,10 +120,20 @@ public class CaseInsensitiveMap extends 
             return false;
         }
 
-        String s = key.toString().toLowerCase();
+        String s = assembleKey(key);
         return super.containsKey(s);
     }
 
+    private static String assembleKey(Object key) {
+        String s = key.toString().toLowerCase();
+        if (s.startsWith("camel")) {
+            // use intern String for headers which is Camel* headers
+            // this reduces memory allocations needed for those common headers
+            s = s.intern();
+        }
+        return s;
+    }
+
     @Override
     public synchronized Set<Map.Entry<String, Object>> entrySet() {
         if (entrySetView == null) {

Modified: 
camel/trunk/camel-core/src/test/java/org/apache/camel/util/CaseInsensitiveMapTest.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/CaseInsensitiveMapTest.java?rev=1055489&r1=1055488&r2=1055489&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/util/CaseInsensitiveMapTest.java
 (original)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/util/CaseInsensitiveMapTest.java
 Wed Jan  5 15:32:33 2011
@@ -20,9 +20,11 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
@@ -476,4 +478,38 @@ public class CaseInsensitiveMapTest exte
         assertEquals("cheese", map.get("cAKe"));
     }
 
+    public void testCopyMapWithCamelHeadersTest() throws Exception {
+        Map<String, Object> map = new CaseInsensitiveMap();
+        map.put("CamelA", "A");
+        map.put("CamelB", "B");
+        map.put("CamelC", "C");
+
+        // retain maps so we can profile that the map doesn't duplicate
+        // camel keys as they are intern
+        List<Map> maps = new ArrayList<Map>();
+
+        for (int i = 0; i < 10000; i++) {
+            Map<String, Object> copy = new CaseInsensitiveMap(map);
+            assertEquals(3, copy.size());
+            assertEquals("A", copy.get("CamelA"));
+            assertEquals("B", copy.get("CamelB"));
+            assertEquals("C", copy.get("CamelC"));
+
+            maps.add(copy);
+        }
+
+        assertEquals(10000, maps.size());
+
+        assertEquals(3, map.size());
+        assertEquals("A", map.get("CamelA"));
+        assertEquals("B", map.get("CamelB"));
+        assertEquals("C", map.get("CamelC"));
+
+        // use a memory profiler to see memory allocation
+        // often you may want to give it time to run so you
+        // have chance to capture memory snapshot in profiler
+        // Thread.sleep(9999999);
+    }
+
+
 }
\ No newline at end of file


Reply via email to