我试图优化我在Android设备上运行的简单区域增长算法。最初我使用ArrayList
来保存属于一个地区的点。每个点都由一个Point
实例描述,该实例需要为每个点实例化。它采用算法大约15秒找到约100万像素的图像内的所有区域。为什么Java本地缓冲区速度很慢?
class Point
{
public int x, y;
}
我以为我可以通过减少Point
实例数量减少计算时间:为
的Point
类是那么简单。因此,我通过一个Region
类,利用了点争取本地缓存取代了点列表:
private int capacity;
private int pointsCount = 0;
private ByteBuffer buffer;
private IntBuffer intBufferView;
所需的字节的缓冲区大小的计算,基于点的数量:
private static int getByteBufferSize(int capacity)
{
// 4 bytes per integer and 2 integers per point
return capacity * 4 * 2;
}
的初始容量我选择为100,但我也尝试将其设置为10,这是ArrayList
的初始容量,我试图将其设置为我测试图像中最大区域的大小:
public Region()
{
this.capacity = 100;
this.buffer = ByteBuffer.allocateDirect(getByteBufferSize(100));
this.intBufferView = buffer.asIntBuffer();
}
对于添加点的区域I中使用这种方法:
public void add(final Point point)
{
if(pointsCount >= capacity)
{
grow();
}
final int offset = 2 * pointsCount;
intBufferView.put(offset + 0, point.x);
intBufferView.put(offset + 1, point.y);
++pointsCount;
}
和用于读取某一点时,通过索引来识别,这种方法:
public void fetchPoint(Point p, int pointIndex)
{
final int offset = 2 * pointIndex;
p.x = intBufferView.get(offset + 0);
p.y = intBufferView.get(offset + 1);
}
我实现生长策略等于所使用的ArrayList
政策:
private void grow()
{
capacity = (capacity * 3)/2 + 1;
final int bufferSize = getByteBufferSize(capacity);
final ByteBuffer newBuffer = ByteBuffer.allocateDirect(bufferSize);
newBuffer.put(buffer);
newBuffer.rewind();
buffer = newBuffer;
intBufferView = buffer.asIntBuffer();
}
然而,这种优化的区域增长算法会约33秒完成相同的图像。这是我无法解释的性能下降。这是我的执行,整个想法还是这里的问题?
我之前和ByteBuffer一起工作过,它不需要任何接近毫秒的地方(甚至可能接近几秒钟,就像在你的手机上一样),但是你仍然会看到一个下降。案例)检查你自己的算法 - 99.99%的问题会出现在那里,99.99%的时间会出现在你做的一些代码中** not **在这里发帖 –
我敢打赌你> 90所消耗时间的百分比(在显示的代码中)是s在成长中()。分配和复制数据是昂贵的部分。 – haraldK
为什么选择投票? – theV0ID