Repository: graphhopper/graphhopper
Pull request #1945 (2020-03-04 18:53:30)

Clean up TurnCostStorage
TurnCostStorage had several layers of read/write methods. To me, it looked like the class couldn't make up its mind if its IntRefs/Encoders should work the same way as for edges, or not. And then got stuck in the middle.

I just removed everything except *one* way of accessing it, namely the one that is used in production code. And adapted all the tests.


Patch:
diff --git a/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java b/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java
index f0a634958..8a633b133 100644
--- a/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java
+++ b/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java
@@ -599,7 +599,7 @@ public class EncodingManager implements EncodedValueLookup {
 
     public void handleTurnRelationTags(OSMTurnRelation turnRelation, TurnCostParser.ExternalInternalMap map, Graph graph) {
         for (TurnCostParser parser : turnCostParsers.values()) {
-            parser.handleTurnRelationTags(TurnCost.createFlags(), turnRelation, map, graph);
+            parser.handleTurnRelationTags(turnRelation, map, graph);
         }
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParser.java b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParser.java
index 7bcb8ec23..9211eebab 100644
--- a/core/src/main/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParser.java
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParser.java
@@ -21,7 +21,6 @@ import com.graphhopper.reader.OSMTurnRelation;
 import com.graphhopper.routing.profiles.*;
 import com.graphhopper.routing.util.DefaultEdgeFilter;
 import com.graphhopper.storage.Graph;
-import com.graphhopper.storage.IntsRef;
 import com.graphhopper.storage.TurnCostStorage;
 import com.graphhopper.util.EdgeExplorer;
 import com.graphhopper.util.EdgeIterator;
@@ -85,11 +84,11 @@ public class OSMTurnRelationParser implements TurnCostParser {
     }
 
     @Override
-    public void handleTurnRelationTags(IntsRef turnCostFlags, OSMTurnRelation turnRelation, ExternalInternalMap map, Graph graph) {
+    public void handleTurnRelationTags(OSMTurnRelation turnRelation, ExternalInternalMap map, Graph graph) {
         if (!turnRelation.isVehicleTypeConcernedByTurnRestriction(restrictions))
             return;
 
-        addRelationToTCStorage(turnRelation, turnCostFlags, map, graph);
+        addRelationToTCStorage(turnRelation, map, graph);
     }
 
     private EdgeExplorer getInExplorer(Graph graph) {
@@ -103,7 +102,7 @@ public class OSMTurnRelationParser implements TurnCostParser {
     /**
      * Add the specified relation to the TurnCostStorage
      */
-    void addRelationToTCStorage(OSMTurnRelation osmTurnRelation, IntsRef turnCostFlags,
+    void addRelationToTCStorage(OSMTurnRelation osmTurnRelation,
                                 ExternalInternalMap map, Graph graph) {
         TurnCostStorage tcs = graph.getTurnCostStorage();
         int viaNode = map.getInternalNodeIdOfOsmNode(osmTurnRelation.getViaOsmNodeId());
@@ -134,7 +133,7 @@ public class OSMTurnRelationParser implements TurnCostParser {
                 long wayId = map.getOsmIdOfInternalEdge(edgeId);
                 if (edgeId != edgeIdFrom && osmTurnRelation.getRestriction() == OSMTurnRelation.Type.ONLY && wayId != osmTurnRelation.getOsmIdTo()
                         || osmTurnRelation.getRestriction() == OSMTurnRelation.Type.NOT && wayId == osmTurnRelation.getOsmIdTo() && wayId >= 0) {
-                    tcs.set(turnCostEnc, turnCostFlags, edgeIdFrom, viaNode, iter.getEdge(), Double.POSITIVE_INFINITY);
+                    tcs.set(turnCostEnc, edgeIdFrom, viaNode, iter.getEdge(), Double.POSITIVE_INFINITY);
                     if (osmTurnRelation.getRestriction() == OSMTurnRelation.Type.NOT)
                         break;
                 }
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/TurnCostParser.java b/core/src/main/java/com/graphhopper/routing/util/parsers/TurnCostParser.java
index e3ce9c8db..a77f1b471 100644
--- a/core/src/main/java/com/graphhopper/routing/util/parsers/TurnCostParser.java
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/TurnCostParser.java
@@ -21,7 +21,6 @@ import com.graphhopper.reader.OSMTurnRelation;
 import com.graphhopper.routing.profiles.EncodedValue;
 import com.graphhopper.routing.profiles.EncodedValueLookup;
 import com.graphhopper.storage.Graph;
-import com.graphhopper.storage.IntsRef;
 
 import java.util.List;
 
@@ -34,7 +33,7 @@ public interface TurnCostParser {
 
     void createTurnCostEncodedValues(EncodedValueLookup lookup, List<EncodedValue> registerNewEncodedValue);
 
-    void handleTurnRelationTags(IntsRef turnCostFlags, OSMTurnRelation turnRelation, ExternalInternalMap map, Graph graph);
+    void handleTurnRelationTags(OSMTurnRelation turnRelation, ExternalInternalMap map, Graph graph);
 
     /**
      * This map associates the internal GraphHopper nodes IDs with external IDs (OSM) and similarly for the edge IDs
diff --git a/core/src/main/java/com/graphhopper/routing/weighting/DefaultTurnCostProvider.java b/core/src/main/java/com/graphhopper/routing/weighting/DefaultTurnCostProvider.java
index bf7a649b6..8564d8710 100644
--- a/core/src/main/java/com/graphhopper/routing/weighting/DefaultTurnCostProvider.java
+++ b/core/src/main/java/com/graphhopper/routing/weighting/DefaultTurnCostProvider.java
@@ -21,7 +21,6 @@ package com.graphhopper.routing.weighting;
 import com.graphhopper.routing.profiles.DecimalEncodedValue;
 import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.FlagEncoder;
-import com.graphhopper.storage.IntsRef;
 import com.graphhopper.storage.TurnCostStorage;
 import com.graphhopper.util.EdgeIterator;
 
@@ -62,12 +61,12 @@ public class DefaultTurnCostProvider implements TurnCostProvider {
             return 0;
         }
         double tCost = 0;
-        if (turnCostStorage.isUTurn(edgeFrom, edgeTo)) {
+        if (edgeFrom == edgeTo) {
             // note that the u-turn costs overwrite any turn costs set in TurnCostStorage
-            tCost = turnCostStorage.isUTurnAllowed(nodeVia) ? uTurnCosts : Double.POSITIVE_INFINITY;
+            tCost = true ? uTurnCosts : Double.POSITIVE_INFINITY;
         } else {
             if (turnCostEnc != null)
-                tCost = turnCostStorage.get(turnCostEnc, TurnCost.createFlags(), edgeFrom, nodeVia, edgeTo);
+                tCost = turnCostStorage.get(turnCostEnc, edgeFrom, nodeVia, edgeTo);
         }
         return tCost;
     }
diff --git a/core/src/main/java/com/graphhopper/storage/TurnCostStorage.java b/core/src/main/java/com/graphhopper/storage/TurnCostStorage.java
index d2c123801..236adf8f3 100644
--- a/core/src/main/java/com/graphhopper/storage/TurnCostStorage.java
+++ b/core/src/main/java/com/graphhopper/storage/TurnCostStorage.java
@@ -18,12 +18,9 @@
 package com.graphhopper.storage;
 
 import com.graphhopper.routing.profiles.DecimalEncodedValue;
-import com.graphhopper.routing.profiles.EncodedValueLookup;
 import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.util.EdgeIterator;
 
-import static com.graphhopper.routing.util.EncodingManager.getKey;
-
 /**
  * Holds turn cost tables for each node. The additional field of a node will be used to point towards the
  * first entry within a node cost table to identify turn restrictions or turn costs.
@@ -95,42 +92,19 @@ public class TurnCostStorage implements Storable<TurnCostStorage> {
         return true;
     }
 
-    /**
-     * This is a convenient setter method and should not be used in loops or where speed is important.
-     */
-    public void setExpensive(String name, EncodedValueLookup lookup, int fromEdge, int viaNode, int toEdge, double cost) {
-        set(lookup.getDecimalEncodedValue(TurnCost.key(name)), TurnCost.createFlags(), fromEdge, viaNode, toEdge, cost);
-    }
-
     /**
      * Sets the turn cost at the viaNode when going from "fromEdge" to "toEdge"
+     * WARNING: It is tacitly assumed that for every encoder, this method is only called once per turn relation.
+     * Subsequent calls for the same encoder and the same turn relation will have undefined results.
+     * (The implementation below ORs the new bits into the existing bits.)
      */
-    public void set(DecimalEncodedValue turnCostEnc, IntsRef tcFlags, int fromEdge, int viaNode, int toEdge, double cost) {
-        // reset is required as we could have read a value for other vehicles before (that was changed in the meantime) that we would overwrite
-        tcFlags.ints[0] = 0;
+    public void set(DecimalEncodedValue turnCostEnc, int fromEdge, int viaNode, int toEdge, double cost) {
+        IntsRef tcFlags = TurnCost.createFlags();
         turnCostEnc.setDecimal(false, tcFlags, cost);
-        setTurnCost(tcFlags, fromEdge, viaNode, toEdge);
+        merge(tcFlags, fromEdge, viaNode, toEdge);
     }
 
-    /**
-     * Add an entry which is a turn restriction or cost information via the turnFlags. Overwrite existing information
-     * if it is the same edges and node.
-     *
-     * @param fromEdge edge ID
-     * @param viaNode  node ID
-     * @param toEdge   edge ID
-     * @param tcFlags  flags to be written
-     */
-    public void setTurnCost(IntsRef tcFlags, int fromEdge, int viaNode, int toEdge) {
-        if (tcFlags.length != 1)
-            throw new IllegalArgumentException("Cannot use IntsRef with length != 1");
-        if (tcFlags.ints[0] == 0)
-            return;
-
-        setOrMerge(tcFlags, fromEdge, viaNode, toEdge, true);
-    }
-
-    void setOrMerge(IntsRef tcFlags, int fromEdge, int viaNode, int toEdge, boolean merge) {
+    private void merge(IntsRef tcFlags, int fromEdge, int viaNode, int toEdge) {
         int newEntryIndex = turnCostsCount;
         ensureTurnCostIndex(newEntryIndex);
         boolean oldEntryFound = false;
@@ -168,10 +142,8 @@ public class TurnCostStorage implements Storable<TurnCostStorage> {
             if (!oldEntryFound) {
                 // set next-pointer to this new cost entry
                 turnCosts.setInt((long) previousEntryIndex * BYTES_PER_ENTRY + TC_NEXT, newEntryIndex);
-            } else if (merge) {
-                newFlags = existingFlags | newFlags;
             } else {
-                // overwrite!
+                newFlags = existingFlags | newFlags;
             }
         }
         long costsBase; // where to (over)write
@@ -187,42 +159,29 @@ public class TurnCostStorage implements Storable<TurnCostStorage> {
         turnCosts.setInt(costsBase + TC_NEXT, next);
     }
 
-    /**
-     * This is a convenient getter method and should not be used in loops or where speed is important.
-     */
-    public double getExpensive(String name, EncodedValueLookup lookup, int fromEdge, int viaNode, int toEdge) {
-        return get(lookup.getDecimalEncodedValue(TurnCost.key(name)), TurnCost.createFlags(), fromEdge, viaNode, toEdge);
-    }
-
     /**
      * @return the turn cost of the viaNode when going from "fromEdge" to "toEdge"
      */
-    public double get(DecimalEncodedValue turnCostEnc, IntsRef tcFlags, int fromEdge, int viaNode, int toEdge) {
-        return turnCostEnc.getDecimal(false, readFlags(tcFlags, fromEdge, viaNode, toEdge));
+    public double get(DecimalEncodedValue turnCostEnc, int fromEdge, int viaNode, int toEdge) {
+        IntsRef flags = readFlags(fromEdge, viaNode, toEdge);
+        return turnCostEnc.getDecimal(false, flags);
     }
 
     /**
      * @return turn cost flags of the specified triple "from edge", "via node" and "to edge"
      */
-    private IntsRef readFlags(IntsRef tcFlags, int fromEdge, int viaNode, int toEdge) {
+    private IntsRef readFlags(int fromEdge, int viaNode, int toEdge) {
         if (!EdgeIterator.Edge.isValid(fromEdge) || !EdgeIterator.Edge.isValid(toEdge))
             throw new IllegalArgumentException("from and to edge cannot be NO_EDGE");
         if (viaNode < 0)
             throw new IllegalArgumentException("via node cannot be negative");
 
-        nextCostFlags(tcFlags, fromEdge, viaNode, toEdge);
-        return tcFlags;
-    }
-
-    public boolean isUTurn(int edgeFrom, int edgeTo) {
-        return edgeFrom == edgeTo;
-    }
-
-    public boolean isUTurnAllowed(int node) {
-        return true;
+        IntsRef flags = TurnCost.createFlags();
+        readFlags(flags, fromEdge, viaNode, toEdge);
+        return flags;
     }
 
-    private void nextCostFlags(IntsRef tcFlags, int fromEdge, int viaNode, int toEdge) {
+    private void readFlags(IntsRef tcFlags, int fromEdge, int viaNode, int toEdge) {
         int turnCostIndex = nodeAccess.getTurnCostIndex(viaNode);
         int i = 0;
         for (; i < 1000; i++) {
diff --git a/core/src/main/java/com/graphhopper/util/GHUtility.java b/core/src/main/java/com/graphhopper/util/GHUtility.java
index 92eea753e..0481d0a53 100644
--- a/core/src/main/java/com/graphhopper/util/GHUtility.java
+++ b/core/src/main/java/com/graphhopper/util/GHUtility.java
@@ -234,7 +234,6 @@ public class GHUtility {
         DecimalEncodedValue turnCostEnc = em.getDecimalEncodedValue(TurnCost.key(encoder.toString()));
         EdgeExplorer inExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.inEdges(encoder));
         EdgeExplorer outExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.outEdges(encoder));
-        IntsRef tcFlags = TurnCost.createFlags();
         for (int node = 0; node < graph.getNodes(); ++node) {
             if (random.nextDouble() < pNodeHasTurnCosts) {
                 EdgeIterator inIter = inExplorer.setBaseNode(node);
@@ -247,7 +246,7 @@ public class GHUtility {
                         }
                         if (random.nextDouble() < pEdgePairHasTurnCosts) {
                             double cost = random.nextDouble() < pCostIsRestriction ? Double.POSITIVE_INFINITY : random.nextDouble() * maxTurnCost;
-                            turnCostStorage.set(turnCostEnc, tcFlags, inIter.getEdge(), node, outIter.getEdge(), cost);
+                            turnCostStorage.set(turnCostEnc, inIter.getEdge(), node, outIter.getEdge(), cost);
                         }
                     }
                 }


Test patch:
diff --git a/core/src/test/java/com/graphhopper/routing/BidirPathExtractorTest.java b/core/src/test/java/com/graphhopper/routing/BidirPathExtractorTest.java
index 773b85a7d..3d33e5560 100644
--- a/core/src/test/java/com/graphhopper/routing/BidirPathExtractorTest.java
+++ b/core/src/test/java/com/graphhopper/routing/BidirPathExtractorTest.java
@@ -65,9 +65,7 @@ public class BidirPathExtractorTest {
         // weight and the time of the path
         TurnCostStorage turnCostStorage = g.getTurnCostStorage();
         DecimalEncodedValue turnCostEnc = encodingManager.getDecimalEncodedValue(TurnCost.key(carEncoder.toString()));
-        IntsRef tcFlags = TurnCost.createFlags();
-        turnCostEnc.setDecimal(false, tcFlags, 5);
-        turnCostStorage.setTurnCost(tcFlags, 0, 2, 1);
+        turnCostStorage.set(turnCostEnc, 0, 2, 1, 5);
 
         SPTEntry fwdEntry = new SPTEntry(0, 2, 0.6);
         fwdEntry.parent = new SPTEntry(EdgeIterator.NO_EDGE, 1, 0);
diff --git a/core/src/test/java/com/graphhopper/routing/CHQueryWithTurnCostsTest.java b/core/src/test/java/com/graphhopper/routing/CHQueryWithTurnCostsTest.java
index bc456d80d..604c5c768 100644
--- a/core/src/test/java/com/graphhopper/routing/CHQueryWithTurnCostsTest.java
+++ b/core/src/test/java/com/graphhopper/routing/CHQueryWithTurnCostsTest.java
@@ -20,14 +20,13 @@ package com.graphhopper.routing;
 
 import com.carrotsearch.hppc.IntArrayList;
 import com.graphhopper.routing.ch.PrepareEncoder;
+import com.graphhopper.routing.profiles.EncodedValueLookup;
+import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.routing.util.MotorcycleFlagEncoder;
 import com.graphhopper.routing.weighting.Weighting;
-import com.graphhopper.storage.CHGraph;
-import com.graphhopper.storage.GraphBuilder;
-import com.graphhopper.storage.GraphHopperStorage;
-import com.graphhopper.storage.RoutingCHGraphImpl;
+import com.graphhopper.storage.*;
 import com.graphhopper.util.EdgeIteratorState;
 import com.graphhopper.util.GHUtility;
 import org.junit.Test;
@@ -731,8 +730,7 @@ public class CHQueryWithTurnCostsTest {
     }
 
     private void setTurnCost(EdgeIteratorState edge1, EdgeIteratorState edge2, int viaNode, double costs) {
-        graph.getTurnCostStorage().setExpensive(encoder.toString(), encodingManager,
-                edge1.getEdge(), viaNode, edge2.getEdge(), costs);
+        graph.getTurnCostStorage().set(((EncodedValueLookup) encodingManager).getDecimalEncodedValue(TurnCost.key(encoder.toString())), edge1.getEdge(), viaNode, edge2.getEdge(), costs);
     }
 
     private void setRestriction(int from, int via, int to) {
diff --git a/core/src/test/java/com/graphhopper/routing/DirectedBidirectionalDijkstraTest.java b/core/src/test/java/com/graphhopper/routing/DirectedBidirectionalDijkstraTest.java
index b40748f81..37e1e7c13 100644
--- a/core/src/test/java/com/graphhopper/routing/DirectedBidirectionalDijkstraTest.java
+++ b/core/src/test/java/com/graphhopper/routing/DirectedBidirectionalDijkstraTest.java
@@ -248,11 +248,11 @@ public class DirectedBidirectionalDijkstraTest {
         int leftNorth = graph.edge(9, 0, 1, true).getEdge();
 
         // make paths fully deterministic by applying some turn costs at junction node 2
-        setTurnCost(7, 2, 3, 1);
-        setTurnCost(7, 2, 6, 3);
-        setTurnCost(1, 2, 3, 5);
-        setTurnCost(1, 2, 6, 7);
-        setTurnCost(1, 2, 7, 9);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 7, 2).getEdge(), 2, GHUtility.getEdge(graph, 2, 3).getEdge(), 1);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 7, 2).getEdge(), 2, GHUtility.getEdge(graph, 2, 6).getEdge(), 3);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 1, 2).getEdge(), 2, GHUtility.getEdge(graph, 2, 3).getEdge(), 5);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 1, 2).getEdge(), 2, GHUtility.getEdge(graph, 2, 6).getEdge(), 7);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 1, 2).getEdge(), 2, GHUtility.getEdge(graph, 2, 7).getEdge(), 9);
 
         final double unitEdgeWeight = 0.06;
         assertPath(calcPath(9, 9, leftNorth, leftSouth),
@@ -322,8 +322,8 @@ public class DirectedBidirectionalDijkstraTest {
         graph.edge(4, 5, 1, true);
         graph.edge(5, 2, 1, true);
 
-        addRestriction(0, 3, 4);
-        setTurnCost(4, 5, 2, 6);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 0, 3).getEdge(), 3, GHUtility.getEdge(graph, 3, 4).getEdge(), Double.POSITIVE_INFINITY);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 4, 5).getEdge(), 5, GHUtility.getEdge(graph, 5, 2).getEdge(), 6);
 
         // due to the restrictions we have to take the expensive path with turn costs
         assertPath(calcPath(0, 2, 0, 6), 6.24, 4, 6240, nodes(0, 1, 4, 5, 2));
@@ -356,8 +356,8 @@ public class DirectedBidirectionalDijkstraTest {
         int right6 = graph.edge(9, 6, 10, true).getEdge();
 
         // enforce p-turn (using the loop in clockwise direction)
-        addRestriction(0, 1, 6);
-        addRestriction(5, 4, 3);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 0, 1).getEdge(), 1, GHUtility.getEdge(graph, 1, 6).getEdge(), Double.POSITIVE_INFINITY);
+        turnCostStorage.set(turnCostEnc, GHUtility.getEdge(graph, 5, 4).getEdge(), 4, GHUtility.getEdge(graph, 4, 3).getEdge(), Double.POSITIVE_INFINITY);
 
         assertPath(calcPath(0, 6, right0, left6), 64.2, 1070, 64200, nodes(0, 1, 2, 3, 4, 5, 2, 1, 6));
         // if the u-turn cost is finite it depends on its value if we rather do the p-turn or do an immediate u-turn at node 2
@@ -515,27 +515,6 @@ public class DirectedBidirectionalDijkstraTest {
         return new DijkstraBidirectionRef(graph, weighting, TraversalMode.EDGE_BASED);
     }
 
-    private void addRestriction(int fromNode, int node, int toNode) {
-        IntsRef tcFlags = TurnCost.createFlags();
-        turnCostEnc.setDecimal(false, tcFlags, Double.POSITIVE_INFINITY);
-        turnCostStorage.setTurnCost(
-                tcFlags,
-                GHUtility.getEdge(graph, fromNode, node).getEdge(),
-                node,
-                GHUtility.getEdge(graph, node, toNode).getEdge()
-        );
-    }
-
-    private void setTurnCost(int fromNode, int node, int toNode, double turnCost) {
-        IntsRef tcFlags = TurnCost.createFlags();
-        turnCostEnc.setDecimal(false, tcFlags, turnCost);
-        turnCostStorage.setTurnCost(
-                tcFlags,
-                GHUtility.getEdge(graph, fromNode, node).getEdge(),
-                node,
-                GHUtility.getEdge(graph, node, toNode).getEdge());
-    }
-
     private IntArrayList nodes(int... nodes) {
         return IntArrayList.from(nodes);
     }
diff --git a/core/src/test/java/com/graphhopper/routing/EdgeBasedRoutingAlgorithmTest.java b/core/src/test/java/com/graphhopper/routing/EdgeBasedRoutingAlgorithmTest.java
index 79b856258..9caadd861 100644
--- a/core/src/test/java/com/graphhopper/routing/EdgeBasedRoutingAlgorithmTest.java
+++ b/core/src/test/java/com/graphhopper/routing/EdgeBasedRoutingAlgorithmTest.java
@@ -19,6 +19,8 @@ package com.graphhopper.routing;
 
 import com.carrotsearch.hppc.IntArrayList;
 import com.carrotsearch.hppc.cursors.IntCursor;
+import com.graphhopper.routing.profiles.EncodedValueLookup;
+import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.CarFlagEncoder;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.routing.util.FlagEncoder;
@@ -458,7 +460,6 @@ public class EdgeBasedRoutingAlgorithmTest {
     }
 
     private void setTurnCost(GraphHopperStorage g, double cost, int from, int via, int to) {
-        g.getTurnCostStorage().setExpensive(carEncoder.toString(), g.getEncodingManager(),
-                getEdge(g, from, via).getEdge(), via, getEdge(g, via, to).getEdge(), cost);
+        g.getTurnCostStorage().set(((EncodedValueLookup) g.getEncodingManager()).getDecimalEncodedValue(TurnCost.key(carEncoder.toString())), getEdge(g, from, via).getEdge(), via, getEdge(g, via, to).getEdge(), cost);
     }
 }
diff --git a/core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java b/core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java
index 21f7ccf88..5a4395c66 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/CHTurnCostTest.java
@@ -21,6 +21,8 @@ import com.carrotsearch.hppc.IntArrayList;
 import com.graphhopper.Repeat;
 import com.graphhopper.RepeatRule;
 import com.graphhopper.routing.*;
+import com.graphhopper.routing.profiles.EncodedValueLookup;
+import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.querygraph.QueryGraph;
 import com.graphhopper.routing.util.*;
 import com.graphhopper.routing.weighting.DefaultTurnCostProvider;
@@ -1221,7 +1223,7 @@ public class CHTurnCostTest {
     }
 
     private void setRestriction(EdgeIteratorState inEdge, EdgeIteratorState outEdge, int viaNode) {
-        graph.getTurnCostStorage().setExpensive("car", encodingManager, inEdge.getEdge(), viaNode, outEdge.getEdge(), Double.POSITIVE_INFINITY);
+        graph.getTurnCostStorage().set(((EncodedValueLookup) encodingManager).getDecimalEncodedValue(TurnCost.key("car")), inEdge.getEdge(), viaNode, outEdge.getEdge(), Double.POSITIVE_INFINITY);
     }
 
     private void setTurnCost(int from, int via, int to, double cost) {
@@ -1229,7 +1231,7 @@ public class CHTurnCostTest {
     }
 
     private void setTurnCost(EdgeIteratorState inEdge, EdgeIteratorState outEdge, int viaNode, double costs) {
-        graph.getTurnCostStorage().setExpensive("car", encodingManager, inEdge.getEdge(), viaNode, outEdge.getEdge(), costs);
+        graph.getTurnCostStorage().set(((EncodedValueLookup) encodingManager).getDecimalEncodedValue(TurnCost.key("car")), inEdge.getEdge(), viaNode, outEdge.getEdge(), costs);
     }
 
     private void setCostOrRestriction(EdgeIteratorState inEdge, EdgeIteratorState outEdge, int viaNode, int cost) {
diff --git a/core/src/test/java/com/graphhopper/routing/ch/EdgeBasedNodeContractorTest.java b/core/src/test/java/com/graphhopper/routing/ch/EdgeBasedNodeContractorTest.java
index 715bfb682..3569e833c 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/EdgeBasedNodeContractorTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/EdgeBasedNodeContractorTest.java
@@ -21,13 +21,12 @@ package com.graphhopper.routing.ch;
 import com.graphhopper.Repeat;
 import com.graphhopper.RepeatRule;
 import com.graphhopper.routing.profiles.BooleanEncodedValue;
+import com.graphhopper.routing.profiles.EncodedValueLookup;
+import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.AllCHEdgesIterator;
 import com.graphhopper.routing.util.CarFlagEncoder;
 import com.graphhopper.routing.util.EncodingManager;
-import com.graphhopper.storage.CHGraph;
-import com.graphhopper.storage.CHProfile;
-import com.graphhopper.storage.GraphBuilder;
-import com.graphhopper.storage.GraphHopperStorage;
+import com.graphhopper.storage.*;
 import com.graphhopper.util.EdgeIteratorState;
 import com.graphhopper.util.GHUtility;
 import com.graphhopper.util.PMap;
@@ -1398,7 +1397,8 @@ public class EdgeBasedNodeContractorTest {
     }
 
     private void setTurnCost(EdgeIteratorState inEdge, EdgeIteratorState outEdge, int viaNode, double cost) {
-        graph.getTurnCostStorage().setExpensive("car", encoder, inEdge.getEdge(), viaNode, outEdge.getEdge(), cost >= maxCost ? Double.POSITIVE_INFINITY : cost);
+        double cost1 = cost >= maxCost ? Double.POSITIVE_INFINITY : cost;
+        graph.getTurnCostStorage().set(((EncodedValueLookup) encoder).getDecimalEncodedValue(TurnCost.key("car")), inEdge.getEdge(), viaNode, outEdge.getEdge(), cost1);
     }
 
     private EdgeIteratorState getEdge(int from, int to) {
diff --git a/core/src/test/java/com/graphhopper/routing/ch/Path4CHTest.java b/core/src/test/java/com/graphhopper/routing/ch/Path4CHTest.java
index 9044121b7..7b02b812c 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/Path4CHTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/Path4CHTest.java
@@ -4,6 +4,8 @@ import com.graphhopper.routing.AlgorithmOptions;
 import com.graphhopper.routing.Path;
 import com.graphhopper.routing.RoutingAlgorithm;
 import com.graphhopper.routing.profiles.DecimalEncodedValue;
+import com.graphhopper.routing.profiles.EncodedValueLookup;
+import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.routing.util.MotorcycleFlagEncoder;
@@ -124,8 +126,7 @@ public class Path4CHTest {
     }
 
     private void setTurnCost(EdgeIteratorState inEdge, EdgeIteratorState outEdge, int viaNode, int cost) {
-        graph.getTurnCostStorage().setExpensive(encoder.toString(), graph.getEncodingManager(),
-                inEdge.getEdge(), viaNode, outEdge.getEdge(), cost);
+        graph.getTurnCostStorage().set(((EncodedValueLookup) graph.getEncodingManager()).getDecimalEncodedValue(TurnCost.key(encoder.toString())), inEdge.getEdge(), viaNode, outEdge.getEdge(), cost);
     }
 
     private void setTurnCost(int from, int via, int to, int cost) {
diff --git a/core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java b/core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java
index ad067fbc1..5ca674bbb 100644
--- a/core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java
+++ b/core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java
@@ -496,7 +496,6 @@ public class QueryGraphTest {
         GraphHopperStorage graphWithTurnCosts = new GraphHopperStorage(new RAMDirectory(), em, false, true).
                 create(100);
         TurnCostStorage turnExt = graphWithTurnCosts.getTurnCostStorage();
-        IntsRef tcFlags = TurnCost.createFlags();
         DecimalEncodedValue turnCostEnc = em.getDecimalEncodedValue(TurnCost.key(encoder.toString()));
         NodeAccess na = graphWithTurnCosts.getNodeAccess();
         na.setNode(0, .00, .00);
@@ -512,8 +511,7 @@ public class QueryGraphTest {
         assertEquals(0, weighting.calcTurnWeight(edge0.getEdge(), 1, edge1.getEdge()), .1);
 
         // now use turn costs
-        turnCostEnc.setDecimal(false, tcFlags, 10);
-        turnExt.setTurnCost(tcFlags, edge0.getEdge(), 1, edge1.getEdge());
+        turnExt.set(turnCostEnc, edge0.getEdge(), 1, edge1.getEdge(), 10);
         assertEquals(10, weighting.calcTurnWeight(edge0.getEdge(), 1, edge1.getEdge()), .1);
 
         // now use turn costs with query graph
diff --git a/core/src/test/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParserTest.java b/core/src/test/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParserTest.java
index 3523c0822..a00854a63 100644
--- a/core/src/test/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParserTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParserTest.java
@@ -3,12 +3,10 @@ package com.graphhopper.routing.util.parsers;
 import com.graphhopper.reader.OSMTurnRelation;
 import com.graphhopper.routing.EdgeBasedRoutingAlgorithmTest;
 import com.graphhopper.routing.profiles.DecimalEncodedValue;
-import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.CarFlagEncoder;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.storage.GraphBuilder;
 import com.graphhopper.storage.GraphHopperStorage;
-import com.graphhopper.storage.IntsRef;
 import com.graphhopper.storage.TurnCostStorage;
 import org.junit.Test;
 
@@ -52,19 +50,18 @@ public class OSMTurnRelationParserTest {
 
         // TYPE == ONLY
         OSMTurnRelation instance = new OSMTurnRelation(4, 3, 3, OSMTurnRelation.Type.ONLY);
-        IntsRef tcFlags = TurnCost.createFlags();
-        parser.addRelationToTCStorage(instance, tcFlags, map, ghStorage);
+        parser.addRelationToTCStorage(instance, map, ghStorage);
 
         TurnCostStorage tcs = ghStorage.getTurnCostStorage();
         DecimalEncodedValue tce = parser.getTurnCostEnc();
-        assertTrue(Double.isInfinite(tcs.get(tce, tcFlags, 4, 3, 6)));
-        assertEquals(0, tcs.get(tce, tcFlags, 4, 3, 3), .1);
-        assertTrue(Double.isInfinite(tcs.get(tce, tcFlags, 4, 3, 2)));
+        assertTrue(Double.isInfinite(tcs.get(tce, 4, 3, 6)));
+        assertEquals(0, tcs.get(tce, 4, 3, 3), .1);
+        assertTrue(Double.isInfinite(tcs.get(tce, 4, 3, 2)));
 
         // TYPE == NOT
         instance = new OSMTurnRelation(4, 3, 3, OSMTurnRelation.Type.NOT);
-        parser.addRelationToTCStorage(instance, tcFlags, map, ghStorage);
-        assertTrue(Double.isInfinite(tcs.get(tce, tcFlags, 4, 3, 3)));
+        parser.addRelationToTCStorage(instance, map, ghStorage);
+        assertTrue(Double.isInfinite(tcs.get(tce, 4, 3, 3)));
     }
 
     @Test
@@ -72,6 +69,6 @@ public class OSMTurnRelationParserTest {
         OSMTurnRelationParser parser = new OSMTurnRelationParser("fatcarsomething", 1);
         OSMTurnRelation turnRelation = new OSMTurnRelation(4, 3, 3, OSMTurnRelation.Type.NOT);
         turnRelation.setVehicleTypeRestricted("space");
-        parser.handleTurnRelationTags(TurnCost.createFlags(), turnRelation, null, null);
+        parser.handleTurnRelationTags(turnRelation, null, null);
     }
 }
\ No newline at end of file
diff --git a/core/src/test/java/com/graphhopper/routing/weighting/FastestWeightingTest.java b/core/src/test/java/com/graphhopper/routing/weighting/FastestWeightingTest.java
index b85ecd90f..4b1662cb6 100644
--- a/core/src/test/java/com/graphhopper/routing/weighting/FastestWeightingTest.java
+++ b/core/src/test/java/com/graphhopper/routing/weighting/FastestWeightingTest.java
@@ -17,15 +17,14 @@
  */
 package com.graphhopper.routing.weighting;
 
+import com.graphhopper.routing.profiles.EncodedValueLookup;
+import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.querygraph.VirtualEdgeIteratorState;
 import com.graphhopper.routing.util.Bike2WeightFlagEncoder;
 import com.graphhopper.routing.util.CarFlagEncoder;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.routing.util.FlagEncoder;
-import com.graphhopper.storage.Graph;
-import com.graphhopper.storage.GraphBuilder;
-import com.graphhopper.storage.GraphHopperStorage;
-import com.graphhopper.storage.IntsRef;
+import com.graphhopper.storage.*;
 import com.graphhopper.util.*;
 import com.graphhopper.util.Parameters.Routing;
 import org.junit.Test;
@@ -137,7 +136,7 @@ public class FastestWeightingTest {
     }
 
     private void setTurnCost(Graph graph, int from, int via, int to, double turnCost) {
-        graph.getTurnCostStorage().setExpensive(encoder.toString(), encodingManager, getEdge(graph, from, via).getEdge(), via, getEdge(graph, via, to).getEdge(), turnCost);
+        graph.getTurnCostStorage().set(((EncodedValueLookup) encodingManager).getDecimalEncodedValue(TurnCost.key(encoder.toString())), getEdge(graph, from, via).getEdge(), via, getEdge(graph, via, to).getEdge(), turnCost);
     }
 
 }
diff --git a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageWithTurnCostsTest.java b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageWithTurnCostsTest.java
index 82df64f5c..ec64e952f 100644
--- a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageWithTurnCostsTest.java
+++ b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageWithTurnCostsTest.java
@@ -17,6 +17,8 @@
  */
 package com.graphhopper.storage;
 
+import com.graphhopper.routing.profiles.EncodedValueLookup;
+import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.CarFlagEncoder;
 import com.graphhopper.util.EdgeIteratorState;
 import com.graphhopper.util.Helper;
@@ -149,10 +151,10 @@ public class GraphHopperStorageWithTurnCostsTest extends GraphHopperStorageTest
     }
 
     private double getTurnCost(EdgeIteratorState fromEdge, int viaNode, EdgeIteratorState toEdge) {
-        return graph.getTurnCostStorage().getExpensive("car", encodingManager, toEdge.getEdge(), viaNode, fromEdge.getEdge());
+        return graph.getTurnCostStorage().get(((EncodedValueLookup) encodingManager).getDecimalEncodedValue(TurnCost.key("car")), toEdge.getEdge(), viaNode, fromEdge.getEdge());
     }
 
     private void setTurnCost(int fromEdge, int viaNode, int toEdge, int cost) {
-        graph.getTurnCostStorage().setExpensive("car", encodingManager, fromEdge, viaNode, toEdge, cost);
+        graph.getTurnCostStorage().set(((EncodedValueLookup) encodingManager).getDecimalEncodedValue(TurnCost.key("car")), fromEdge, viaNode, toEdge, cost);
     }
 }
diff --git a/core/src/test/java/com/graphhopper/storage/ShortcutUnpackerTest.java b/core/src/test/java/com/graphhopper/storage/ShortcutUnpackerTest.java
index 5f08f8193..cfcefa5e0 100644
--- a/core/src/test/java/com/graphhopper/storage/ShortcutUnpackerTest.java
+++ b/core/src/test/java/com/graphhopper/storage/ShortcutUnpackerTest.java
@@ -4,6 +4,8 @@ import com.carrotsearch.hppc.DoubleArrayList;
 import com.carrotsearch.hppc.IntArrayList;
 import com.graphhopper.routing.ch.PrepareEncoder;
 import com.graphhopper.routing.profiles.DecimalEncodedValue;
+import com.graphhopper.routing.profiles.EncodedValueLookup;
+import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.routing.util.MotorcycleFlagEncoder;
@@ -298,7 +300,7 @@ public class ShortcutUnpackerTest {
     }
 
     private void setTurnCost(int fromEdge, int viaNode, int toEdge, double cost) {
-        graph.getTurnCostStorage().setExpensive(encoder.toString(), encodingManager, fromEdge, viaNode, toEdge, cost);
+        graph.getTurnCostStorage().set(((EncodedValueLookup) encodingManager).getDecimalEncodedValue(TurnCost.key(encoder.toString())), fromEdge, viaNode, toEdge, cost);
     }
 
     private void shortcut(int baseNode, int adjNode, int skip1, int skip2, int origFirst, int origLast) {
diff --git a/core/src/test/java/com/graphhopper/storage/TurnCostStorageTest.java b/core/src/test/java/com/graphhopper/storage/TurnCostStorageTest.java
index e7ea7963d..218fc1970 100644
--- a/core/src/test/java/com/graphhopper/storage/TurnCostStorageTest.java
+++ b/core/src/test/java/com/graphhopper/storage/TurnCostStorageTest.java
@@ -18,6 +18,7 @@
 
 package com.graphhopper.storage;
 
+import com.graphhopper.routing.profiles.EncodedValueLookup;
 import com.graphhopper.routing.profiles.TurnCost;
 import com.graphhopper.routing.util.BikeFlagEncoder;
 import com.graphhopper.routing.util.CarFlagEncoder;
@@ -31,7 +32,6 @@ import static org.junit.Assert.assertEquals;
 
 public class TurnCostStorageTest {
 
-    private final IntsRef EMPTY = TurnCost.createFlags();
     private EncodingManager manager;
 
     @Before
@@ -75,7 +75,6 @@ public class TurnCostStorageTest {
         setTurnCost(g, edge23, edge31, "bike", 3, 2.0);
         setTurnCost(g, edge31, edge10, "car", 1, 2.0);
         setTurnCost(g, edge31, edge10, "bike", 1, Double.POSITIVE_INFINITY);
-        g.getTurnCostStorage().setOrMerge(EMPTY, edge02, 2, edge24, false);
         setTurnCost(g, edge02, edge24, "bike", 2, Double.POSITIVE_INFINITY);
 
         assertEquals(Double.POSITIVE_INFINITY, getTurnCost(g, edge42, edge23, "car", 2), 0);
@@ -90,23 +89,10 @@ public class TurnCostStorageTest {
         assertEquals(0.0, getTurnCost(g, edge02, edge24, "car", 2), 0);
         assertEquals(Double.POSITIVE_INFINITY, getTurnCost(g, edge02, edge24, "bike", 2), 0);
 
-        // merge per default
         setTurnCost(g, edge02, edge23, "car", 2, Double.POSITIVE_INFINITY);
         setTurnCost(g, edge02, edge23, "bike", 2, Double.POSITIVE_INFINITY);
         assertEquals(Double.POSITIVE_INFINITY, getTurnCost(g, edge02, edge23, "car", 2), 0);
         assertEquals(Double.POSITIVE_INFINITY, getTurnCost(g, edge02, edge23, "bike", 2), 0);
-
-        // overwrite unrelated turn cost value
-        g.getTurnCostStorage().setOrMerge(EMPTY, edge02, 2, edge23, false);
-        g.getTurnCostStorage().setOrMerge(EMPTY, edge02, 2, edge23, false);
-        setTurnCost(g, edge02, edge23, "bike", 2, Double.POSITIVE_INFINITY);
-        assertEquals(0, getTurnCost(g, edge02, edge23, "car", 2), 0);
-        assertEquals(Double.POSITIVE_INFINITY, getTurnCost(g, edge02, edge23, "bike", 2), 0);
-
-        // clear
-        g.getTurnCostStorage().setOrMerge(EMPTY, edge02, 2, edge23, false);
-        assertEquals(0, getTurnCost(g, edge02, edge23, "car", 2), 0);
-        assertEquals(0, getTurnCost(g, edge02, edge23, "bike", 2), 0);
     }
 
     @Test
@@ -123,10 +109,10 @@ public class TurnCostStorageTest {
     }
 
     private void setTurnCost(GraphHopperStorage g, int fromEdge, int toEdge, String vehicle, int viaNode, double cost) {
-        g.getTurnCostStorage().setExpensive(vehicle, manager, fromEdge, viaNode, toEdge, cost);
+        g.getTurnCostStorage().set(((EncodedValueLookup) manager).getDecimalEncodedValue(TurnCost.key(vehicle)), fromEdge, viaNode, toEdge, cost);
     }
 
     private double getTurnCost(GraphHopperStorage g, int fromEdge, int toEdge, String vehicle, int viaNode) {
-        return g.getTurnCostStorage().getExpensive(vehicle, manager, fromEdge, viaNode, toEdge);
+        return g.getTurnCostStorage().get(((EncodedValueLookup) manager).getDecimalEncodedValue(TurnCost.key(vehicle)), fromEdge, viaNode, toEdge);
     }
 }
diff --git a/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java b/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
index 33ac12d34..550bb732b 100644
--- a/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
+++ b/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
@@ -517,30 +517,29 @@ public class OSMReaderTest {
 
         // (2-3)->(3-4) only_straight_on = (2-3)->(3-8) restricted
         // (4-3)->(3-8) no_right_turn = (4-3)->(3-8) restricted
-        IntsRef tcFlags = TurnCost.createFlags();
         DecimalEncodedValue carTCEnc = hopper.getEncodingManager().getDecimalEncodedValue(TurnCost.key("car"));
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge2_3, n3, edge3_8) > 0);
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge4_3, n3, edge3_8) > 0);
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge2_3, n3, edge3_4) == 0);
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge2_3, n3, edge3_2) == 0);
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge2_3, n3, edge3_4) == 0);
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge4_3, n3, edge3_2) == 0);
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge8_3, n3, edge3_2) == 0);
+        assertTrue(tcStorage.get(carTCEnc, edge2_3, n3, edge3_8) > 0);
+        assertTrue(tcStorage.get(carTCEnc, edge4_3, n3, edge3_8) > 0);
+        assertTrue(tcStorage.get(carTCEnc, edge2_3, n3, edge3_4) == 0);
+        assertTrue(tcStorage.get(carTCEnc, edge2_3, n3, edge3_2) == 0);
+        assertTrue(tcStorage.get(carTCEnc, edge2_3, n3, edge3_4) == 0);
+        assertTrue(tcStorage.get(carTCEnc, edge4_3, n3, edge3_2) == 0);
+        assertTrue(tcStorage.get(carTCEnc, edge8_3, n3, edge3_2) == 0);
 
         // u-turn restriction for (6-1)->(1-6) but not for (1-6)->(6-1)
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge1_6, n1, edge1_6) > 0);
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge1_6, n6, edge1_6) == 0);
+        assertTrue(tcStorage.get(carTCEnc, edge1_6, n1, edge1_6) > 0);
+        assertTrue(tcStorage.get(carTCEnc, edge1_6, n6, edge1_6) == 0);
 
         int edge4_5 = GHUtility.getEdge(graph, n4, n5).getEdge();
         int edge5_6 = GHUtility.getEdge(graph, n5, n6).getEdge();
         int edge5_1 = GHUtility.getEdge(graph, n5, n1).getEdge();
 
         // (4-5)->(5-1) right_turn_only = (4-5)->(5-6) restricted
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge4_5, n5, edge5_6) == 0);
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge4_5, n5, edge5_1) > 0);
+        assertTrue(tcStorage.get(carTCEnc, edge4_5, n5, edge5_6) == 0);
+        assertTrue(tcStorage.get(carTCEnc, edge4_5, n5, edge5_1) > 0);
 
         DecimalEncodedValue bikeTCEnc = hopper.getEncodingManager().getDecimalEncodedValue(TurnCost.key("bike"));
