Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

Commit 30cd2e3

Browse files
committed
performance improvements suggested by a1k0n
1 parent bd5b8cf commit 30cd2e3

1 file changed

Lines changed: 19 additions & 14 deletions

File tree

src/main/java/com/spotify/annoy/ANNIndex.java

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class ANNIndex implements AnnoyIndex {
1515

1616

1717
private final ArrayList<Long> roots;
18-
private Map<Integer, MappedByteBuffer> buffers = new HashMap<>();
18+
private MappedByteBuffer[] buffers;
1919

2020
private final int DIMENSION, MIN_LEAF_SIZE;
2121
private final IndexType INDEX_TYPE;
@@ -72,20 +72,25 @@ public ANNIndex(final int dimension,
7272
private void load(final String filename) throws IOException {
7373
memoryMappedFile = new RandomAccessFile(filename, "r");
7474
long fileSize = memoryMappedFile.length();
75-
int buffIndex = (int) Math.ceil(((double) fileSize) / BLOCK_SIZE) - 1;
75+
if (fileSize == 0L) {
76+
throw new IOException("Index is a 0-byte file?");
77+
}
78+
79+
int buffIndex = (int) (fileSize - 1) / BLOCK_SIZE;
7680
int rest = (int) (fileSize % BLOCK_SIZE);
7781
int blockSize = (rest > 0 ? rest : BLOCK_SIZE);
7882
long position = Math.max(0, fileSize - blockSize);
7983

84+
buffers = new MappedByteBuffer[buffIndex + 1];
8085
boolean process = true;
8186
int m = -1;
8287
long index = fileSize;
83-
while(blockSize > 0) {
88+
while(position >= 0) {
8489
MappedByteBuffer annBuf = memoryMappedFile.getChannel().map(
8590
FileChannel.MapMode.READ_ONLY, position, blockSize);
8691
annBuf.order(ByteOrder.LITTLE_ENDIAN);
8792

88-
buffers.put(buffIndex--, annBuf);
93+
buffers[buffIndex--] = annBuf;
8994

9095
for (int i = blockSize - NODE_SIZE; process && i >= 0; i -= NODE_SIZE) {
9196
index -= NODE_SIZE;
@@ -95,31 +100,31 @@ private void load(final String filename) throws IOException {
95100
m = k;
96101
} else {
97102
process = false;
98-
break;
99103
}
100104
}
101-
blockSize = (int) Math.min(BLOCK_SIZE, position);
105+
blockSize = BLOCK_SIZE;
102106
position = position - blockSize;
103107
}
104108
}
105109

106110
private float getFloatInAnnBuf(long pos) {
107-
int b = (int) Math.floor(((double) pos) / BLOCK_SIZE);
108-
int f = (int) (pos - (b * BLOCK_SIZE));
109-
return buffers.get(b).getFloat(f);
111+
int b = (int) pos / BLOCK_SIZE;
112+
int f = (int) pos % BLOCK_SIZE;
113+
return buffers[b].getFloat(f);
110114
}
111115

112116
private int getIntInAnnBuf(long pos) {
113-
int b = (int) Math.floor(((double) pos) / BLOCK_SIZE);
114-
int f = (int) (pos - (b * BLOCK_SIZE));
115-
return buffers.get(b).getInt(f);
117+
int b = (int) pos / BLOCK_SIZE;
118+
int i = (int) pos % BLOCK_SIZE;
119+
return buffers[b].getInt(i);
116120
}
117121

118122
@Override
119123
public void getNodeVector(final long nodeOffset, float[] v) {
124+
MappedByteBuffer nodeBuf = buffers[(int) nodeOffset / BLOCK_SIZE];
125+
int offset = (int) (nodeOffset % BLOCK_SIZE) + K_NODE_HEADER_STYLE;
120126
for (int i = 0; i < DIMENSION; i++) {
121-
long offSet = nodeOffset + K_NODE_HEADER_STYLE + i * FLOAT_SIZE;
122-
v[i] = getFloatInAnnBuf(offSet);
127+
v[i] = nodeBuf.getFloat(offset + i * FLOAT_SIZE);
123128
}
124129
}
125130

0 commit comments

Comments
 (0)