You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by tr...@apache.org on 2007/11/05 10:32:21 UTC

svn commit: r591932 - in /mina/trunk/core/src/main/java/org/apache/mina: common/CachedBufferAllocator.java util/CircularQueue.java

Author: trustin
Date: Mon Nov  5 01:32:20 2007
New Revision: 591932

URL: http://svn.apache.org/viewvc?rev=591932&view=rev
Log:
* Added CircularQueue which is more GC friendly and outperforms LinkedList
* CachedBufferAllocator now uses CircularQueue

Added:
    mina/trunk/core/src/main/java/org/apache/mina/util/CircularQueue.java   (with props)
Modified:
    mina/trunk/core/src/main/java/org/apache/mina/common/CachedBufferAllocator.java

Modified: mina/trunk/core/src/main/java/org/apache/mina/common/CachedBufferAllocator.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/common/CachedBufferAllocator.java?rev=591932&r1=591931&r2=591932&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/common/CachedBufferAllocator.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/common/CachedBufferAllocator.java Mon Nov  5 01:32:20 2007
@@ -22,10 +22,11 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.Map;
 import java.util.Queue;
 
+import org.apache.mina.util.CircularQueue;
+
 /**
  * An {@link IoBufferAllocator} that caches the buffers which are likely to
  * be reused during auto-expansion of the buffers.
@@ -68,9 +69,9 @@
                 Map<Integer, Queue<ByteBuffer>> queues =
                     new HashMap<Integer, Queue<ByteBuffer>>();
                 for (int i = 0; i < 31; i ++) {
-                    queues.put(1 << i, new LinkedList<ByteBuffer>());
+                    queues.put(1 << i, new CircularQueue<ByteBuffer>(MAX_POOL_SIZE));
                 }
-                queues.put(Integer.MAX_VALUE, new LinkedList<ByteBuffer>());
+                queues.put(Integer.MAX_VALUE, new CircularQueue<ByteBuffer>(MAX_POOL_SIZE));
                 return queues;
             }
         };

Added: mina/trunk/core/src/main/java/org/apache/mina/util/CircularQueue.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/util/CircularQueue.java?rev=591932&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/util/CircularQueue.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/util/CircularQueue.java Mon Nov  5 01:32:20 2007
@@ -0,0 +1,282 @@
+/*
+ *  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.mina.util;
+
+import java.io.Serializable;
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+
+/**
+ * A unbounded circular queue based on array.
+ * 
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class CircularQueue<E> extends AbstractList<E> implements List<E>, Queue<E>, Serializable {
+
+    private static final long serialVersionUID = 3993421269224511264L;
+
+    private static final int DEFAULT_CAPACITY = 4;
+
+    private Object[] items;
+    private int mask;
+    private int first = 0;
+    private int last = 0;
+    private boolean full;
+
+    /**
+     * Construct a new, empty queue.
+     */
+    public CircularQueue() {
+        this(DEFAULT_CAPACITY);
+    }
+    
+    public CircularQueue(int initialCapacity) {
+        int actualCapacity = 1;
+        while (actualCapacity < initialCapacity) {
+            actualCapacity <<= 1;
+            if (actualCapacity < 0) {
+                actualCapacity = 1 << 30;
+                break;
+            }
+        }
+        items = new Object[actualCapacity];
+        mask = actualCapacity - 1;
+    }
+
+    /**
+     * Returns the capacity of this queue.
+     */
+    public int capacity() {
+        return items.length;
+    }
+
+    @Override
+    public void clear() {
+        Arrays.fill(items, null);
+        first = 0;
+        last = 0;
+        full = false;
+    }
+
+    @SuppressWarnings("unchecked")
+    public E poll() {
+        if (isEmpty()) {
+            return null;
+        }
+
+        Object ret = items[first];
+        items[first] = null;
+        decreaseSize();
+
+        return (E) ret;
+    }
+
+    public boolean offer(E item) {
+        if (item == null) {
+            throw new NullPointerException("item");
+        }
+        ensureCapacity();
+        items[last] = item;
+        increaseSize();
+        return true;
+    }
+
+    @SuppressWarnings("unchecked")
+    public E peek() {
+        if (isEmpty()) {
+            return null;
+        }
+
+        return (E) items[first];
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public E get(int idx) {
+        checkIndex(idx);
+        return (E) items[getRealIndex(idx)];
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return first == last & !full;
+    }
+
+    @Override
+    public int size() {
+        if (full) {
+            return capacity();
+        }
+        
+        if (last >= first) {
+            return last - first;
+        } else {
+            return last - first + capacity();
+        }
+    }
+    
+    @Override
+    public String toString() {
+        return "first=" + first + ", last=" + last + ", size=" + size()
+                + ", mask = " + mask;
+    }
+
+    private void checkIndex(int idx) {
+        if (idx < 0 || idx >= size()) {
+            throw new IndexOutOfBoundsException(String.valueOf(idx));
+        }
+    }
+
+    private int getRealIndex(int idx) {
+        return (first + idx) & mask;
+    }
+
+    private void increaseSize() {
+        last = (last + 1) & mask;
+        full = first == last;
+    }
+
+    private void decreaseSize() {
+        first = (first + 1) & mask;
+        full = false;
+    }
+
+    private void ensureCapacity() {
+        if (!full) {
+            return;
+        }
+
+        // expand queue
+        final int oldLen = items.length;
+        Object[] tmp = new Object[oldLen << 1];
+
+        if (first < last) {
+            System.arraycopy(items, first, tmp, 0, last - first);
+        } else {
+            System.arraycopy(items, first, tmp, 0, oldLen - first);
+            System.arraycopy(items, 0, tmp, oldLen - first, last);
+        }
+
+        first = 0;
+        last = oldLen;
+        items = tmp;
+        mask = tmp.length - 1;
+    }
+
+    @Override
+    public boolean add(E o) {
+        return offer(o);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public E set(int idx, E o) {
+        checkIndex(idx);
+
+        int realIdx = getRealIndex(idx);
+        Object old = items[realIdx];
+        items[realIdx] = o;
+        return (E) old;
+    }
+
+    @Override
+    public void add(int idx, E o) {
+        if (idx == size()) {
+            offer(o);
+            return;
+        }
+
+        checkIndex(idx);
+        ensureCapacity();
+
+        int realIdx = getRealIndex(idx);
+
+        // Make a room for a new element.
+        if (first < last) {
+            System
+                    .arraycopy(items, realIdx, items, realIdx + 1, last
+                            - realIdx);
+        } else {
+            if (realIdx >= first) {
+                System.arraycopy(items, 0, items, 1, last);
+                items[0] = items[items.length - 1];
+                System.arraycopy(items, realIdx, items, realIdx + 1,
+                        items.length - realIdx - 1);
+            } else {
+                System.arraycopy(items, realIdx, items, realIdx + 1, last
+                        - realIdx);
+            }
+        }
+
+        items[realIdx] = o;
+        increaseSize();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public E remove(int idx) {
+        if (idx == 0) {
+            return poll();
+        }
+
+        checkIndex(idx);
+
+        int realIdx = getRealIndex(idx);
+        Object removed = items[realIdx];
+
+        // Remove a room for the removed element.
+        if (first < last) {
+            System.arraycopy(items, first, items, first + 1, realIdx - first);
+        } else {
+            if (realIdx >= first) {
+                System.arraycopy(items, first, items, first + 1, realIdx
+                        - first);
+            } else {
+                System.arraycopy(items, 0, items, 1, realIdx);
+                items[0] = items[items.length - 1];
+                System.arraycopy(items, first, items, first + 1, items.length
+                        - first - 1);
+            }
+        }
+
+        items[first] = null;
+        decreaseSize();
+
+        return (E) removed;
+    }
+
+    public E remove() {
+        if (isEmpty()) {
+            throw new NoSuchElementException();
+        }
+        return poll();
+    }
+
+    public E element() {
+        if (isEmpty()) {
+            throw new NoSuchElementException();
+        }
+        return peek();
+    }
+}
\ No newline at end of file

Propchange: mina/trunk/core/src/main/java/org/apache/mina/util/CircularQueue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: mina/trunk/core/src/main/java/org/apache/mina/util/CircularQueue.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date