-        assertTrue(tcStorage.get(bikeTCEnc, tcFlags, edge4_5, n5, edge5_6) == 0);
+        assertTrue(tcStorage.get(bikeTCEnc, edge4_5, n5, edge5_6) == 0);
 
         int n10 = AbstractGraphStorageTester.getIdOf(graph, 40, 10);
         int n11 = AbstractGraphStorageTester.getIdOf(graph, 40, 11);
@@ -549,11 +548,11 @@ public class OSMReaderTest {
         int edge10_11 = GHUtility.getEdge(graph, n10, n11).getEdge();
         int edge11_14 = GHUtility.getEdge(graph, n11, n14).getEdge();
 
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge11_14, n11, edge10_11) == 0);
-        assertTrue(tcStorage.get(bikeTCEnc, tcFlags, edge11_14, n11, edge10_11) == 0);
+        assertTrue(tcStorage.get(carTCEnc, edge11_14, n11, edge10_11) == 0);
+        assertTrue(tcStorage.get(bikeTCEnc, edge11_14, n11, edge10_11) == 0);
 
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge10_11, n11, edge11_14) == 0);
-        assertTrue(tcStorage.get(bikeTCEnc, tcFlags, edge10_11, n11, edge11_14) > 0);
+        assertTrue(tcStorage.get(carTCEnc, edge10_11, n11, edge11_14) == 0);
+        assertTrue(tcStorage.get(bikeTCEnc, edge10_11, n11, edge11_14) > 0);
     }
 
     @Test
