From 51c3e1286d7923eb2ecbc97aade9d2cf5faa22b7 Mon Sep 17 00:00:00 2001 From: Michael Glavassevich Date: Tue, 9 Aug 2011 14:51:31 +0000 Subject: [PATCH] JIRA Issue #1521: http://issues.apache.org/jira/browse/XERCESJ-1521. Compact the SoftReferenceSymbolTable if after cleaning out cleared SoftReferences the number of symbols drops below 25% of the table's load factor threshold. git-svn-id: https://svn.apache.org/repos/asf/xerces/java/trunk@1155386 13f79535-47bb-0310-9956-ffa450edef68 --- .../xerces/util/SoftReferenceSymbolTable.java | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/org/apache/xerces/util/SoftReferenceSymbolTable.java b/src/org/apache/xerces/util/SoftReferenceSymbolTable.java index aebe2f449..542bfb7da 100644 --- a/src/org/apache/xerces/util/SoftReferenceSymbolTable.java +++ b/src/org/apache/xerces/util/SoftReferenceSymbolTable.java @@ -200,12 +200,26 @@ public String addSymbol(char[] buffer, int offset, int length) { * and load factor. */ protected void rehash() { - - int oldCapacity = fBuckets.length; - SREntry[] oldTable = fBuckets; - - int newCapacity = oldCapacity * 2 + 1; - SREntry[] newTable = new SREntry[newCapacity]; + rehashCommon(fBuckets.length * 2 + 1); + } + + /** + * Reduces the capacity of and internally reorganizes this + * SymbolTable, in order to accommodate and access its entries in + * a more memory efficient way. This method is called automatically when + * the number of keys in the SymbolTable drops below 25% of this + * hashtable's load factor (as a result of SoftReferences which have + * been cleared). + */ + protected void compact() { + rehashCommon(((int) (fCount / fLoadFactor)) * 2 + 1); + } + + private void rehashCommon(final int newCapacity) { + + final int oldCapacity = fBuckets.length; + final SREntry[] oldTable = fBuckets; + final SREntry[] newTable = new SREntry[newCapacity]; fThreshold = (int)(newCapacity * fLoadFactor); fBuckets = newTable; @@ -312,9 +312,17 @@ public class SoftReferenceSymbolTable ex */ private void clean() { SREntry entry = (SREntry)fReferenceQueue.poll(); - while (entry != null) { - removeEntry(entry); - entry = (SREntry)fReferenceQueue.poll(); + if (entry != null) { + do { + removeEntry(entry); + entry = (SREntry)fReferenceQueue.poll(); + } + while (entry != null); + // Reduce the number of buckets if the number of items + // in the table has dropped below 25% of the threshold. + if (fCount < (fThreshold >> 2)) { + compact(); + } } }