Java优先级队列实现-内存位置
作者:互联网
我正在尝试在Java中实现高效的优先级队列.我已经很好地实现了二进制堆,但是它没有理想的缓存性能.为此,我开始研究二进制堆中的Van Emde Boas布局,从而使我得到了二进制堆的“阻塞”版本,其中的诀窍是计运算符索引和父索引.
尽管我能够做到这一点,但缓存行为(和运行时间)变得更糟.我认为问题是:由于是Java,因此可能无法实现引用的局部性-我不确定使用对象数组是否实际上会使对象在Java内存中是连续的,请问有人可以确认吗?
我也非常想知道Java的本机PriorityQueue使用哪种数据结构,如果有的话.
解决方法:
通常,没有一种好的方法可以强制队列中的对象占用连续的内存块.但是,有些技术适用于特殊情况.
从高层次上讲,这些技术涉及使用字节数组以及将数据“串行化”到阵列或从阵列中“串行化”.如果要存储非常简单的对象,这实际上非常有效.例如,如果要存储一堆2D点权重,则只需编写等效于权重的字节(x坐标,y坐标)即可.
当然,此时的问题是在偷看/弹出时分配实例.您可以通过使用回调来避免这种情况.
请注意,即使在存储对象本身很复杂的情况下,也可以使用类似的技术,即为权重保留一个数组,为实际对象保留单独的引用数组,这样您可以避免在绝对必要之前遵循对象引用.
回到存储简单不变值类型的方法,这是您可以做的事情的不完整草图:
abstract class LowLevelPQ<T> {
interface DataHandler<R, T> {
R handle(byte[] source, int startLoc);
}
LowLevelPQ(int entryByteSize) { ... }
abstract encode(T element, byte[] target, int startLoc);
abstract T decode(byte[] source, int startLoc);
abstract int compare(byte[] data, int startLoc1, int startLoc2);
abstract <R> R peek(DataHandler<R, T> handler) { ... }
abstract <R> R pop(DataHandler<R, T> handler) { ... }
}
class WeightedPoint {
WeightedPoint(int weight, double x, double y) { ... }
double weight() { ... }
double x() { ... }
...
}
class WeightedPointPQ extends LowLevelPQ<WeightedPoint> {
WeightedPointPQ() {
super(4 + 8 + 8); // int,double,double
}
int compare(byte[] data, int startLoc1, int startLoc2) {
// relies on Java's big endian-ness
for (int i = 0; i < 4; ++i) {
int v1 = 0xFF & (int) data[startLoc1];
int v2 = 0xFF & (int) data[startLoc2];
if (v1 < v2) { return -1; }
if (v1 > v2) { return 1; }
}
return 0;
}
...
}
标签:priority-queue,heap,memory-management,java 来源: https://codeday.me/bug/20191102/1993892.html