@@ -721,26 +720,25 @@ public class OSMReaderTest {
         Graph graph = hopper.getGraphHopperStorage();
         TurnCostStorage tcStorage = graph.getTurnCostStorage();
 
-        IntsRef tcFlags = TurnCost.createFlags();
         int edge1 = GHUtility.getEdge(graph, 1, 0).getEdge();
         int edge2 = GHUtility.getEdge(graph, 0, 2).getEdge();
         // the 2nd entry provides turn flags for bike only
-        assertTrue(Double.isInfinite(tcStorage.get(carTCEnc, tcFlags, edge1, 0, edge2)));
-        assertTrue(Double.isInfinite(tcStorage.get(truckTCEnc, tcFlags, edge1, 0, edge2)));
-        assertEquals(0, tcStorage.get(bikeTCEnc, tcFlags, edge1, 0, edge2), .1);
+        assertTrue(Double.isInfinite(tcStorage.get(carTCEnc, edge1, 0, edge2)));
+        assertTrue(Double.isInfinite(tcStorage.get(truckTCEnc, edge1, 0, edge2)));
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge1, 0, edge2), .1);
 
         edge1 = GHUtility.getEdge(graph, 2, 0).getEdge();
         edge2 = GHUtility.getEdge(graph, 0, 3).getEdge();
         // the first entry provides turn flags for car and foot only
