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 文件加载到自托管服务器

无法在未调用 Looper.prepare() Graphhopper 的线程内创建处理程序

openstreetmap算路服务搭建

程序员越来越多内卷,是因为爱装X爱炫富。。。

程序员越来越多内卷,是因为爱装X爱炫富。。。

Dijkstra算法举例分析