我在 Java 中实现了一个 GapBuffer 列表,但我不知道为什么它会受到这样的性能损失。用 C# 编写的类似代码的行为符合预期:插入到列表中间比 C# 的 List 实现快得多。但是 Java 版本的行为很奇怪。
以下是一些基准测试信息:
Adding/removing 10,000,000 items @ the end of the dynamic array...
ArrayList: 683 milliseconds
GapBufferList: 416 milliseconds
Adding/removing 100,000 items @ a random spot in the dynamic array...
- ArrayList add: 721 milliseconds
- ArrayList remove: 612 milliseconds
ArrayList: 1333 milliseconds
- GapBufferList add: 1293 milliseconds
- GapBufferList remove: 2775 milliseconds
GapBufferList: 4068 milliseconds
Adding/removing 100,000 items @ the beginning of the dynamic array...
ArrayList: 2422 milliseconds
GapBufferList: 13 milliseconds
Clearly, the GapBufferList is the better option.
如您所见,当您插入到列表的开头时,间隙缓冲区的行为与预期一样:它比 ArrayList 好很多、很多、很多倍。但是,当在列表中的随机位置插入和删除时,间隙缓冲区有一个奇怪的性能损失,我无法解释。更奇怪的是,从 GapBufferList 中删除项目比添加项目要慢 - 根据我到目前为止运行的每个测试,删除项目所需的时间大约是添加项目的三倍,尽管事实上他们的代码几乎相同:
@Override
public void add(int index, T t)
{
if (index < 0 || index > back.length - gapSize) throw new IndexOutOfBoundsException();
if (gapPos > index)
{
int diff = gapPos - index;
for (int q = 1; q <= diff; q++)
back[gapPos - q + gapSize] = back[gapPos - q];
}
else if (index > gapPos)
{
int diff = gapPos - index;
for (int q = 0; q < diff; q++)
back[gapPos + q] = back[gapPos + gapSize + q];
}
gapPos = index;
if (gapSize == 0) increaseSize();
back[gapPos++] = t; gapSize--;
}
@Override
public T remove(int index)
{
if (index < 0 || index >= back.length - gapSize) throw new IndexOutOfBoundsException();
if (gapPos > index + 1)
{
int diff = gapPos - (index + 1);
for (int q = 1; q <= diff; q++)
back[gapPos - q + gapSize] = back[gapPos - q];
}
else
{
int diff = (index + 1) - gapPos;
for (int q = 0; q < diff; q++)
back[gapPos + q] = back[gapPos + gapSize + q];
}
gapSize++;
return back[gapPos = index];
}
间隙缓冲区的代码可以在这里找到,基准入口点的代码可以在这里找到。(您可以用 替换任何引用Flow.***Exception
。RuntimeException
)