-        assertEquals(0, tcStorage.get(carTCEnc, tcFlags, edge1, 0, edge2), .1);
-        assertEquals(0, tcStorage.get(truckTCEnc, tcFlags, edge1, 0, edge2), .1);
-        assertTrue(Double.isInfinite(tcStorage.get(bikeTCEnc, tcFlags, edge1, 0, edge2)));
+        assertEquals(0, tcStorage.get(carTCEnc, edge1, 0, edge2), .1);
+        assertEquals(0, tcStorage.get(truckTCEnc, edge1, 0, edge2), .1);
+        assertTrue(Double.isInfinite(tcStorage.get(bikeTCEnc, edge1, 0, edge2)));
 
         edge1 = GHUtility.getEdge(graph, 3, 0).getEdge();
         edge2 = GHUtility.getEdge(graph, 0, 2).getEdge();
-        assertEquals(0, tcStorage.get(carTCEnc, tcFlags, edge1, 0, edge2), .1);
-        assertTrue(Double.isInfinite(tcStorage.get(truckTCEnc, tcFlags, edge1, 0, edge2)));
-        assertEquals(0, tcStorage.get(bikeTCEnc, tcFlags, edge1, 0, edge2), .1);
+        assertEquals(0, tcStorage.get(carTCEnc, edge1, 0, edge2), .1);
+        assertTrue(Double.isInfinite(tcStorage.get(truckTCEnc, edge1, 0, edge2)));
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge1, 0, edge2), .1);
     }
 
     @Test
