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