diff options
9 files changed, 62 insertions, 24 deletions
diff --git a/container-core/src/main/java/com/yahoo/processing/rendering/AsynchronousSectionedRenderer.java b/container-core/src/main/java/com/yahoo/processing/rendering/AsynchronousSectionedRenderer.java index eeb02f768f4..6e1d2627c22 100644 --- a/container-core/src/main/java/com/yahoo/processing/rendering/AsynchronousSectionedRenderer.java +++ b/container-core/src/main/java/com/yahoo/processing/rendering/AsynchronousSectionedRenderer.java @@ -363,6 +363,7 @@ public abstract class AsynchronousSectionedRenderer<RESPONSE extends Response> e endRenderLevel(list); stream.flush(); dataListListenerStack.removeFirst(); + list.close(); if (parent != null) parent.childCompleted(); } diff --git a/container-search/src/main/java/com/yahoo/fs4/mplex/ConnectionPool.java b/container-search/src/main/java/com/yahoo/fs4/mplex/ConnectionPool.java index 342dc120113..e84adfbef2c 100644 --- a/container-search/src/main/java/com/yahoo/fs4/mplex/ConnectionPool.java +++ b/container-search/src/main/java/com/yahoo/fs4/mplex/ConnectionPool.java @@ -13,10 +13,11 @@ import com.yahoo.log.LogLevel; /** * Pool of FS4 connections. * - * @author tonytv + * @author Tony Vaagenes */ public class ConnectionPool { - final static int CLEANINGPERIOD = 1000; // Execute every second + + private final static int CLEANINGPERIOD = 1000; // Execute every second private final Queue<FS4Connection> connections = new ConcurrentLinkedQueue<>(); private final AtomicInteger activeConnections = new AtomicInteger(0); private final AtomicInteger passiveConnections = new AtomicInteger(0); diff --git a/container-search/src/main/java/com/yahoo/search/grouping/result/AbstractList.java b/container-search/src/main/java/com/yahoo/search/grouping/result/AbstractList.java index 030a3c08cd6..e4c351149f6 100644 --- a/container-search/src/main/java/com/yahoo/search/grouping/result/AbstractList.java +++ b/container-search/src/main/java/com/yahoo/search/grouping/result/AbstractList.java @@ -45,4 +45,10 @@ public abstract class AbstractList extends HitGroup { return continuations; } + @Override + public void close() { + super.close(); + continuations.clear(); + } + } diff --git a/container-search/src/main/java/com/yahoo/search/grouping/result/Group.java b/container-search/src/main/java/com/yahoo/search/grouping/result/Group.java index 9d6e7ebd233..c0c6c67e463 100644 --- a/container-search/src/main/java/com/yahoo/search/grouping/result/Group.java +++ b/container-search/src/main/java/com/yahoo/search/grouping/result/Group.java @@ -10,7 +10,7 @@ import com.yahoo.search.result.Relevance; * as fields, use {@link #getField(String)} to access), {@link GroupList} and {@link HitList}. Use the {@link * com.yahoo.search.grouping.GroupingRequest#getResultGroup(com.yahoo.search.Result)} to retrieve an instance of this. * - * @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen</a> + * @author Simon Thoresen */ public class Group extends HitGroup { diff --git a/container-search/src/main/java/com/yahoo/search/pagetemplates/result/SectionHitGroup.java b/container-search/src/main/java/com/yahoo/search/pagetemplates/result/SectionHitGroup.java index 5897628ace1..cd3578acd11 100644 --- a/container-search/src/main/java/com/yahoo/search/pagetemplates/result/SectionHitGroup.java +++ b/container-search/src/main/java/com/yahoo/search/pagetemplates/result/SectionHitGroup.java @@ -17,8 +17,8 @@ import java.util.List; public class SectionHitGroup extends HitGroup { private static final long serialVersionUID = -9048845836777953538L; - private List<Source> sources=new ArrayList<>(0); - private List<Renderer> renderers=new ArrayList<>(0); + private List<Source> sources = new ArrayList<>(0); + private List<Renderer> renderers = new ArrayList<>(0); private final String displayId; private boolean leaf=false; @@ -49,4 +49,10 @@ public class SectionHitGroup extends HitGroup { public void setLeaf(boolean leaf) { this.leaf=leaf; } + @Override + public void close() { + sources = null; + renderers = null; + } + } diff --git a/container-search/src/main/java/com/yahoo/search/result/Hit.java b/container-search/src/main/java/com/yahoo/search/result/Hit.java index 076e6659d2b..0d8f575b1f6 100644 --- a/container-search/src/main/java/com/yahoo/search/result/Hit.java +++ b/container-search/src/main/java/com/yahoo/search/result/Hit.java @@ -797,4 +797,10 @@ public class Hit extends ListenableFreezableClass implements Data, Comparable<Hi } } + protected void close() { + query = null; + fields = null; + unmodifiableFieldMap = null; + } + } diff --git a/container-search/src/main/java/com/yahoo/search/result/HitGroup.java b/container-search/src/main/java/com/yahoo/search/result/HitGroup.java index cb3a9abffc4..8ad8e6a732f 100644 --- a/container-search/src/main/java/com/yahoo/search/result/HitGroup.java +++ b/container-search/src/main/java/com/yahoo/search/result/HitGroup.java @@ -68,13 +68,13 @@ public class HitGroup extends Hit implements DataList<Hit>, Cloneable, Iterable< transient private HitOrderer hitOrderer = null; /** Accounting the number of subgroups to allow some early returns when the number is 0 */ - private int subgroupCount=0; + private int subgroupCount = 0; /** * The number of hits not cached at this level, not counting hits in subgroups or * any nested hitgroups themselves */ - private int notCachedCount=0; + private int notCachedCount = 0; /** * A direct reference to the errors of this result, or null if there are no errors. @@ -921,4 +921,13 @@ public class HitGroup extends Hit implements DataList<Hit>, Cloneable, Iterable< hits.addListener(runnable); } + @Override + public void close() { + super.close(); + hits = null; + unmodifiableHits = null; + hitOrderer = null; + incomingHits.drain(); // Just to gc as much as possible + } + } diff --git a/processing/src/main/java/com/yahoo/processing/response/DataList.java b/processing/src/main/java/com/yahoo/processing/response/DataList.java index 911cb6f70e6..1f762ab8d58 100644 --- a/processing/src/main/java/com/yahoo/processing/response/DataList.java +++ b/processing/src/main/java/com/yahoo/processing/response/DataList.java @@ -28,9 +28,9 @@ public interface DataList<DATATYPE extends Data> extends Data { * @param data the data to add to this * @return the input data instance, for chaining */ - public DATATYPE add(DATATYPE data); + DATATYPE add(DATATYPE data); - public DATATYPE get(int index); + DATATYPE get(int index); /** * Returns the content of this as a List. @@ -38,7 +38,7 @@ public interface DataList<DATATYPE extends Data> extends Data { * If the returned list is editable and this is frozen, the only allowed operation is to add new items * to the end of the list. */ - public List<DATATYPE> asList(); + List<DATATYPE> asList(); /** * Returns the buffer of incoming/future data to this list. @@ -49,7 +49,7 @@ public interface DataList<DATATYPE extends Data> extends Data { * such lists responds to <i>read</i> calls to IncomingData as expected and without * incurring any synchronization, and throws an exception on <i>write</i> calls. */ - public IncomingData<DATATYPE> incoming(); + IncomingData<DATATYPE> incoming(); /** * Returns a future in which all incoming data in this has become available. @@ -73,13 +73,22 @@ public interface DataList<DATATYPE extends Data> extends Data { * Making this call on a list which does not support future data always returns immediately and * causes no memory synchronization cost. */ - public ListenableFuture<DataList<DATATYPE>> complete(); + ListenableFuture<DataList<DATATYPE>> complete(); /** * Adds a listener which is invoked every time data is added to this list. * The listener is always invoked on the same thread which is adding the data, * and hence it can modify this list freely without synchronization. */ - public void addDataListener(Runnable runnable); + void addDataListener(Runnable runnable); + + /** + * Notify this list that is will never be accessed again, neither for read nor write. + * Implementations can override this as an optimization to release any data held in the list + * for garbage collection. + * + * This default implementation does nothing. + */ + default void close() {}; } diff --git a/processing/src/main/java/com/yahoo/processing/response/IncomingData.java b/processing/src/main/java/com/yahoo/processing/response/IncomingData.java index 7034b2c2a02..b8cdf8683bc 100644 --- a/processing/src/main/java/com/yahoo/processing/response/IncomingData.java +++ b/processing/src/main/java/com/yahoo/processing/response/IncomingData.java @@ -22,7 +22,7 @@ public interface IncomingData<DATATYPE extends Data> { * Note that accessing the owner from the thread producing incoming data * is generally *not* thread safe. */ - public DataList<DATATYPE> getOwner(); + DataList<DATATYPE> getOwner(); /** * Returns a future in which all the incoming data that will be produced in this is available. @@ -35,57 +35,57 @@ public interface IncomingData<DATATYPE extends Data> { * <p> * This return the list owning this for convenience. */ - public abstract ListenableFuture<DataList<DATATYPE>> completed(); + ListenableFuture<DataList<DATATYPE>> completed(); /** * Returns whether this is complete */ - public boolean isComplete(); + boolean isComplete(); /** * Add new data and mark this as completed * * @throws IllegalStateException if this is already complete or does not allow writes */ - public void addLast(DATATYPE data); + void addLast(DATATYPE data); /** * Add new data without completing this * * @throws IllegalStateException if this is already complete or does not allow writes */ - public void add(DATATYPE data); + void add(DATATYPE data); /** * Add new data and mark this as completed * * @throws IllegalStateException if this is already complete or does not allow writes */ - public void addLast(List<DATATYPE> data); + void addLast(List<DATATYPE> data); /** * Add new data without completing this. * * @throws IllegalStateException if this is already complete or does not allow writes */ - public void add(List<DATATYPE> data); + void add(List<DATATYPE> data); /** * Mark this as completed and notify any listeners. If this is already complete this method does nothing. */ - public void markComplete(); + void markComplete(); /** * Get and remove all the data currently available in this */ - public List<DATATYPE> drain(); + List<DATATYPE> drain(); /** * Add a listener which will be invoked every time new data is added to this. * This listener may be invoked at any time in any thread, any thread synchronization is left * to the listener itself */ - public void addNewDataListener(Runnable listener, Executor executor); + void addNewDataListener(Runnable listener, Executor executor); /** * Creates a null implementation of this which is empty and complete at creation: @@ -98,7 +98,7 @@ public interface IncomingData<DATATYPE extends Data> { * This allows consumers to check for completion the same way whether or not the data list in question * supports asynchronous addition of data, and without incurring unnecessary costs. */ - public static final class NullIncomingData<DATATYPE extends Data> implements IncomingData<DATATYPE> { + final class NullIncomingData<DATATYPE extends Data> implements IncomingData<DATATYPE> { private DataList<DATATYPE> owner; private final ImmediateFuture<DATATYPE> completionFuture; |