|
@@ -23,6 +23,7 @@ import com.google.common.base.Preconditions;
|
|
import org.apache.lucene.util.ArrayUtil;
|
|
import org.apache.lucene.util.ArrayUtil;
|
|
import org.apache.lucene.util.BytesRef;
|
|
import org.apache.lucene.util.BytesRef;
|
|
import org.apache.lucene.util.RamUsageEstimator;
|
|
import org.apache.lucene.util.RamUsageEstimator;
|
|
|
|
+import org.elasticsearch.ElasticsearchIllegalStateException;
|
|
import org.elasticsearch.cache.recycler.PageCacheRecycler;
|
|
import org.elasticsearch.cache.recycler.PageCacheRecycler;
|
|
import org.elasticsearch.common.component.AbstractComponent;
|
|
import org.elasticsearch.common.component.AbstractComponent;
|
|
import org.elasticsearch.common.inject.Inject;
|
|
import org.elasticsearch.common.inject.Inject;
|
|
@@ -33,11 +34,14 @@ import org.elasticsearch.common.settings.ImmutableSettings;
|
|
import org.elasticsearch.common.settings.Settings;
|
|
import org.elasticsearch.common.settings.Settings;
|
|
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
|
|
+import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
|
|
/** Utility class to work with arrays. */
|
|
/** Utility class to work with arrays. */
|
|
public class BigArrays extends AbstractComponent {
|
|
public class BigArrays extends AbstractComponent {
|
|
|
|
|
|
- public static final BigArrays NON_RECYCLING_INSTANCE = new BigArrays(ImmutableSettings.EMPTY, null);
|
|
|
|
|
|
+ // TODO: switch to a circuit breaker that is shared not only on big arrays level, and applies to other request level data structures
|
|
|
|
+ public static final String MAX_SIZE_IN_BYTES_SETTING = "requests.memory.breaker.limit";
|
|
|
|
+ public static final BigArrays NON_RECYCLING_INSTANCE = new BigArrays(ImmutableSettings.EMPTY, null, Long.MAX_VALUE);
|
|
|
|
|
|
/** Page size in bytes: 16KB */
|
|
/** Page size in bytes: 16KB */
|
|
public static final int PAGE_SIZE_IN_BYTES = 1 << 14;
|
|
public static final int PAGE_SIZE_IN_BYTES = 1 << 14;
|
|
@@ -80,13 +84,15 @@ public class BigArrays extends AbstractComponent {
|
|
return index == (int) index;
|
|
return index == (int) index;
|
|
}
|
|
}
|
|
|
|
|
|
- private static abstract class AbstractArrayWrapper extends AbstractArray {
|
|
|
|
|
|
+ private static abstract class AbstractArrayWrapper extends AbstractArray implements BigArray {
|
|
|
|
+
|
|
|
|
+ protected static final long SHALLOW_SIZE = RamUsageEstimator.shallowSizeOfInstance(ByteArrayWrapper.class);
|
|
|
|
|
|
private final Releasable releasable;
|
|
private final Releasable releasable;
|
|
private final long size;
|
|
private final long size;
|
|
|
|
|
|
- AbstractArrayWrapper(long size, Releasable releasable, boolean clearOnResize) {
|
|
|
|
- super(clearOnResize);
|
|
|
|
|
|
+ AbstractArrayWrapper(BigArrays bigArrays, long size, Releasable releasable, boolean clearOnResize) {
|
|
|
|
+ super(bigArrays, clearOnResize);
|
|
this.releasable = releasable;
|
|
this.releasable = releasable;
|
|
this.size = size;
|
|
this.size = size;
|
|
}
|
|
}
|
|
@@ -96,7 +102,7 @@ public class BigArrays extends AbstractComponent {
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public final void close() {
|
|
|
|
|
|
+ protected final void doClose() {
|
|
Releasables.close(releasable);
|
|
Releasables.close(releasable);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -106,11 +112,16 @@ public class BigArrays extends AbstractComponent {
|
|
|
|
|
|
private final byte[] array;
|
|
private final byte[] array;
|
|
|
|
|
|
- ByteArrayWrapper(byte[] array, long size, Recycler.V<byte[]> releasable, boolean clearOnResize) {
|
|
|
|
- super(size, releasable, clearOnResize);
|
|
|
|
|
|
+ ByteArrayWrapper(BigArrays bigArrays, byte[] array, long size, Recycler.V<byte[]> releasable, boolean clearOnResize) {
|
|
|
|
+ super(bigArrays, size, releasable, clearOnResize);
|
|
this.array = array;
|
|
this.array = array;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public long sizeInBytes() {
|
|
|
|
+ return SHALLOW_SIZE + RamUsageEstimator.sizeOf(array);
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public byte get(long index) {
|
|
public byte get(long index) {
|
|
assert indexIsInt(index);
|
|
assert indexIsInt(index);
|
|
@@ -152,11 +163,16 @@ public class BigArrays extends AbstractComponent {
|
|
|
|
|
|
private final int[] array;
|
|
private final int[] array;
|
|
|
|
|
|
- IntArrayWrapper(int[] array, long size, Recycler.V<int[]> releasable, boolean clearOnResize) {
|
|
|
|
- super(size, releasable, clearOnResize);
|
|
|
|
|
|
+ IntArrayWrapper(BigArrays bigArrays, int[] array, long size, Recycler.V<int[]> releasable, boolean clearOnResize) {
|
|
|
|
+ super(bigArrays, size, releasable, clearOnResize);
|
|
this.array = array;
|
|
this.array = array;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public long sizeInBytes() {
|
|
|
|
+ return SHALLOW_SIZE + RamUsageEstimator.sizeOf(array);
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public int get(long index) {
|
|
public int get(long index) {
|
|
assert indexIsInt(index);
|
|
assert indexIsInt(index);
|
|
@@ -190,11 +206,16 @@ public class BigArrays extends AbstractComponent {
|
|
|
|
|
|
private final long[] array;
|
|
private final long[] array;
|
|
|
|
|
|
- LongArrayWrapper(long[] array, long size, Recycler.V<long[]> releasable, boolean clearOnResize) {
|
|
|
|
- super(size, releasable, clearOnResize);
|
|
|
|
|
|
+ LongArrayWrapper(BigArrays bigArrays, long[] array, long size, Recycler.V<long[]> releasable, boolean clearOnResize) {
|
|
|
|
+ super(bigArrays, size, releasable, clearOnResize);
|
|
this.array = array;
|
|
this.array = array;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public long sizeInBytes() {
|
|
|
|
+ return SHALLOW_SIZE + RamUsageEstimator.sizeOf(array);
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public long get(long index) {
|
|
public long get(long index) {
|
|
assert indexIsInt(index);
|
|
assert indexIsInt(index);
|
|
@@ -227,11 +248,16 @@ public class BigArrays extends AbstractComponent {
|
|
|
|
|
|
private final double[] array;
|
|
private final double[] array;
|
|
|
|
|
|
- DoubleArrayWrapper(double[] array, long size, Recycler.V<double[]> releasable, boolean clearOnResize) {
|
|
|
|
- super(size, releasable, clearOnResize);
|
|
|
|
|
|
+ DoubleArrayWrapper(BigArrays bigArrays, double[] array, long size, Recycler.V<double[]> releasable, boolean clearOnResize) {
|
|
|
|
+ super(bigArrays, size, releasable, clearOnResize);
|
|
this.array = array;
|
|
this.array = array;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public long sizeInBytes() {
|
|
|
|
+ return SHALLOW_SIZE + RamUsageEstimator.sizeOf(array);
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public double get(long index) {
|
|
public double get(long index) {
|
|
assert indexIsInt(index);
|
|
assert indexIsInt(index);
|
|
@@ -265,11 +291,16 @@ public class BigArrays extends AbstractComponent {
|
|
|
|
|
|
private final float[] array;
|
|
private final float[] array;
|
|
|
|
|
|
- FloatArrayWrapper(float[] array, long size, Recycler.V<float[]> releasable, boolean clearOnResize) {
|
|
|
|
- super(size, releasable, clearOnResize);
|
|
|
|
|
|
+ FloatArrayWrapper(BigArrays bigArrays, float[] array, long size, Recycler.V<float[]> releasable, boolean clearOnResize) {
|
|
|
|
+ super(bigArrays, size, releasable, clearOnResize);
|
|
this.array = array;
|
|
this.array = array;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public long sizeInBytes() {
|
|
|
|
+ return SHALLOW_SIZE + RamUsageEstimator.sizeOf(array);
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public float get(long index) {
|
|
public float get(long index) {
|
|
assert indexIsInt(index);
|
|
assert indexIsInt(index);
|
|
@@ -303,11 +334,16 @@ public class BigArrays extends AbstractComponent {
|
|
|
|
|
|
private final Object[] array;
|
|
private final Object[] array;
|
|
|
|
|
|
- ObjectArrayWrapper(Object[] array, long size, Recycler.V<Object[]> releasable) {
|
|
|
|
- super(size, releasable, true);
|
|
|
|
|
|
+ ObjectArrayWrapper(BigArrays bigArrays, Object[] array, long size, Recycler.V<Object[]> releasable) {
|
|
|
|
+ super(bigArrays, size, releasable, true);
|
|
this.array = array;
|
|
this.array = array;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public long sizeInBytes() {
|
|
|
|
+ return SHALLOW_SIZE + RamUsageEstimator.alignObjectSize(RamUsageEstimator.NUM_BYTES_ARRAY_HEADER + RamUsageEstimator.NUM_BYTES_OBJECT_REF * size());
|
|
|
|
+ }
|
|
|
|
+
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
@Override
|
|
public T get(long index) {
|
|
public T get(long index) {
|
|
@@ -327,11 +363,46 @@ public class BigArrays extends AbstractComponent {
|
|
}
|
|
}
|
|
|
|
|
|
final PageCacheRecycler recycler;
|
|
final PageCacheRecycler recycler;
|
|
|
|
+ final AtomicLong ramBytesUsed;
|
|
|
|
+ final long maxSizeInBytes;
|
|
|
|
|
|
@Inject
|
|
@Inject
|
|
public BigArrays(Settings settings, PageCacheRecycler recycler) {
|
|
public BigArrays(Settings settings, PageCacheRecycler recycler) {
|
|
|
|
+ this(settings, recycler, settings.getAsMemory(MAX_SIZE_IN_BYTES_SETTING, "20%").bytes());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private BigArrays(Settings settings, PageCacheRecycler recycler, final long maxSizeInBytes) {
|
|
super(settings);
|
|
super(settings);
|
|
|
|
+ this.maxSizeInBytes = maxSizeInBytes;
|
|
this.recycler = recycler;
|
|
this.recycler = recycler;
|
|
|
|
+ ramBytesUsed = new AtomicLong();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void validate(long delta) {
|
|
|
|
+ final long totalSizeInBytes = ramBytesUsed.addAndGet(delta);
|
|
|
|
+ if (totalSizeInBytes > maxSizeInBytes) {
|
|
|
|
+ throw new ElasticsearchIllegalStateException("Maximum number of bytes allocated exceeded: [" + totalSizeInBytes + "] (> " + maxSizeInBytes + ")");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private <T extends AbstractBigArray> T resizeInPlace(T array, long newSize) {
|
|
|
|
+ final long oldMemSize = array.sizeInBytes();
|
|
|
|
+ array.resize(newSize);
|
|
|
|
+ validate(array.sizeInBytes() - oldMemSize);
|
|
|
|
+ return array;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private <T extends BigArray> T validate(T array) {
|
|
|
|
+ boolean success = false;
|
|
|
|
+ try {
|
|
|
|
+ validate(array.sizeInBytes());
|
|
|
|
+ success = true;
|
|
|
|
+ } finally {
|
|
|
|
+ if (!success) {
|
|
|
|
+ Releasables.closeWhileHandlingException(array);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return array;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -340,14 +411,16 @@ public class BigArrays extends AbstractComponent {
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
*/
|
|
*/
|
|
public ByteArray newByteArray(long size, boolean clearOnResize) {
|
|
public ByteArray newByteArray(long size, boolean clearOnResize) {
|
|
|
|
+ final ByteArray array;
|
|
if (size > BYTE_PAGE_SIZE) {
|
|
if (size > BYTE_PAGE_SIZE) {
|
|
- return new BigByteArray(size, recycler, clearOnResize);
|
|
|
|
|
|
+ array = new BigByteArray(size, this, clearOnResize);
|
|
} else if (size >= BYTE_PAGE_SIZE / 2 && recycler != null) {
|
|
} else if (size >= BYTE_PAGE_SIZE / 2 && recycler != null) {
|
|
final Recycler.V<byte[]> page = recycler.bytePage(clearOnResize);
|
|
final Recycler.V<byte[]> page = recycler.bytePage(clearOnResize);
|
|
- return new ByteArrayWrapper(page.v(), size, page, clearOnResize);
|
|
|
|
|
|
+ array = new ByteArrayWrapper(this, page.v(), size, page, clearOnResize);
|
|
} else {
|
|
} else {
|
|
- return new ByteArrayWrapper(new byte[(int) size], size, null, clearOnResize);
|
|
|
|
|
|
+ array = new ByteArrayWrapper(this, new byte[(int) size], size, null, clearOnResize);
|
|
}
|
|
}
|
|
|
|
+ return validate(array);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -361,14 +434,13 @@ public class BigArrays extends AbstractComponent {
|
|
/** Resize the array to the exact provided size. */
|
|
/** Resize the array to the exact provided size. */
|
|
public ByteArray resize(ByteArray array, long size) {
|
|
public ByteArray resize(ByteArray array, long size) {
|
|
if (array instanceof BigByteArray) {
|
|
if (array instanceof BigByteArray) {
|
|
- ((BigByteArray) array).resize(size);
|
|
|
|
- return array;
|
|
|
|
|
|
+ return resizeInPlace((BigByteArray) array, size);
|
|
} else {
|
|
} else {
|
|
AbstractArray arr = (AbstractArray) array;
|
|
AbstractArray arr = (AbstractArray) array;
|
|
final ByteArray newArray = newByteArray(size, arr.clearOnResize);
|
|
final ByteArray newArray = newByteArray(size, arr.clearOnResize);
|
|
final byte[] rawArray = ((ByteArrayWrapper) array).array;
|
|
final byte[] rawArray = ((ByteArrayWrapper) array).array;
|
|
newArray.set(0, rawArray, 0, (int) Math.min(rawArray.length, newArray.size()));
|
|
newArray.set(0, rawArray, 0, (int) Math.min(rawArray.length, newArray.size()));
|
|
- array.close();
|
|
|
|
|
|
+ arr.close();
|
|
return newArray;
|
|
return newArray;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -421,14 +493,16 @@ public class BigArrays extends AbstractComponent {
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
*/
|
|
*/
|
|
public IntArray newIntArray(long size, boolean clearOnResize) {
|
|
public IntArray newIntArray(long size, boolean clearOnResize) {
|
|
|
|
+ final IntArray array;
|
|
if (size > INT_PAGE_SIZE) {
|
|
if (size > INT_PAGE_SIZE) {
|
|
- return new BigIntArray(size, recycler, clearOnResize);
|
|
|
|
|
|
+ array = new BigIntArray(size, this, clearOnResize);
|
|
} else if (size >= INT_PAGE_SIZE / 2 && recycler != null) {
|
|
} else if (size >= INT_PAGE_SIZE / 2 && recycler != null) {
|
|
final Recycler.V<int[]> page = recycler.intPage(clearOnResize);
|
|
final Recycler.V<int[]> page = recycler.intPage(clearOnResize);
|
|
- return new IntArrayWrapper(page.v(), size, page, clearOnResize);
|
|
|
|
|
|
+ array = new IntArrayWrapper(this, page.v(), size, page, clearOnResize);
|
|
} else {
|
|
} else {
|
|
- return new IntArrayWrapper(new int[(int) size], size, null, clearOnResize);
|
|
|
|
|
|
+ array = new IntArrayWrapper(this, new int[(int) size], size, null, clearOnResize);
|
|
}
|
|
}
|
|
|
|
+ return validate(array);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -442,8 +516,7 @@ public class BigArrays extends AbstractComponent {
|
|
/** Resize the array to the exact provided size. */
|
|
/** Resize the array to the exact provided size. */
|
|
public IntArray resize(IntArray array, long size) {
|
|
public IntArray resize(IntArray array, long size) {
|
|
if (array instanceof BigIntArray) {
|
|
if (array instanceof BigIntArray) {
|
|
- ((BigIntArray) array).resize(size);
|
|
|
|
- return array;
|
|
|
|
|
|
+ return resizeInPlace((BigIntArray) array, size);
|
|
} else {
|
|
} else {
|
|
AbstractArray arr = (AbstractArray) array;
|
|
AbstractArray arr = (AbstractArray) array;
|
|
final IntArray newArray = newIntArray(size, arr.clearOnResize);
|
|
final IntArray newArray = newIntArray(size, arr.clearOnResize);
|
|
@@ -470,14 +543,16 @@ public class BigArrays extends AbstractComponent {
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
*/
|
|
*/
|
|
public LongArray newLongArray(long size, boolean clearOnResize) {
|
|
public LongArray newLongArray(long size, boolean clearOnResize) {
|
|
|
|
+ final LongArray array;
|
|
if (size > LONG_PAGE_SIZE) {
|
|
if (size > LONG_PAGE_SIZE) {
|
|
- return new BigLongArray(size, recycler, clearOnResize);
|
|
|
|
|
|
+ array = new BigLongArray(size, this, clearOnResize);
|
|
} else if (size >= LONG_PAGE_SIZE / 2 && recycler != null) {
|
|
} else if (size >= LONG_PAGE_SIZE / 2 && recycler != null) {
|
|
final Recycler.V<long[]> page = recycler.longPage(clearOnResize);
|
|
final Recycler.V<long[]> page = recycler.longPage(clearOnResize);
|
|
- return new LongArrayWrapper(page.v(), size, page, clearOnResize);
|
|
|
|
|
|
+ array = new LongArrayWrapper(this, page.v(), size, page, clearOnResize);
|
|
} else {
|
|
} else {
|
|
- return new LongArrayWrapper(new long[(int) size], size, null, clearOnResize);
|
|
|
|
|
|
+ array = new LongArrayWrapper(this, new long[(int) size], size, null, clearOnResize);
|
|
}
|
|
}
|
|
|
|
+ return validate(array);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -491,8 +566,7 @@ public class BigArrays extends AbstractComponent {
|
|
/** Resize the array to the exact provided size. */
|
|
/** Resize the array to the exact provided size. */
|
|
public LongArray resize(LongArray array, long size) {
|
|
public LongArray resize(LongArray array, long size) {
|
|
if (array instanceof BigLongArray) {
|
|
if (array instanceof BigLongArray) {
|
|
- ((BigLongArray) array).resize(size);
|
|
|
|
- return array;
|
|
|
|
|
|
+ return resizeInPlace((BigLongArray) array, size);
|
|
} else {
|
|
} else {
|
|
AbstractArray arr = (AbstractArray) array;
|
|
AbstractArray arr = (AbstractArray) array;
|
|
final LongArray newArray = newLongArray(size, arr.clearOnResize);
|
|
final LongArray newArray = newLongArray(size, arr.clearOnResize);
|
|
@@ -519,14 +593,16 @@ public class BigArrays extends AbstractComponent {
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
*/
|
|
*/
|
|
public DoubleArray newDoubleArray(long size, boolean clearOnResize) {
|
|
public DoubleArray newDoubleArray(long size, boolean clearOnResize) {
|
|
|
|
+ final DoubleArray arr;
|
|
if (size > DOUBLE_PAGE_SIZE) {
|
|
if (size > DOUBLE_PAGE_SIZE) {
|
|
- return new BigDoubleArray(size, recycler, clearOnResize);
|
|
|
|
|
|
+ arr = new BigDoubleArray(size, this, clearOnResize);
|
|
} else if (size >= DOUBLE_PAGE_SIZE / 2 && recycler != null) {
|
|
} else if (size >= DOUBLE_PAGE_SIZE / 2 && recycler != null) {
|
|
final Recycler.V<double[]> page = recycler.doublePage(clearOnResize);
|
|
final Recycler.V<double[]> page = recycler.doublePage(clearOnResize);
|
|
- return new DoubleArrayWrapper(page.v(), size, page, clearOnResize);
|
|
|
|
|
|
+ arr = new DoubleArrayWrapper(this, page.v(), size, page, clearOnResize);
|
|
} else {
|
|
} else {
|
|
- return new DoubleArrayWrapper(new double[(int) size], size, null, clearOnResize);
|
|
|
|
|
|
+ arr = new DoubleArrayWrapper(this, new double[(int) size], size, null, clearOnResize);
|
|
}
|
|
}
|
|
|
|
+ return validate(arr);
|
|
}
|
|
}
|
|
|
|
|
|
/** Allocate a new {@link DoubleArray} of the given capacity. */
|
|
/** Allocate a new {@link DoubleArray} of the given capacity. */
|
|
@@ -537,8 +613,7 @@ public class BigArrays extends AbstractComponent {
|
|
/** Resize the array to the exact provided size. */
|
|
/** Resize the array to the exact provided size. */
|
|
public DoubleArray resize(DoubleArray array, long size) {
|
|
public DoubleArray resize(DoubleArray array, long size) {
|
|
if (array instanceof BigDoubleArray) {
|
|
if (array instanceof BigDoubleArray) {
|
|
- ((BigDoubleArray) array).resize(size);
|
|
|
|
- return array;
|
|
|
|
|
|
+ return resizeInPlace((BigDoubleArray) array, size);
|
|
} else {
|
|
} else {
|
|
AbstractArray arr = (AbstractArray) array;
|
|
AbstractArray arr = (AbstractArray) array;
|
|
final DoubleArray newArray = newDoubleArray(size, arr.clearOnResize);
|
|
final DoubleArray newArray = newDoubleArray(size, arr.clearOnResize);
|
|
@@ -565,14 +640,16 @@ public class BigArrays extends AbstractComponent {
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
* @param clearOnResize whether values should be set to 0 on initialization and resize
|
|
*/
|
|
*/
|
|
public FloatArray newFloatArray(long size, boolean clearOnResize) {
|
|
public FloatArray newFloatArray(long size, boolean clearOnResize) {
|
|
|
|
+ final FloatArray array;
|
|
if (size > FLOAT_PAGE_SIZE) {
|
|
if (size > FLOAT_PAGE_SIZE) {
|
|
- return new BigFloatArray(size, recycler, clearOnResize);
|
|
|
|
|
|
+ array = new BigFloatArray(size, this, clearOnResize);
|
|
} else if (size >= FLOAT_PAGE_SIZE / 2 && recycler != null) {
|
|
} else if (size >= FLOAT_PAGE_SIZE / 2 && recycler != null) {
|
|
final Recycler.V<float[]> page = recycler.floatPage(clearOnResize);
|
|
final Recycler.V<float[]> page = recycler.floatPage(clearOnResize);
|
|
- return new FloatArrayWrapper(page.v(), size, page, clearOnResize);
|
|
|
|
|
|
+ array = new FloatArrayWrapper(this, page.v(), size, page, clearOnResize);
|
|
} else {
|
|
} else {
|
|
- return new FloatArrayWrapper(new float[(int) size], size, null, clearOnResize);
|
|
|
|
|
|
+ array = new FloatArrayWrapper(this, new float[(int) size], size, null, clearOnResize);
|
|
}
|
|
}
|
|
|
|
+ return validate(array);
|
|
}
|
|
}
|
|
|
|
|
|
/** Allocate a new {@link FloatArray} of the given capacity. */
|
|
/** Allocate a new {@link FloatArray} of the given capacity. */
|
|
@@ -583,14 +660,14 @@ public class BigArrays extends AbstractComponent {
|
|
/** Resize the array to the exact provided size. */
|
|
/** Resize the array to the exact provided size. */
|
|
public FloatArray resize(FloatArray array, long size) {
|
|
public FloatArray resize(FloatArray array, long size) {
|
|
if (array instanceof BigFloatArray) {
|
|
if (array instanceof BigFloatArray) {
|
|
- ((BigFloatArray) array).resize(size);
|
|
|
|
- return array;
|
|
|
|
|
|
+ return resizeInPlace((BigFloatArray) array, size);
|
|
} else {
|
|
} else {
|
|
AbstractArray arr = (AbstractArray) array;
|
|
AbstractArray arr = (AbstractArray) array;
|
|
final FloatArray newArray = newFloatArray(size, arr.clearOnResize);
|
|
final FloatArray newArray = newFloatArray(size, arr.clearOnResize);
|
|
for (long i = 0, end = Math.min(size, array.size()); i < end; ++i) {
|
|
for (long i = 0, end = Math.min(size, array.size()); i < end; ++i) {
|
|
newArray.set(i, array.get(i));
|
|
newArray.set(i, array.get(i));
|
|
}
|
|
}
|
|
|
|
+ arr.close();
|
|
return newArray;
|
|
return newArray;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -609,21 +686,22 @@ public class BigArrays extends AbstractComponent {
|
|
* @param size the initial length of the array
|
|
* @param size the initial length of the array
|
|
*/
|
|
*/
|
|
public <T> ObjectArray<T> newObjectArray(long size) {
|
|
public <T> ObjectArray<T> newObjectArray(long size) {
|
|
|
|
+ final ObjectArray<T> array;
|
|
if (size > OBJECT_PAGE_SIZE) {
|
|
if (size > OBJECT_PAGE_SIZE) {
|
|
- return new BigObjectArray<>(size, recycler);
|
|
|
|
|
|
+ array = new BigObjectArray<>(size, this);
|
|
} else if (size >= OBJECT_PAGE_SIZE / 2 && recycler != null) {
|
|
} else if (size >= OBJECT_PAGE_SIZE / 2 && recycler != null) {
|
|
final Recycler.V<Object[]> page = recycler.objectPage();
|
|
final Recycler.V<Object[]> page = recycler.objectPage();
|
|
- return new ObjectArrayWrapper<>(page.v(), size, page);
|
|
|
|
|
|
+ array = new ObjectArrayWrapper<>(this, page.v(), size, page);
|
|
} else {
|
|
} else {
|
|
- return new ObjectArrayWrapper<>(new Object[(int) size], size, null);
|
|
|
|
|
|
+ array = new ObjectArrayWrapper<>(this, new Object[(int) size], size, null);
|
|
}
|
|
}
|
|
|
|
+ return validate(array);
|
|
}
|
|
}
|
|
|
|
|
|
/** Resize the array to the exact provided size. */
|
|
/** Resize the array to the exact provided size. */
|
|
public <T> ObjectArray<T> resize(ObjectArray<T> array, long size) {
|
|
public <T> ObjectArray<T> resize(ObjectArray<T> array, long size) {
|
|
if (array instanceof BigObjectArray) {
|
|
if (array instanceof BigObjectArray) {
|
|
- ((BigObjectArray<?>) array).resize(size);
|
|
|
|
- return array;
|
|
|
|
|
|
+ return resizeInPlace((BigObjectArray<T>) array, size);
|
|
} else {
|
|
} else {
|
|
final ObjectArray<T> newArray = newObjectArray(size);
|
|
final ObjectArray<T> newArray = newObjectArray(size);
|
|
for (long i = 0, end = Math.min(size, array.size()); i < end; ++i) {
|
|
for (long i = 0, end = Math.min(size, array.size()); i < end; ++i) {
|
|
@@ -643,4 +721,10 @@ public class BigArrays extends AbstractComponent {
|
|
return resize(array, newSize);
|
|
return resize(array, newSize);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Return an approximate number of bytes that have been allocated but not released yet.
|
|
|
|
+ */
|
|
|
|
+ public long sizeInBytes() {
|
|
|
|
+ return ramBytesUsed.get();
|
|
|
|
+ }
|
|
}
|
|
}
|