@@ -778,38 +776,37 @@ public class OSMReaderTest {
         // (2-3)->(3-4) only_straight_on except bicycle = (2-3)->(3-8) restricted for car
         // (4-3)->(3-8) no_right_turn dedicated to motorcar = (4-3)->(3-8) restricted for car
 
-        IntsRef tcFlags = TurnCost.createFlags();
         DecimalEncodedValue carTCEnc = hopper.getEncodingManager().getDecimalEncodedValue(TurnCost.key("car"));
-        assertTrue(tcStorage.get(carTCEnc, tcFlags, edge2_3, n3, edge3_8) > 0);
-        assertTrue(tcStorage.get(carTCEnc,tcFlags, edge4_3, n3, edge3_8) > 0);
-        assertEquals(0, tcStorage.get(carTCEnc,tcFlags, edge2_3, n3, edge3_4), .1);
-        assertEquals(0, tcStorage.get(carTCEnc,tcFlags, edge2_3, n3, edge3_2), .1);
-        assertEquals(0, tcStorage.get(carTCEnc,tcFlags, edge2_3, n3, edge3_4), .1);
-        assertEquals(0, tcStorage.get(carTCEnc,tcFlags, edge4_3, n3, edge3_2), .1);
-        assertEquals(0, tcStorage.get(carTCEnc,tcFlags, edge8_3, n3, edge3_2), .1);
+        assertTrue(tcStorage.get(carTCEnc, edge2_3, n3, edge3_8) > 0);
+        assertTrue(tcStorage.get(carTCEnc, edge4_3, n3, edge3_8) > 0);
+        assertEquals(0, tcStorage.get(carTCEnc, edge2_3, n3, edge3_4), .1);
+        assertEquals(0, tcStorage.get(carTCEnc, edge2_3, n3, edge3_2), .1);
+        assertEquals(0, tcStorage.get(carTCEnc, edge2_3, n3, edge3_4), .1);
+        assertEquals(0, tcStorage.get(carTCEnc, edge4_3, n3, edge3_2), .1);
+        assertEquals(0, tcStorage.get(carTCEnc, edge8_3, n3, edge3_2), .1);
 
         DecimalEncodedValue bikeTCEnc = hopper.getEncodingManager().getDecimalEncodedValue(TurnCost.key("bike"));
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge2_3, n3, edge3_8), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge4_3, n3, edge3_8), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge2_3, n3, edge3_4), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge2_3, n3, edge3_2), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge2_3, n3, edge3_4), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge4_3, n3, edge3_2), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge8_3, n3, edge3_2), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge2_3, n3, edge3_8), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge4_3, n3, edge3_8), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge2_3, n3, edge3_4), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge2_3, n3, edge3_2), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge2_3, n3, edge3_4), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge4_3, n3, edge3_2), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge8_3, n3, edge3_2), .1);
 
         // u-turn except bus;bicycle restriction for (6-1)->(1-6) but not for (1-6)->(6-1)
