mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-06 21:18:31 +00:00
improve the logic of expanding byte arrays
This commit is contained in:
parent
7ff4371f95
commit
83323f2c88
@ -19,11 +19,102 @@
|
||||
|
||||
package org.elasticsearch.common;
|
||||
|
||||
import org.elasticsearch.monitor.jvm.JvmUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Bytes {
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array size >= minTargetSize, generally
|
||||
* over-allocating exponentially to achieve amortized
|
||||
* linear-time cost as the array grows.
|
||||
* <p/>
|
||||
* NOTE: this was originally borrowed from Python 2.4.2
|
||||
* listobject.c sources (attribution in LICENSE.txt), but
|
||||
* has now been substantially changed based on
|
||||
* discussions from java-dev thread with subject "Dynamic
|
||||
* array reallocation algorithms", started on Jan 12
|
||||
* 2010.
|
||||
*
|
||||
* @param minTargetSize Minimum required value to be returned.
|
||||
* @param bytesPerElement Bytes used by each element of
|
||||
* the array. See constants in {@link RamUsageEstimator}.
|
||||
* @lucene.internal
|
||||
*/
|
||||
|
||||
public static int oversize(int minTargetSize, int bytesPerElement) {
|
||||
|
||||
if (minTargetSize < 0) {
|
||||
// catch usage that accidentally overflows int
|
||||
throw new IllegalArgumentException("invalid array size " + minTargetSize);
|
||||
}
|
||||
|
||||
if (minTargetSize == 0) {
|
||||
// wait until at least one element is requested
|
||||
return 0;
|
||||
}
|
||||
|
||||
// asymptotic exponential growth by 1/8th, favors
|
||||
// spending a bit more CPU to not tie up too much wasted
|
||||
// RAM:
|
||||
int extra = minTargetSize >> 3;
|
||||
|
||||
if (extra < 3) {
|
||||
// for very small arrays, where constant overhead of
|
||||
// realloc is presumably relatively high, we grow
|
||||
// faster
|
||||
extra = 3;
|
||||
}
|
||||
|
||||
int newSize = minTargetSize + extra;
|
||||
|
||||
// add 7 to allow for worst case byte alignment addition below:
|
||||
if (newSize + 7 < 0) {
|
||||
// int overflowed -- return max allowed array size
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
if (JvmUtils.JRE_IS_64BIT) {
|
||||
// round up to 8 byte alignment in 64bit env
|
||||
switch (bytesPerElement) {
|
||||
case 4:
|
||||
// round up to multiple of 2
|
||||
return (newSize + 1) & 0x7ffffffe;
|
||||
case 2:
|
||||
// round up to multiple of 4
|
||||
return (newSize + 3) & 0x7ffffffc;
|
||||
case 1:
|
||||
// round up to multiple of 8
|
||||
return (newSize + 7) & 0x7ffffff8;
|
||||
case 8:
|
||||
// no rounding
|
||||
default:
|
||||
// odd (invalid?) size
|
||||
return newSize;
|
||||
}
|
||||
} else {
|
||||
// round up to 4 byte alignment in 64bit env
|
||||
switch (bytesPerElement) {
|
||||
case 2:
|
||||
// round up to multiple of 2
|
||||
return (newSize + 1) & 0x7ffffffe;
|
||||
case 1:
|
||||
// round up to multiple of 4
|
||||
return (newSize + 3) & 0x7ffffffc;
|
||||
case 4:
|
||||
case 8:
|
||||
// no rounding
|
||||
default:
|
||||
// odd (invalid?) size
|
||||
return newSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final byte[] EMPTY_ARRAY = new byte[0];
|
||||
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.elasticsearch.common.io;
|
||||
|
||||
import org.elasticsearch.common.Bytes;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
|
||||
@ -76,7 +77,7 @@ public class FastByteArrayOutputStream extends OutputStream implements BytesStre
|
||||
public void write(int b) {
|
||||
int newcount = count + 1;
|
||||
if (newcount > buf.length) {
|
||||
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
|
||||
buf = Arrays.copyOf(buf, Bytes.oversize(newcount, 1));
|
||||
}
|
||||
buf[count] = (byte) b;
|
||||
count = newcount;
|
||||
@ -98,7 +99,7 @@ public class FastByteArrayOutputStream extends OutputStream implements BytesStre
|
||||
}
|
||||
int newcount = count + len;
|
||||
if (newcount > buf.length) {
|
||||
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
|
||||
buf = Arrays.copyOf(buf, Bytes.oversize(newcount, 1));
|
||||
}
|
||||
System.arraycopy(b, off, buf, count, len);
|
||||
count = newcount;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.elasticsearch.common.io.stream;
|
||||
|
||||
import org.elasticsearch.common.Bytes;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.BytesStream;
|
||||
@ -42,7 +43,7 @@ public class BytesStreamOutput extends StreamOutput implements BytesStream {
|
||||
protected int count;
|
||||
|
||||
public BytesStreamOutput() {
|
||||
this(126);
|
||||
this(1024);
|
||||
}
|
||||
|
||||
public BytesStreamOutput(int size) {
|
||||
@ -53,7 +54,7 @@ public class BytesStreamOutput extends StreamOutput implements BytesStream {
|
||||
public void writeByte(byte b) throws IOException {
|
||||
int newcount = count + 1;
|
||||
if (newcount > buf.length) {
|
||||
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
|
||||
buf = Arrays.copyOf(buf, Bytes.oversize(newcount, 1));
|
||||
}
|
||||
buf[count] = b;
|
||||
count = newcount;
|
||||
@ -66,7 +67,7 @@ public class BytesStreamOutput extends StreamOutput implements BytesStream {
|
||||
}
|
||||
int newcount = count + length;
|
||||
if (newcount > buf.length) {
|
||||
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
|
||||
buf = Arrays.copyOf(buf, Bytes.oversize(newcount, 1));
|
||||
}
|
||||
System.arraycopy(b, offset, buf, count, length);
|
||||
count = newcount;
|
||||
|
81
src/main/java/org/elasticsearch/monitor/jvm/JvmUtils.java
Normal file
81
src/main/java/org/elasticsearch/monitor/jvm/JvmUtils.java
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.monitor.jvm;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class JvmUtils {
|
||||
|
||||
/**
|
||||
* True iff running on a 64bit JVM
|
||||
*/
|
||||
public static final boolean JRE_IS_64BIT;
|
||||
|
||||
public static final boolean JRE_IS_MINIMUM_JAVA6;
|
||||
public static final boolean JRE_IS_MINIMUM_JAVA7;
|
||||
|
||||
static {
|
||||
boolean is64Bit = false;
|
||||
try {
|
||||
final Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
||||
final Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
final Object unsafe = unsafeField.get(null);
|
||||
final int addressSize = ((Number) unsafeClass.getMethod("addressSize")
|
||||
.invoke(unsafe)).intValue();
|
||||
//System.out.println("Address size: " + addressSize);
|
||||
is64Bit = addressSize >= 8;
|
||||
} catch (Throwable e) {
|
||||
final String x = System.getProperty("sun.arch.data.model");
|
||||
if (x != null) {
|
||||
is64Bit = x.indexOf("64") != -1;
|
||||
} else {
|
||||
String OS_ARCH = System.getProperty("os.arch");
|
||||
if (OS_ARCH != null && OS_ARCH.indexOf("64") != -1) {
|
||||
is64Bit = true;
|
||||
} else {
|
||||
is64Bit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
JRE_IS_64BIT = is64Bit;
|
||||
|
||||
// this method only exists in Java 6:
|
||||
boolean v6 = true;
|
||||
try {
|
||||
String.class.getMethod("isEmpty");
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
v6 = false;
|
||||
}
|
||||
JRE_IS_MINIMUM_JAVA6 = v6;
|
||||
|
||||
// this method only exists in Java 7:
|
||||
boolean v7 = true;
|
||||
try {
|
||||
Throwable.class.getMethod("getSuppressed");
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
v7 = false;
|
||||
}
|
||||
JRE_IS_MINIMUM_JAVA7 = v7;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user