Skip to content

Commit 7573aba

Browse files
committed
Change MultiBuffer to use an array instead of a list to store buffers
1 parent 0ff877e commit 7573aba

File tree

2 files changed

+29
-22
lines changed

2 files changed

+29
-22
lines changed

src/main/java/com/maxmind/db/BufferHolder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ final class BufferHolder {
7575
}
7676
this.buffer = SingleBuffer.wrap(data);
7777
} else {
78-
this.buffer = MultiBuffer.wrap(chunks);
78+
this.buffer = MultiBuffer.wrap(chunks.toArray(new ByteBuffer[0]));
7979
}
8080
}
8181

src/main/java/com/maxmind/db/MultiBuffer.java

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class MultiBuffer implements Buffer {
2525
/** Maximum size per underlying chunk. */
2626
static final int CHUNK_SIZE = Integer.MAX_VALUE / 2;
2727

28-
final List<ByteBuffer> buffers = new ArrayList<>();
28+
final ByteBuffer[] buffers;
2929
private final long capacity;
3030

3131
private long position = 0;
@@ -46,17 +46,24 @@ public MultiBuffer(long capacity) {
4646

4747
int fullChunks = (int) (capacity / CHUNK_SIZE);
4848
int remainder = (int) (capacity % CHUNK_SIZE);
49+
int totalChunks = fullChunks + (remainder > 0 ? 1 : 0);
50+
51+
this.buffers = new ByteBuffer[totalChunks];
52+
4953
for (int i = 0; i < fullChunks; i++) {
50-
buffers.add(ByteBuffer.allocateDirect(CHUNK_SIZE));
54+
buffers[i] = ByteBuffer.allocateDirect(CHUNK_SIZE);
5155
}
5256
if (remainder > 0) {
53-
buffers.add(ByteBuffer.allocateDirect(remainder));
57+
buffers[totalChunks - 1] = ByteBuffer.allocateDirect(remainder);
5458
}
5559
}
5660

57-
private MultiBuffer(List<ByteBuffer> buffers) {
58-
this.buffers.addAll(buffers);
59-
long capacity = buffers.stream().mapToLong(ByteBuffer::capacity).sum();
61+
private MultiBuffer(ByteBuffer[] buffers) {
62+
this.buffers = buffers.clone();
63+
long capacity = 0;
64+
for (ByteBuffer buffer : buffers) {
65+
capacity += buffer.capacity();
66+
}
6067
this.capacity = capacity;
6168
this.limit = capacity;
6269
}
@@ -126,7 +133,7 @@ public Buffer get(byte[] dst) {
126133
while (length > 0) {
127134
int bufIndex = (int) (pos / CHUNK_SIZE);
128135
int bufOffset = (int) (pos % CHUNK_SIZE);
129-
ByteBuffer buf = buffers.get(bufIndex).duplicate();
136+
ByteBuffer buf = buffers[bufIndex].duplicate();
130137
buf.position(bufOffset);
131138
int toRead = Math.min(buf.remaining(), length);
132139
buf.get(dst, offset, toRead);
@@ -146,15 +153,15 @@ public byte get(long index) {
146153
}
147154
int bufIndex = (int) (index / CHUNK_SIZE);
148155
int offset = (int) (index % CHUNK_SIZE);
149-
return buffers.get(bufIndex).get(offset);
156+
return buffers[bufIndex].get(offset);
150157
}
151158

152159
/** {@inheritDoc} */
153160
@Override
154161
public double getDouble() {
155162
int bufIndex = (int) (position / CHUNK_SIZE);
156163
int off = (int) (position % CHUNK_SIZE);
157-
ByteBuffer buf = buffers.get(bufIndex);
164+
ByteBuffer buf = buffers[bufIndex];
158165
buf.position(off);
159166
if (buf.remaining() >= 8) {
160167
double value = buf.getDouble();
@@ -172,7 +179,7 @@ public double getDouble() {
172179
public float getFloat() {
173180
int bufIndex = (int) (position / CHUNK_SIZE);
174181
int off = (int) (position % CHUNK_SIZE);
175-
ByteBuffer buf = buffers.get(bufIndex);
182+
ByteBuffer buf = buffers[bufIndex];
176183
buf.position(off);
177184
if (buf.remaining() >= 4) {
178185
float value = buf.getFloat();
@@ -189,8 +196,8 @@ public float getFloat() {
189196
@Override
190197
public Buffer duplicate() {
191198
MultiBuffer copy = new MultiBuffer(capacity);
192-
for (int i = 0; i < buffers.size(); i++) {
193-
copy.buffers.set(i, buffers.get(i).duplicate());
199+
for (int i = 0; i < buffers.length; i++) {
200+
copy.buffers[i] = buffers[i].duplicate();
194201
}
195202
copy.position = this.position;
196203
copy.limit = this.limit;
@@ -202,8 +209,8 @@ public Buffer duplicate() {
202209
public long readFrom(FileChannel channel) throws IOException {
203210
long totalRead = 0;
204211
long pos = position;
205-
for (int i = (int) (pos / CHUNK_SIZE); i < buffers.size(); i++) {
206-
ByteBuffer buf = buffers.get(i);
212+
for (int i = (int) (pos / CHUNK_SIZE); i < buffers.length; i++) {
213+
ByteBuffer buf = buffers[i];
207214
buf.position((int) (pos % CHUNK_SIZE));
208215
int read = channel.read(buf);
209216
if (read == -1) {
@@ -240,7 +247,7 @@ public String decode(CharsetDecoder decoder)
240247
int bufIndex = (int) (pos / CHUNK_SIZE);
241248
int bufOffset = (int) (pos % CHUNK_SIZE);
242249

243-
ByteBuffer srcView = buffers.get(bufIndex).duplicate();
250+
ByteBuffer srcView = buffers[bufIndex].duplicate();
244251
srcView.position(bufOffset);
245252

246253
int toRead = (int) Math.min(srcView.remaining(), remainingBytes);
@@ -272,13 +279,13 @@ public String decode(CharsetDecoder decoder)
272279
* @param chunks the byte arrays to wrap
273280
* @return a new {@code MultiBuffer} backed by the arrays
274281
*/
275-
public static MultiBuffer wrap(List<ByteBuffer> chunks) {
276-
for (int i = 0; i < chunks.size(); i++) {
277-
ByteBuffer chunk = chunks.get(i);
282+
public static MultiBuffer wrap(ByteBuffer[] chunks) {
283+
for (int i = 0; i < chunks.length; i++) {
284+
ByteBuffer chunk = chunks[i];
278285
if (chunk.capacity() == CHUNK_SIZE) {
279286
continue;
280287
}
281-
if (i == chunks.size() - 1) {
288+
if (i == chunks.length - 1) {
282289
// The last chunk can have a different size
283290
continue;
284291
}
@@ -306,15 +313,15 @@ public static MultiBuffer mapFromChannel(FileChannel channel) throws IOException
306313
MultiBuffer buf = new MultiBuffer(size);
307314
long remaining = size;
308315

309-
for (int i = 0; i < buf.buffers.size(); i++) {
316+
for (int i = 0; i < buf.buffers.length; i++) {
310317
long chunkPos = (long) i * CHUNK_SIZE;
311318
long chunkSize = Math.min(CHUNK_SIZE, remaining);
312319
ByteBuffer mapped = channel.map(
313320
FileChannel.MapMode.READ_ONLY,
314321
chunkPos,
315322
chunkSize
316323
);
317-
buf.buffers.set(i, mapped);
324+
buf.buffers[i] = mapped;
318325
remaining -= chunkSize;
319326
}
320327
return buf;

0 commit comments

Comments
 (0)