MATSIM
TravelTimeDataArray.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * TravelTimeRoleArray.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.trafficmonitoring;
22 
24 
25 import java.util.Arrays;
26 
34 class TravelTimeDataArray extends TravelTimeData {
35 
36  /* The original implementation used two arrays to store the data:
37  * an int-array (later replaced with a short-array) to store the count,
38  * and a double-array to store the travel-time. Thus, for each time-bin,
39  * 10 bytes were used. And for each operation, at least 2 memory accesses
40  * had to be performed to access the two arrays.
41  *
42  * The current implementation now uses only 1 array of type long, thus
43  * requiring only 8 bytes per time-bin instead of 10, a reduction of 20%.
44  * For each time-bin, the long-value contains the count as int-value in
45  * the higher 4 bytes, and the travel-time as an int in the lower 4 bytes.
46  * To support fractional values for the travel-time (although this is
47  * very rarely used in MATSim), the (double-value) travel-time is multiplied
48  * by 1000 and then stored as int, supporting millisecond resolution in
49  * the travel time and (2^31 - 1)/1000 = 2147483.647 seconds as maximum
50  * travel time (which is more than 596 hours or 24.8 days).
51  *
52  * The reduced memory usage can lead to fewer CPU cache misses, and as
53  * only one array access is necessary instead of two, routing-performance
54  * improves considerably, especially if used with an efficient routing
55  * implementation like SpeedyALT.
56  *
57  * -mrieser, april 2021
58  */
59  private final long[] data;
60  private final Link link;
61 
62  TravelTimeDataArray(final Link link, final int numSlots) {
63  this.data = new long[numSlots];
64  this.link = link;
65  resetTravelTimes();
66  }
67 
68  static long encode(int count, double traveltime) {
69  long hi = count;
70  int lo = (int) (traveltime * 1000);
71  long val = hi << 32 | (lo & 0xffffffffL);
72  return val;
73  }
74 
75  static int count(long encoded) {
76  return (int) (encoded >>> 32);
77  }
78 
79  static double traveltime(long encoded) {
80  int tt = (int) (encoded);
81  return tt / 1000.0;
82  }
83 
84  @Override
85  public void resetTravelTimes() {
86  long val = encode(0, -1.0);
87  Arrays.fill(this.data, val);
88  }
89 
90  @Override
91  public void setTravelTime( final int timeSlot, final double traveltime ) {
92  this.data[timeSlot] = encode(1, traveltime);
93  }
94 
95  @Override
96  public void addTravelTime(final int timeSlot, final double traveltime) {
97  long val = this.data[timeSlot];
98  int cnt = count(val);
99  double tt = traveltime(val);
100  double sum = tt * cnt;
101 
102  sum += traveltime;
103  cnt++;
104 
105  this.data[timeSlot] = encode(cnt, sum / cnt);
106  }
107 
108  @Override
109  public double getTravelTime(final int timeSlot, final double now) {
110  long val = this.data[timeSlot];
111  double ttime = traveltime(val);
112  if (ttime >= 0.0) return ttime; // negative values are invalid.
113 
114  // ttime can only be <0 if it never accumulated anything, i.e. if cnt == 0, so just use freespeed
115  double freespeed = this.link.getLength() / this.link.getFreespeed(now);
116  this.data[timeSlot] = encode(0, freespeed);
117  return freespeed;
118  }
119 
120  /* package-private for debugging */ String cntToString(){
121  StringBuilder strb = new StringBuilder().append( "cnt=[ " );
122  for( int ii = 0 ; ii < this.data.length ; ii++ ){
123  strb.append( count(this.data[ii]) ).append( " " );
124  }
125  strb.append( "]" );
126  return strb.toString();
127  }
128  /* package-private for debugging */ String ttToString() {
129  StringBuilder strb = new StringBuilder().append( "tt=[ " );
130  for ( int ii=0 ; ii<this.data.length ; ii++ ) {
131  strb.append( traveltime(this.data[ii]) ).append( " " );
132  }
133  strb.append( "]" );
134  return strb.toString();
135  }
136 
137 }