From 3f646474c28e86375b3bfc55a31072197579fb5c Mon Sep 17 00:00:00 2001 From: Francesco Nigro Date: Thu, 18 Jan 2018 15:45:20 +0100 Subject: [PATCH] ARTEMIS-1622 Reduce memory footprint of QueueImpl LinkedListImpl is turned into an optionally intrusive linked list by allowing message references to extend Node. --- .../utils/collections/LinkedListImpl.java | 39 ++++++++++++++----- .../paging/cursor/PagedReferenceImpl.java | 4 +- .../server/impl/MessageReferenceImpl.java | 3 +- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListImpl.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListImpl.java index 81b5d6091a..6071324559 100644 --- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListImpl.java +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/LinkedListImpl.java @@ -18,6 +18,7 @@ package org.apache.activemq.artemis.utils.collections; import java.lang.reflect.Array; import java.util.NoSuchElementException; +import java.util.Objects; /** * A linked list implementation which allows multiple iterators to exist at the same time on the queue, and which see any @@ -48,7 +49,7 @@ public class LinkedListImpl implements LinkedList { @Override public void addHead(E e) { - Node node = new Node<>(e); + Node node = Node.with(e); node.next = head.next; @@ -71,7 +72,7 @@ public class LinkedListImpl implements LinkedList { if (size == 0) { addHead(e); } else { - Node node = new Node<>(e); + Node node = Node.with(e); node.prev = tail; @@ -217,23 +218,43 @@ public class LinkedListImpl implements LinkedList { throw new IllegalStateException("Cannot find iter to remove"); } - private static final class Node { + public static class Node { - Node next; + private Node next; - Node prev; + private Node prev; - final E val; + private final T val; - int iterCount; + private int iterCount; - Node(E e) { + @SuppressWarnings("unchecked") + protected Node() { + val = (T)this; + } + + //only the head is allowed to hold a null + private Node(T e) { val = e; } @Override public String toString() { - return "Node, value = " + val; + return val == this ? "Intrusive Node" : "Node, value = " + val; + } + + private static Node with(final T o) { + Objects.requireNonNull(o, "Only HEAD nodes are allowed to hold null values"); + if (o instanceof Node) { + final Node node = (Node) o; + //only a node that not belong already to a list is allowed to be reused + if (node.prev == null && node.next == null) { + //reset the iterCount + node.iterCount = 0; + return node; + } + } + return new Node(o); } } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PagedReferenceImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PagedReferenceImpl.java index 25874f0d3a..7189007f7d 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PagedReferenceImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/PagedReferenceImpl.java @@ -20,16 +20,16 @@ import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicInteger; import org.apache.activemq.artemis.api.core.Message; - import org.apache.activemq.artemis.core.paging.PagedMessage; import org.apache.activemq.artemis.core.server.ActiveMQServerLogger; import org.apache.activemq.artemis.core.server.MessageReference; import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.core.server.impl.AckReason; import org.apache.activemq.artemis.core.transaction.Transaction; +import org.apache.activemq.artemis.utils.collections.LinkedListImpl; import org.jboss.logging.Logger; -public class PagedReferenceImpl implements PagedReference { +public class PagedReferenceImpl extends LinkedListImpl.Node implements PagedReference { private static final Logger logger = Logger.getLogger(PagedReferenceImpl.class); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/MessageReferenceImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/MessageReferenceImpl.java index bffb1adca2..1b434bc28e 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/MessageReferenceImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/MessageReferenceImpl.java @@ -22,11 +22,12 @@ import org.apache.activemq.artemis.api.core.Message; import org.apache.activemq.artemis.core.server.MessageReference; import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.core.transaction.Transaction; +import org.apache.activemq.artemis.utils.collections.LinkedListImpl; /** * Implementation of a MessageReference */ -public class MessageReferenceImpl implements MessageReference { +public class MessageReferenceImpl extends LinkedListImpl.Node implements MessageReference { private final AtomicInteger deliveryCount = new AtomicInteger();