[英]Why are Java native buffers that slow?
我試圖優化在Android設備上運行的簡單區域增長算法。 最初,我使用ArrayList
來保存屬於一個區域的點。 每個點都由Point
實例描述,每個實例都需要實例化。 該算法花了大約15秒的時間才能找到圖像中約1兆像素的所有區域。
Point
類很簡單:
class Point
{
public int x, y;
}
我以為我可以通過減少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();
}
為了向該區域添加點,我使用了以下方法:
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秒才能完成同一張圖像。 這是我無法解釋的性能下降。 是我的實現,整個想法還是這里的問題?
坦白說,我認為整個想法都是錯誤的。 Buffer
類針對與您不同的用例進行了優化。 即在I / O設備之間來回傳輸數據(廣義上。
如果要獲得比當前更好的性能,請將Buffer
替換為int[]
。 我預計您會看到較小的性能下降(與ArrayList<Point>
版本相比),但是仍然會看到下降。 那就是您為節省內存而付出的代價。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.