-        assertTrue(tcStorage.get(carTCEnc,tcFlags, edge1_6, n1, edge1_6) > 0);
-        assertEquals(0, tcStorage.get(carTCEnc,tcFlags, edge1_6, n6, edge1_6), .1);
+        assertTrue(tcStorage.get(carTCEnc, edge1_6, n1, edge1_6) > 0);
+        assertEquals(0, tcStorage.get(carTCEnc, edge1_6, n6, edge1_6), .1);
 
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge1_6, n1, edge1_6), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge1_6, n6, edge1_6), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge1_6, n1, edge1_6), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge1_6, n6, edge1_6), .1);
 
         // (4-5)->(5-6) right_turn_only dedicated to motorcar = (4-5)->(5-1) restricted
-        assertEquals(0, tcStorage.get(carTCEnc,tcFlags, edge4_5, n5, edge5_6), .1);
-        assertTrue(tcStorage.get(carTCEnc,tcFlags, edge4_5, n5, edge5_1) > 0);
+        assertEquals(0, tcStorage.get(carTCEnc, edge4_5, n5, edge5_6), .1);
+        assertTrue(tcStorage.get(carTCEnc, edge4_5, n5, edge5_1) > 0);
 
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge4_5, n5, edge5_6), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge4_5, n5, edge5_1), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge4_5, n5, edge5_6), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge4_5, n5, edge5_1), .1);
     }
 
     @Test
