Skip to content

Commit 6da0e02

Browse files
committed
Remove QueryGraph cache, fix graphhopper#1768
1 parent 302882b commit 6da0e02

File tree

5 files changed

+15
-160
lines changed

5 files changed

+15
-160
lines changed

core/src/main/java/com/graphhopper/routing/AbstractBidirectionEdgeCHNoSOD.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,8 @@ public AbstractBidirectionEdgeCHNoSOD(Graph graph, TurnWeighting weighting) {
4747
// the inner explorers will run on the base- (or query/base-)graph edges only
4848
Graph baseGraph = graph.getBaseGraph();
4949
// we need extra edge explorers, because they get called inside a loop that already iterates over edges
50-
// important: we have to use different filter ids for the edge explorers here than we use for the edge
51-
// explorers in the superclass, otherwise this will not work with QueryGraph's edge explorer cache, see #1623.
52-
innerInExplorer = baseGraph.createEdgeExplorer(DefaultEdgeFilter.inEdges(flagEncoder).setFilterId(1));
53-
innerOutExplorer = baseGraph.createEdgeExplorer(DefaultEdgeFilter.outEdges(flagEncoder).setFilterId(1));
50+
innerInExplorer = baseGraph.createEdgeExplorer(DefaultEdgeFilter.inEdges(flagEncoder));
51+
innerOutExplorer = baseGraph.createEdgeExplorer(DefaultEdgeFilter.outEdges(flagEncoder));
5452
}
5553

5654
@Override

