Skip to content

Commit e162d51

Browse files
committed
Avoid dummy endpoints in no-endpoint LineString uncompaction
Rewrite CompactLineStringUtils.uncompactLineString(byte[], boolean) to decode delta-encoded coordinates directly from origin (0,0) instead of delegating to the endpoint-aware overload with dummy (0,0) endpoints and then stripping them via removeStartEndCoordinatesFromLineString(). This eliminates per-call allocation of 2 dummy Coordinate objects, 1 intermediate LineString, and 1 redundant Coordinate[] copy. JFR profiling under production-like load shows geometry subsystem allocation dropped from 93 GB to 42 GB (-55%) and overall allocation rate dropped from 1,499 MB/s to 1,170 MB/s (-22%).
1 parent bec3bd4 commit e162d51

3 files changed

Lines changed: 44 additions & 12 deletions

File tree

street/src/main/java/org/opentripplanner/street/geometry/CompactLineStringUtils.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,27 @@ public static LineString uncompactLineString(
168168
}
169169

170170
/**
171-
* Wrapper for the above method in the case where there are no start/end coordinates provided.
172-
* 0-coordinates are added and then removed in order for the delta encoding to work correctly.
173-
* Same as the other version, but in a var-len int packed form (Dlugosz coding).
171+
* Uncompact a line string that was compacted without start/end endpoint context. Decodes the
172+
* delta-encoded coordinates directly, avoiding the intermediate dummy-endpoint LineString and
173+
* subsequent strip that the previous implementation used.
174174
*/
175175
public static LineString uncompactLineString(byte[] packedCoords, boolean reverse) {
176-
LineString lineString = uncompactLineString(0.0, 0.0, 0.0, 0.0, packedCoords, reverse);
177-
return GeometryUtils.removeStartEndCoordinatesFromLineString(lineString);
176+
int[] coords = DlugoszVarLenIntPacker.unpack(packedCoords);
177+
if (coords == null || coords.length == 0) {
178+
return GeometryUtils.makeLineString(new Coordinate[0]);
179+
}
180+
int size = coords.length / 2;
181+
Coordinate[] c = new Coordinate[size];
182+
int oix = 0;
183+
int oiy = 0;
184+
for (int i = 0; i < size; i++) {
185+
int ix = oix + coords[i * 2];
186+
int iy = oiy + coords[i * 2 + 1];
187+
c[i] = new Coordinate(ix / FIXED_FLOAT_MULT, iy / FIXED_FLOAT_MULT);
188+
oix = ix;
189+
oiy = iy;
190+
}
191+
LineString out = GeometryUtils.makeLineString(c);
192+
return reverse ? out.reverse() : out;
178193
}
179194
}

street/src/main/java/org/opentripplanner/street/geometry/GeometryUtils.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,6 @@ public static LineString addStartEndCoordinatesToLineString(
113113
return makeLineString(result);
114114
}
115115

116-
public static LineString removeStartEndCoordinatesFromLineString(LineString lineString) {
117-
Coordinate[] c = lineString.getCoordinates();
118-
Coordinate[] result = new Coordinate[c.length - 2];
119-
System.arraycopy(c, 1, result, 0, c.length - 2);
120-
return makeLineString(result);
121-
}
122-
123116
public static GeometryFactory getGeometryFactory() {
124117
return GF;
125118
}

street/src/test/java/org/opentripplanner/street/geometry/CompactLineStringUtilsTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,30 @@ public final void testCompactString() {
8080
assertTrue(lsi.equalsExact(ls2, 0.00000015));
8181
}
8282

83+
@Test
84+
public void testNoEndpointRoundTrip() {
85+
GeometryFactory gf = new GeometryFactory();
86+
87+
Coordinate[] points = {
88+
new Coordinate(-179.99, 1.12345),
89+
new Coordinate(10.123456, 59.654321),
90+
new Coordinate(179.99, 1.12345),
91+
};
92+
LineString original = gf.createLineString(points);
93+
94+
// Forward
95+
byte[] packed = CompactLineStringUtils.compactLineString(original, false);
96+
LineString result = CompactLineStringUtils.uncompactLineString(packed, false);
97+
assertEquals(original.getNumPoints(), result.getNumPoints());
98+
assertTrue(original.equalsExact(result, 0.0000015));
99+
100+
// Reverse
101+
LineString reversed = (LineString) original.reverse();
102+
result = CompactLineStringUtils.uncompactLineString(packed, true);
103+
assertEquals(reversed.getNumPoints(), result.getNumPoints());
104+
assertTrue(reversed.equalsExact(result, 0.0000015));
105+
}
106+
83107
@Test
84108
public final void testDlugoszVarLenIntPacker() {
85109
packTest(new int[] {}, 0);

0 commit comments

Comments
 (0)