@@ -835,25 +832,24 @@ public class OSMReaderTest {
         int edge4_5 = GHUtility.getEdge(graph, n4, n5).getEdge();
         int edge5_1 = GHUtility.getEdge(graph, n5, n1).getEdge();
 
-        IntsRef tcFlags = TurnCost.createFlags();
         DecimalEncodedValue carTCEnc = hopper.getEncodingManager().getDecimalEncodedValue(TurnCost.key("car"));
         DecimalEncodedValue bikeTCEnc = hopper.getEncodingManager().getDecimalEncodedValue(TurnCost.key("bike"));
 
         // (1-2)->(2-3) no_right_turn for motorcar and bus
-        assertTrue(tcStorage.get(carTCEnc,tcFlags, edge1_2, n2, edge2_3) > 0);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge1_2, n2, edge2_3), .1);
+        assertTrue(tcStorage.get(carTCEnc, edge1_2, n2, edge2_3) > 0);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge1_2, n2, edge2_3), .1);
 
         // (3-4)->(4-5) no_right_turn for motorcycle and motorcar
-        assertTrue(Double.isInfinite(tcStorage.get(carTCEnc,tcFlags, edge3_4, n4, edge4_5)));
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge3_4, n4, edge4_5), .1);
+        assertTrue(Double.isInfinite(tcStorage.get(carTCEnc, edge3_4, n4, edge4_5)));
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge3_4, n4, edge4_5), .1);
 
         // (5-1)->(1-2) no_right_turn for bus and psv except for motorcar and bicycle
-        assertEquals(0, tcStorage.get(carTCEnc,tcFlags, edge4_5, n5, edge5_1), .1);
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge4_5, n5, edge5_1), .1);
+        assertEquals(0, tcStorage.get(carTCEnc, edge4_5, n5, edge5_1), .1);
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge4_5, n5, edge5_1), .1);
 
         // (5-1)->(1-2) no_right_turn for motorcar and motorcycle except for bus and bicycle
-        assertTrue(Double.isInfinite(tcStorage.get(carTCEnc,tcFlags, edge5_1, n1, edge1_2)));
-        assertEquals(0, tcStorage.get(bikeTCEnc,tcFlags, edge5_1, n1, edge1_2), .1);
+        assertTrue(Double.isInfinite(tcStorage.get(carTCEnc, edge5_1, n1, edge1_2)));
+        assertEquals(0, tcStorage.get(bikeTCEnc, edge5_1, n1, edge1_2), .1);
     }
 
     @Test