16
16
import java .util .concurrent .ExecutionException ;
17
17
18
18
/**
19
- * Retains linkages between PointSets and the StreetLayers for specific StreetModes.
20
- * This used to be embedded in the PointSets themselves, now there should be one instance per TransportNetwork.
19
+ * Retains linkages between PointSets and the StreetLayers for specific StreetModes, including egress distance tables .
20
+ * LinkageCaches used to be associated with individual PointSets, but now there is a single cache per TransportNetwork.
21
21
* There could instead be one instance per AnalystWorker or per JVM (static), but this would cause the mappings
22
22
* including PointSets, StreetLayers, and Linkages (which hold references to the TransportNetwork) to stick around
23
- * even when we try to garbage collect a TransportNetwork. This is less of an issue now that we don't plan to have
24
- * workers migrate between TransportNetworks .
23
+ * even when we try to garbage collect a TransportNetwork. In cloud operation, this problem would not necessarily arise
24
+ * in practice since workers are permanently associated with a single base TransportNetwork .
25
25
*/
26
26
public class LinkageCache {
27
27
28
28
private static final Logger LOG = LoggerFactory .getLogger (LinkageCache .class );
29
29
30
30
/**
31
- * Maximum number of street network linkages to cache per PointSet. This is a crude way of limiting memory
32
- * consumption, and should eventually be replaced with a WeighingCache. Since every Scenario including the
33
- * baseline has its own StreetLayer instance now, this means we can hold walk, bike, and car linkages (with
34
- * distance tables) for 2 scenarios plus the baseline at once.
35
- * FIXME this used to be per-PointSet, now it's one single limit per TransportNetwork.
31
+ * Maximum number of street network linkages and associated egress tables to retain in this LinkageCache.
32
+ * This is a crude way of limiting memory consumption, and would ideally be replaced with a WeighingCache.
33
+ * However, the memory consumption of a particular linkage is difficult to quantify, as the bulk of the data
34
+ * is distance tables, and multiple linkages may share a large number of references to reused distance tables.
35
+ * Since every Scenario including the baseline has its own StreetLayer instance, we could for example hold linkages
36
+ * (with associated distance tables) for walk, bike, and car egress for 2 scenarios plus the baseline at once.
36
37
*/
37
38
public static int LINKAGE_CACHE_SIZE = 9 ;
38
39
39
40
/**
40
- * When this PointSet is connected to the street network, the resulting data are cached in this Map to speed up
41
- * later reuse. Different linkages are produced for different street networks and for different on-street modes
42
- * of travel. At first we were careful to key this cache on the StreetNetwork itself (rather than the
43
- * TransportNetwork or Scenario) to ensure that linkages were re-used for multiple scenarios that have the same
44
- * street network. However, selectively re-linking to the street network is now usually fast, and
45
- * StreetNetworks must be copied for every scenario due to references to their containing TransportNetwork.
41
+ * For a particular TransportNetwork, a different linkage is produced for each unique combination of destination
42
+ * points, StreetLayer, and on-street mode of travel (see details of Key). A distinct StreetLayer instance exists
43
+ * for each scenario even when its contents remain unchanged by the scenario, because the StreetLayer references
44
+ * the enclosing TransportNetwork for the scenario.
46
45
* Note that this cache will be serialized with the PointSet, but serializing a Guava cache only serializes the
47
- * cache instance and its settings, not the contents of the cache. We consider this sane behavior.
46
+ * cache instance and its settings, not the contents of the cache. This is the intended behavior.
48
47
*/
49
48
protected transient LoadingCache <Key , LinkedPointSet > linkageCache ;
50
49
@@ -59,24 +58,24 @@ public class LinkageCache {
59
58
/**
60
59
* The logic for lazy-loading linkages into the cache.
61
60
*
62
- // FIXME FIXME clean up these notes on sub-linkages.
63
- // We know that pointSet is a WebMercatorGridPointSet, but if it's a new one we want to replicate its
64
- // linkages based on the base scenarioNetwork.gridPointSet's linkages. We don't know if it's new, so such
65
- // logic has to happen in the loop below over all streetModes, where we fetch and build the egress cost
66
- // tables. We already know for sure this is a scenarioNetwork.
67
- // So if we see a linkage for scenarioNetwork.gridPointSet, we need to add another linkage.
68
- // When this mapping exists:
69
- // (scenarioNetwork.gridPointSet, StreetLayer, StreetMode) -> linkageFor(scenarioNetwork.gridPointSet)
70
- // We need to generate this mapping:
71
- // (pointSet, StreetLayer, StreetMode) -> new LinkedPointSet(linkageFor(scenarioNetwork.gridPointSet), pointSet);
72
- // Note that: ((WebMercatorGridPointSet)pointSet).base == scenarioNetwork.gridPointSet
73
- // I'm afraid BaseLinkage means two different things here: we can subset bigger linkages that already
74
- // exist, or we can redo subsets of linkages of the same size them them when applying scenarios.
75
- // Yes: in one situation, the PointSet objects are identical when making the new linkage, but the
76
- // streetLayer differs. In the other situation, the PointSet objects are different but the other aspects
77
- // are the same. Again this is the difference between a PointSet and its linkage. We should call them
78
- // PointSetLinkages instead of LinkedPointSets because they do not subclass PointSet.
79
- // basePointSet vs. baseStreetLayer vs. baseLinkage.
61
+ * FIXME clean up these notes on sub-linkages, some of which may be obsolete .
62
+ * We know that pointSet is a WebMercatorGridPointSet, but if it's a new one we want to replicate its
63
+ * linkages based on the base scenarioNetwork.gridPointSet's linkages. We don't know if it's new, so such
64
+ * logic has to happen in the loop below over all streetModes, where we fetch and build the egress cost
65
+ * tables. We already know for sure this is a scenarioNetwork.
66
+ * So if we see a linkage for scenarioNetwork.gridPointSet, we need to add another linkage.
67
+ * When this mapping exists:
68
+ * (scenarioNetwork.gridPointSet, StreetLayer, StreetMode) -> linkageFor(scenarioNetwork.gridPointSet)
69
+ * We need to generate this mapping:
70
+ * (pointSet, StreetLayer, StreetMode) -> new LinkedPointSet(linkageFor(scenarioNetwork.gridPointSet), pointSet);
71
+ * Note that: ((WebMercatorGridPointSet)pointSet).base == scenarioNetwork.gridPointSet
72
+ * I'm afraid BaseLinkage means two different things here: we can subset bigger linkages that already
73
+ * exist, or we can redo subsets of linkages of the same size when applying scenarios.
74
+ * Yes: in one situation, the PointSet objects are identical when making the new linkage, but the
75
+ * streetLayer differs. In the other situation, the PointSet objects are different but the other aspects
76
+ * are the same. Again this is the difference between a PointSet and its linkage. We should call them
77
+ * PointSetLinkages instead of LinkedPointSets because they do not subclass PointSet.
78
+ * basePointSet vs. baseStreetLayer vs. baseLinkage.
80
79
*/
81
80
private class LinkageCacheLoader extends CacheLoader <Key , LinkedPointSet > implements Serializable {
82
81
@ Override
0 commit comments