Skip to content

Commit 3034608

Browse files
committed
Speed improvements in BasePath by converting the path to utf8 segments one time, and then always comparing on utf8 arrays
1 parent db02504 commit 3034608

File tree

1 file changed

+30
-6
lines changed
  • firebase-firestore/src/main/java/com/google/firebase/firestore/model

1 file changed

+30
-6
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/model/BasePath.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import androidx.annotation.NonNull;
2020
import com.google.firebase.firestore.util.Util;
21+
import java.nio.charset.StandardCharsets;
2122
import java.util.ArrayList;
2223
import java.util.List;
2324

@@ -27,6 +28,7 @@
2728
*/
2829
public abstract class BasePath<B extends BasePath<B>> implements Comparable<B> {
2930
final List<String> segments;
31+
List<byte[]> utf8Segments = null;
3032

3133
BasePath(List<String> segments) {
3234
this.segments = segments;
@@ -93,8 +95,12 @@ public int compareTo(@NonNull B o) {
9395
int i = 0;
9496
int myLength = length();
9597
int theirLength = o.length();
98+
List<byte[]> myUtf8Segments = ensureUtf8Segments();
99+
List<byte[]> theirUtf8Segments = o.ensureUtf8Segments();
96100
while (i < myLength && i < theirLength) {
97-
int localCompare = compareSegments(getSegment(i), o.getSegment(i));
101+
int localCompare =
102+
compareSegments(
103+
myUtf8Segments.get(i), theirUtf8Segments.get(i), getSegment(i), o.getSegment(i));
98104
if (localCompare != 0) {
99105
return localCompare;
100106
}
@@ -103,21 +109,39 @@ public int compareTo(@NonNull B o) {
103109
return Integer.compare(myLength, theirLength);
104110
}
105111

106-
private static int compareSegments(String lhs, String rhs) {
107-
boolean isLhsNumeric = isNumericId(lhs);
108-
boolean isRhsNumeric = isNumericId(rhs);
112+
private static int compareSegments(byte[] lhs, byte[] rhs, String lhsString, String rhsString) {
113+
boolean isLhsNumeric = lhs == null;
114+
boolean isRhsNumeric = rhs == null;
109115

110116
if (isLhsNumeric && !isRhsNumeric) { // Only lhs is numeric
111117
return -1;
112118
} else if (!isLhsNumeric && isRhsNumeric) { // Only rhs is numeric
113119
return 1;
114120
} else if (isLhsNumeric && isRhsNumeric) { // both numeric
115-
return Long.compare(extractNumericId(lhs), extractNumericId(rhs));
121+
return Long.compare(extractNumericId(lhsString), extractNumericId(rhsString));
116122
} else { // both string
117-
return Util.compareUtf8Strings(lhs, rhs);
123+
return Util.compareByteArrays(lhs, rhs);
118124
}
119125
}
120126

127+
public List<byte[]> ensureUtf8Segments() {
128+
if (this.utf8Segments == null) {
129+
this.utf8Segments = new ArrayList<>(this.segments.size());
130+
for (int i = 0; i < this.segments.size(); i++) {
131+
String segment = this.segments.get(i);
132+
boolean isNumeric = isNumericId(segment);
133+
if (!isNumeric) {
134+
byte[] utf8Bytes = segment.getBytes(StandardCharsets.UTF_8);
135+
this.utf8Segments.add(utf8Bytes);
136+
} else {
137+
this.utf8Segments.add(null);
138+
}
139+
}
140+
}
141+
142+
return this.utf8Segments;
143+
}
144+
121145
/** Checks if a segment is a numeric ID (starts with "__id" and ends with "__"). */
122146
private static boolean isNumericId(String segment) {
123147
return segment.startsWith("__id") && segment.endsWith("__");

0 commit comments

Comments
 (0)