You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2008/07/22 13:29:39 UTC

svn commit: r678719 - in /jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name: HashCache.java NameFactoryImpl.java

Author: jukka
Date: Tue Jul 22 04:29:38 2008
New Revision: 678719

URL: http://svn.apache.org/viewvc?rev=678719&view=rev
Log:
JCR-1663: REFERENCE properties produce duplicate strings in memory

Use cached flyweight Name instances to avoid many copies of the same names taking up too much memory. Passes all tests and reportedly decreases memory usage.

Since my proposed patch: Added improvements suggested by Thomas (thanks!) and moved the cache functionality to a separate class to increase separation of concerns.

Added:
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java
Modified:
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NameFactoryImpl.java

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java?rev=678719&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java Tue Jul 22 04:29:38 2008
@@ -0,0 +1,62 @@
+/*
+ * 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.jackrabbit.spi.commons.name;
+
+/**
+ * Simple utility class that implements a fixed-size and thread-safe
+ * (non-blocking) cache of objects. The cache is simply an array
+ * of objects, indexed by their hash codes. If more than one objects
+ * hash to the same location, only the most recently accessed object is
+ * kept in the cache.
+ *
+ * @see https://issues.apache.org/jira/browse/JCR-1663
+ */
+class HashCache {
+
+    /**
+     * Size of the cache (must be a power of two). Note that this is the
+     * maximum number of objects kept in the cache, but due to hashing it
+     * can well be that only a part of the cache array is filled even if
+     * many more distinct objects are being accessed.
+     */
+    private static final int SIZE_POWER_OF_2 = 1024;
+
+    /**
+     * Array of cached objects, indexed by their hash codes
+     * (module size of the array).
+     */
+    private final Object[] array = new Object[SIZE_POWER_OF_2];
+
+    /**
+     * If a cached copy of the given object already exists, then returns
+     * that copy. Otherwise the given object is cached and returned.
+     *
+     * @param object object to return from the cache
+     * @return the given object or a previously cached copy
+     */
+    public Object get(Object object) {
+        int position = object.hashCode() & (SIZE_POWER_OF_2 - 1);
+        Object previous = array[position];
+        if (object.equals(previous)) {
+            return previous;
+        } else {
+            array[position] = object;
+            return object;
+        }
+    }
+
+}

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NameFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NameFactoryImpl.java?rev=678719&r1=678718&r2=678719&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NameFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NameFactoryImpl.java Tue Jul 22 04:29:38 2008
@@ -26,6 +26,13 @@
 
     private static final NameFactory INSTANCE = new NameFactoryImpl();
 
+    /**
+     * Cache of flyweight name instances.
+     *
+     * @see https://issues.apache.org/jira/browse/JCR-1663
+     */
+    private final HashCache cache = new HashCache();
+
     private NameFactoryImpl() {};
 
     public static NameFactory getInstance() {
@@ -44,7 +51,7 @@
         if (localName == null) {
             throw new IllegalArgumentException("invalid localName specified");
         }
-        return new NameImpl(namespaceURI, localName);
+        return (Name) cache.get(new NameImpl(namespaceURI, localName));
     }
 
     /**
@@ -63,9 +70,9 @@
         }
         if (i == nameString.length() - 1) {
             throw new IllegalArgumentException("Invalid Name literal");
-        } else {
-            return new NameImpl(nameString.substring(1, i), nameString.substring(i + 1));
         }
+        return (Name) cache.get(new NameImpl(
+                nameString.substring(1, i), nameString.substring(i + 1)));
     }
 
     //--------------------------------------------------------< inner class >---