core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@
2222
import com.graphhopper.coll.GHIntObjectHashMap;
2323
import com.graphhopper.routing.util.AllEdgesIterator;
2424
import com.graphhopper.routing.util.EdgeFilter;
25-
import com.graphhopper.storage.*;
25+
import com.graphhopper.storage.ExtendedNodeAccess;
26+
import com.graphhopper.storage.Graph;
27+
import com.graphhopper.storage.NodeAccess;
28+
import com.graphhopper.storage.TurnCostExtension;
2629
import com.graphhopper.storage.index.QueryResult;
2730
import com.graphhopper.util.*;
2831
import com.graphhopper.util.shapes.BBox;
@@ -51,13 +54,11 @@ public class QueryGraph implements Graph {
5154
// todo: why do we need this and do we still need it when we stop wrapping CHGraph with QueryGraph ?
5255
private final QueryGraph baseGraph;
5356
private final TurnCostExtension wrappedExtension;
54-
private final Map<EdgeFilter, EdgeExplorer> cacheMap = new HashMap<>(4);
5557
private final NodeAccess nodeAccess;
5658
private final GraphModification graphModification;
5759

5860
// Use LinkedHashSet for predictable iteration order.
5961
private final Set<VirtualEdgeIteratorState> unfavoredEdges = new LinkedHashSet<>(5);
60-
private boolean useEdgeExplorerCache = false;
6162
private final IntObjectMap<List<EdgeIteratorState>> virtualEdgesAtRealNodes;
6263
private final List<List<EdgeIteratorState>> virtualEdgesAtVirtualNodes;
6364

@@ -93,14 +94,7 @@ private QueryGraph(Graph graph, List<QueryResult> queryResults) {
9394
virtualEdgesAtVirtualNodes = buildVirtualEdgesAtVirtualNodes();
9495

9596
// create very lightweight QueryGraph which uses variables from this QueryGraph (same virtual edges)
96-
baseGraph = new QueryGraph(graph.getBaseGraph(), this) {
97-
// override method to avoid stackoverflow
98-
@Override
99-
public QueryGraph setUseEdgeExplorerCache(boolean useEECache) {
100-
baseGraph.useEdgeExplorerCache = useEECache;
101-
return baseGraph;
102-
}
103-
};
97+
baseGraph = new QueryGraph(graph.getBaseGraph(), this);
10498
}
10599

106100
/**
@@ -138,20 +132,6 @@ public boolean isVirtualNode(int nodeId) {
138132
return nodeId >= mainNodes;
139133
}
140134

141-
/**
142-
* This method is an experimental feature to reduce memory and CPU resources if there are many
143-
* locations ("hundreds") for one QueryGraph. EdgeExplorer instances are cached based on the {@link EdgeFilter}
144-
* passed into {@link #createEdgeExplorer(EdgeFilter)}. For equal (in the java sense) {@link EdgeFilter}s always
145-
* the same {@link EdgeExplorer} will be returned when caching is enabled. Care has to be taken for example for
146-
* custom or threaded algorithms, when using custom {@link EdgeFilter}s, or when the same edge explorer is used
147-
* with different vehicles/encoders.
148-
*/
149-
public QueryGraph setUseEdgeExplorerCache(boolean useEECache) {
150-
this.useEdgeExplorerCache = useEECache;
151-
this.baseGraph.setUseEdgeExplorerCache(useEECache);
152-
return this;
153-
}
154-
155135
/**
156136
* Set those edges at the virtual node (nodeId) to 'unfavored' that require at least a turn of
157137
* 100° from favoredHeading.
@@ -307,19 +287,6 @@ private int getPosOfReverseEdge(int edgeId) {
307287

308288
@Override
309289
public EdgeExplorer createEdgeExplorer(final EdgeFilter edgeFilter) {
310-
if (useEdgeExplorerCache) {
311-
EdgeExplorer cached = cacheMap.get(edgeFilter);
312-
if (cached == null) {
313-
cached = createUncachedEdgeExplorer(edgeFilter);
314-
cacheMap.put(edgeFilter, cached);
315-
}
316-
return cached;
317-
} else {
318-
return createUncachedEdgeExplorer(edgeFilter);
319-
}
320-
}
321-
322-
private EdgeExplorer createUncachedEdgeExplorer(final EdgeFilter edgeFilter) {
323290
// re-use these objects between setBaseNode calls to prevent GC
324291
final EdgeExplorer mainExplorer = mainGraph.createEdgeExplorer(edgeFilter);
325292
final VirtualEdgeIterator virtualEdgeIterator = new VirtualEdgeIterator(edgeFilter, null);

core/src/main/java/com/graphhopper/routing/util/DefaultEdgeFilter.java

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,22 @@
2424
* @author Peter Karich
2525
*/
2626
public class DefaultEdgeFilter implements EdgeFilter {
27-
private static int DEFAULT_FILTER_ID = 0;
2827
private final boolean bwd;
2928
private final boolean fwd;
3029
private final BooleanEncodedValue accessEnc;
31-
/**
32-
* Used to be able to create non-equal filter instances with equal access encoder and fwd/bwd flags.
33-
*/
34-
private int filterId;
3530

36-
private DefaultEdgeFilter(BooleanEncodedValue accessEnc, boolean fwd, boolean bwd, int filterId) {
31+
private DefaultEdgeFilter(BooleanEncodedValue accessEnc, boolean fwd, boolean bwd) {
3732
this.accessEnc = accessEnc;
3833
this.fwd = fwd;
3934
this.bwd = bwd;
40-
this.filterId = filterId;
4135
}
4236

4337
public static DefaultEdgeFilter outEdges(BooleanEncodedValue accessEnc) {
44-
return new DefaultEdgeFilter(accessEnc, true, false, DEFAULT_FILTER_ID);
38+
return new DefaultEdgeFilter(accessEnc, true, false);
4539
}
4640

4741
public static DefaultEdgeFilter inEdges(BooleanEncodedValue accessEnc) {
48-
return new DefaultEdgeFilter(accessEnc, false, true, DEFAULT_FILTER_ID);
42+
return new DefaultEdgeFilter(accessEnc, false, true);
4943
}
5044

5145
/**
@@ -54,7 +48,7 @@ public static DefaultEdgeFilter inEdges(BooleanEncodedValue accessEnc) {
5448
* regardless of their encoding use {@link EdgeFilter#ALL_EDGES} instead.
5549
*/
5650
public static DefaultEdgeFilter allEdges(BooleanEncodedValue accessEnc) {
57-
return new DefaultEdgeFilter(accessEnc, true, true, DEFAULT_FILTER_ID);
51+
return new DefaultEdgeFilter(accessEnc, true, true);
5852
}
5953

6054
public static DefaultEdgeFilter outEdges(FlagEncoder flagEncoder) {
@@ -69,11 +63,6 @@ public static DefaultEdgeFilter allEdges(FlagEncoder flagEncoder) {
6963
return DefaultEdgeFilter.allEdges(flagEncoder.getAccessEnc());
7064
}
7165

72-
public DefaultEdgeFilter setFilterId(int filterId) {
73-
this.filterId = filterId;
74-
return this;
75-
}
76-
7766
public BooleanEncodedValue getAccessEnc() {
7867
return accessEnc;
7968
}
@@ -104,7 +93,6 @@ public boolean equals(Object o) {
10493

10594
if (bwd != that.bwd) return false;
10695
if (fwd != that.fwd) return false;
107-
if (filterId != that.filterId) return false;
10896
return accessEnc.equals(that.accessEnc);
10997
}
11098

@@ -113,7 +101,6 @@ public int hashCode() {
113101
int result = (bwd ? 1 : 0);
114102
result = 31 * result + (fwd ? 1 : 0);
115103
result = 31 * result + accessEnc.hashCode();
116-
result = 31 * result + filterId;
117104
return result;
118105
}
119106
}

core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -894,42 +894,6 @@ public void test_issue_1593_simple() {
894894
assertFalse("no path should be found, but found " + path.calcNodes(), path.isFound());
895895
}
896896

897-
@Test
898-
public void test_issue_1623_query_graph_cache() {
899-
// 4-2->5-3
900-
NodeAccess na = graph.getNodeAccess();
901-
na.setNode(0, 49.408550, 9.701805);
902-
na.setNode(1, 49.405988, 9.706111);
903-
na.setNode(2, 49.400772, 9.706245);
904-
na.setNode(3, 49.403167, 9.704774);
905-
na.setNode(4, 49.405817, 9.704301);
906-
na.setNode(5, 49.402488, 9.707799);
907-
graph.edge(2, 5, 222.771000, false);
908-
graph.edge(4, 2, 583.496000, true);
909-
graph.edge(3, 5, 231.495000, true);
910-
graph.freeze();
911-
912-
RoutingAlgorithmFactory pch = automaticPrepareCH();
913-
LocationIndexTree index = new LocationIndexTree(graph, new RAMDirectory());
914-
index.prepareIndex();
915-
QueryResult qr1 = index.findClosest(49.400772, 9.706245, EdgeFilter.ALL_EDGES);
916-
QueryResult qr2 = index.findClosest(49.403167, 9.704774, EdgeFilter.ALL_EDGES);
917-
QueryGraph queryGraph = QueryGraph.lookup(chGraph, qr1, qr2);
918-
919-
// before fixing #1623 this test only worked for a disabled edge explorer cache
920-
queryGraph.setUseEdgeExplorerCache(true);
921-
922-
assertEquals(2, qr1.getClosestNode());
923-
assertEquals(3, qr2.getClosestNode());
924-
RoutingAlgorithm chAlgo = pch.createAlgo(queryGraph, AlgorithmOptions.start()
925-
.traversalMode(TraversalMode.EDGE_BASED)
926-
.build());
927-
Path path = chAlgo.calcPath(2, 3);
928-
assertTrue("no path found", path.isFound());
929-
assertEquals(IntArrayList.from(2, 5, 3), path.calcNodes());
930-
assertEquals(454.266, path.getDistance(), 1.e-1);
931-
}
932-
933897
@Test
934898
public void testRouteViaVirtualNode() {
935899
// 3

core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java

Lines changed: 4 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@
3333
import org.junit.Before;
3434
import org.junit.Test;
3535

36-
import java.util.*;
36+
import java.util.Arrays;
37+
import java.util.Collections;
38+
import java.util.LinkedHashSet;
39+
import java.util.List;
3740

3841
import static com.graphhopper.storage.index.QueryResult.Position.*;
3942
import static com.graphhopper.util.GHUtility.updateDistancesFor;
@@ -654,70 +657,6 @@ public void testInternalAPIOriginalEdgeKey() {
654657
((VirtualEdgeIteratorState) queryGraph.getEdgeIteratorState(iter.getEdge(), 1)).getOriginalEdgeKey());
655658
}
656659

657-
@Test
658-
public void useEECache() {
659-
initGraph(g);
660-
EdgeExplorer explorer = g.createEdgeExplorer();
661-
EdgeIterator iter = explorer.setBaseNode(1);
662-
assertTrue(iter.next());
663-
QueryResult res = createLocationResult(2, 1.5, iter, 1, PILLAR);
664-
665-
QueryGraph queryGraph = lookup(res);
666-
queryGraph.setUseEdgeExplorerCache(true);
667-
668-
EdgeExplorer edgeExplorer = queryGraph.createEdgeExplorer();
669-
// using cache means same reference
670-
assertSame(edgeExplorer, queryGraph.createEdgeExplorer());
671-
}
672-
673-
@Test
674-
public void useEECache_nestedLoop() {
675-
//
676-
// 0->3
677-
// |\
678-
// 1 2->6
679-
// |\
680-
// 4 5
681-
g.edge(0, 1, 10, false);
682-
g.edge(0, 2, 10, false);
683-
g.edge(0, 3, 10, false);
684-
g.edge(2, 4, 10, false);
685-
g.edge(2, 5, 10, false);
686-
g.edge(2, 6, 10, false);
687-
688-
EdgeExplorer explorer = g.createEdgeExplorer();
689-
EdgeIterator iter = explorer.setBaseNode(0);
690-
assertTrue(iter.next());
691-
QueryResult res = createLocationResult(0, 0, iter, 1, PILLAR);
692-
693-
QueryGraph queryGraph = lookup(Collections.singletonList(res));
694-
queryGraph.setUseEdgeExplorerCache(true);
695-
696-
EdgeExplorer outerEdgeExplorer = queryGraph.createEdgeExplorer(DefaultEdgeFilter.outEdges(carEncoder));
697-
EdgeExplorer innerEdgeExplorer = queryGraph.createEdgeExplorer(DefaultEdgeFilter.outEdges(carEncoder));
698-
699-
// without using filter id for DefaultEdgeFilter the filters are equal and using the explorers in a nested
700-
// loop would fail
701-
assertSame(outerEdgeExplorer, innerEdgeExplorer);
702-
703-
// using a different filter id for the second filter we get different explorers
704-
outerEdgeExplorer = queryGraph.createEdgeExplorer(DefaultEdgeFilter.outEdges(carEncoder));
705-
innerEdgeExplorer = queryGraph.createEdgeExplorer(DefaultEdgeFilter.outEdges(carEncoder).setFilterId(1));
706-
assertNotSame(outerEdgeExplorer, innerEdgeExplorer);
707-
708-
// now we can safely use the two explorers in a nested loop
709-
Set<String> edges = new HashSet<>();
710-
EdgeIterator outerIter = outerEdgeExplorer.setBaseNode(0);
711-
while (outerIter.next()) {
712-
edges.add("o" + outerIter.getBaseNode() + "-" + outerIter.getAdjNode());
713-
EdgeIterator innerIter = innerEdgeExplorer.setBaseNode(outerIter.getAdjNode());
714-
while (innerIter.next()) {
715-
edges.add("i" + innerIter.getBaseNode() + "-" + innerIter.getAdjNode());
716-
}
717-
}
718-
assertEquals(new HashSet<>(Arrays.asList("o0-1", "o0-2", "o0-3", "i2-4", "i2-5", "i2-6")), edges);
719-
}
720-
721660
@Test
722661
public void testWayGeometry_edge() {
723662
// drawn as horizontal linear graph for simplicity

0 commit comments

Comments
 (0)