Graphhopper Dijkstra 一对多内存错误
Posted
技术标签:
【中文标题】Graphhopper Dijkstra 一对多内存错误【英文标题】:Graphhopper Dijkstra One-To-Many Memory Error 【发布时间】:2017-03-23 21:01:38 【问题描述】:无论图表的大小和我使用的服务器如何,每当我尝试通过 dijkstra_one_to_many 算法进行路由时,都会溢出我的堆。测试环境是一个 m3.2xlarge,具有 30gb 的 RAM 和 2x80gb SSD 驱动器。
java.lang.OutOfMemoryError: Java heap space
我在 findEndNode 方法中找到了 com.graphhopper.routing.DijkstraOneToMany
内部的问题代码块:
while (true)
visitedNodes++;
EdgeIterator iter = outEdgeExplorer.setBaseNode(currNode);
while (iter.next())
int adjNode = iter.getAdjNode();
int prevEdgeId = edgeIds[adjNode];
if (!accept(iter, prevEdgeId))
continue;
double tmpWeight = weighting.calcWeight(iter, false, prevEdgeId) + weights[currNode];
if (Double.isInfinite(tmpWeight))
continue;
double w = weights[adjNode];
if (w == Double.MAX_VALUE)
parents[adjNode] = currNode;
weights[adjNode] = tmpWeight;
heap.insert_(tmpWeight, adjNode);
changedNodes.add(adjNode);
edgeIds[adjNode] = iter.getEdge();
else if (w > tmpWeight)
parents[adjNode] = currNode;
weights[adjNode] = tmpWeight;
heap.update_(tmpWeight, adjNode);
changedNodes.add(adjNode);
edgeIds[adjNode] = iter.getEdge();
if (heap.isEmpty() || isMaxVisitedNodesExceeded() || isWeightLimitExceeded())
return NOT_FOUND;
// calling just peek and not poll is important if the next query is cached
currNode = heap.peek_element();
if (finished())
return currNode;
heap.poll_element();
```
似乎永远找不到结束节点,内部数据结构(最小堆?)不断增长,直到我用完堆空间。为什么会这样?
如果需要,我也可以发布我的 config.properties。感谢 Peter 编写了一款很棒的开源软件。
【问题讨论】:
嗯,你试过增加你的堆空间吗? (图表有多大,当前堆大小是多少?)假设您的(未显示)isMaxVisitedNodesExceeded()
工作正常,您没有将heap
字段变量运行到无穷大...
我通过 jvm args 将堆大小设置为 27gb。北美pbf的图是4gb。也许我可以降低访问的最大节点数,但我认为我没有正确使用算法类。
【参考方案1】:
DijkstraOneToMany 类目前不打算(轻松)从外部使用,例如它不是线程安全的。您可以切换到没有不同完成条件的简单 Dijkstra 以降低简单案例的内存需求。
也就是说……可能存在以下问题:
确保缓存对 DijkstraOneToMany 的调用,因为它会创建大型初始数据结构 再次:仅在一个线程中使用它(例如通过 ThreadLocal) 似乎永远找不到结束节点 -> 也许你使用了 QueryGraph 呢?这不会真正起作用,因为我们在 QueryGraph 中创建 DijkstraOneToMany 不知道的所谓虚拟节点,而是尝试选择下一个塔节点,例如通过完全避免 QueryGraph 或通过 EdgeIterator 手动避免感谢 Peter 编写了一款很棒的开源软件。
这不仅仅是我 - 这是一个社区的努力:)!
【讨论】:
所以根据我的理解,听起来我的查询点可能会被捕捉到虚拟边缘,并且 DijkstraOneToMany 不断遍历基本图以寻找它一无所知的 ID? 是的。查询图将虚拟节点和边 ID 引入例如。避免在算法中对两个路口之间的位置进行特殊处理。以上是关于Graphhopper Dijkstra 一对多内存错误的主要内容,如果未能解决你的问题,请参考以下文章
GraphHopper:将多个 OSM 文件加载到自托管服务器