Skip to content

Commit d756984

Browse files
ctf: lazy load mappings and use a tree
O(log(n)) instead of O(n) This patch was made with the assistance of Claude Sonnet 4.5 Change-Id: Ic46ff28a84e45beb8462f642340db19d04fa40fc Signed-off-by: Matthew Khouzam <[email protected]>
1 parent 99a9d62 commit d756984

File tree

2 files changed

+66
-26
lines changed

2 files changed

+66
-26
lines changed

ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDeclaration.java

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@
2020

2121
import java.math.BigInteger;
2222
import java.nio.ByteOrder;
23-
import java.util.HashMap;
23+
import java.util.ArrayList;
24+
import java.util.Collections;
25+
import java.util.Comparator;
2426
import java.util.List;
2527
import java.util.Map;
28+
import java.util.Objects;
29+
import java.util.TreeMap;
2630

2731
import org.eclipse.jdt.annotation.NonNullByDefault;
2832
import org.eclipse.jdt.annotation.Nullable;
@@ -132,7 +136,19 @@ public final class IntegerDeclaration extends Declaration implements ISimpleData
132136
private final long fAlignment;
133137
private final String fClock;
134138
private boolean fVarint = false;
135-
private Map<String, List<IntegerRange>> fMappings = new HashMap<>();
139+
private static class IntervalNode {
140+
final long start, end;
141+
final String name;
142+
143+
IntervalNode(long start, long end, String name) {
144+
this.start = start;
145+
this.end = end;
146+
this.name = name;
147+
}
148+
}
149+
150+
private Map<String, List<IntegerRange>> fMappings = new TreeMap<>();
151+
private List<IntervalNode> fIntervalTree = new ArrayList<>();
136152

137153
// ------------------------------------------------------------------------
138154
// Constructors
@@ -426,7 +442,20 @@ public Map<String, List<IntegerRange>> getMappings() {
426442
* a mapped range of integers
427443
*/
428444
private void setMappings(Map<String, List<IntegerRange>> mappings) {
429-
fMappings = mappings;
445+
fMappings.clear();
446+
fMappings.putAll(mappings);
447+
buildIntervalTree();
448+
}
449+
450+
private void buildIntervalTree() {
451+
fIntervalTree.clear();
452+
for (Map.Entry<String, List<IntegerRange>> entry : fMappings.entrySet()) {
453+
String name = entry.getKey();
454+
for (IntegerRange range : entry.getValue()) {
455+
fIntervalTree.add(new IntervalNode(range.getStart(), range.getEnd(), name));
456+
}
457+
}
458+
Collections.sort(fIntervalTree, Comparator.comparingLong(n -> n.start));
430459
}
431460

432461
/**
@@ -517,11 +546,7 @@ public IntegerDefinition createDefinition(@Nullable IDefinitionScope definitionS
517546
input.setByteOrder(fByteOrder);
518547
long value = read(input);
519548
input.setByteOrder(byteOrder);
520-
if (fMappings.size() == 0) {
521-
return new IntegerDefinition(this, definitionScope, fieldName, value);
522-
}
523-
String mappingName = getMappingForValue(value);
524-
return new IntegerDefinition(this, definitionScope, fieldName, value, mappingName);
549+
return new IntegerDefinition(this, definitionScope, fieldName, value);
525550
}
526551

527552
@Override
@@ -682,25 +707,37 @@ private boolean isBinaryEquivalent(IntegerDeclaration other) {
682707
return !((fLength != BYTE_ALIGN) && !fByteOrder.equals(other.fByteOrder));
683708
}
684709

685-
private String getMappingForValue(long value) {
686-
String mapping = ""; //$NON-NLS-1$
687-
int count = 0;
688-
for (Map.Entry<String, List<IntegerRange>> entry : fMappings.entrySet()) {
689-
String mappingName = entry.getKey();
690-
List<IntegerRange> ranges = entry.getValue();
691-
692-
for (IntegerRange range : ranges) {
693-
if (range.getStart() <= value && value <= range.getEnd()) {
694-
if (count != 0) {
695-
mapping += " " + mappingName; //$NON-NLS-1$
696-
} else {
697-
mapping += mappingName;
698-
}
699-
count++;
710+
String getMappingForValue(long value) {
711+
if (fIntervalTree.isEmpty()) {
712+
return ""; //$NON-NLS-1$
713+
}
700714

701-
}
715+
List<String> matches = new ArrayList<>();
716+
717+
// Binary search for rightmost node with start <= value
718+
int left = 0, right = fIntervalTree.size() - 1;
719+
int lastValid = -1;
720+
721+
while (left <= right) {
722+
int mid = (left + right) / 2;
723+
if (fIntervalTree.get(mid).start <= value) {
724+
lastValid = mid;
725+
left = mid + 1;
726+
} else {
727+
right = mid - 1;
702728
}
703729
}
704-
return mapping;
730+
731+
// Check all nodes from lastValid backwards for overlaps
732+
for (int i = lastValid; i >= 0; i--) {
733+
IntervalNode node = fIntervalTree.get(i);
734+
if (node.end < value) {
735+
break;
736+
}
737+
matches.add(node.name);
738+
}
739+
740+
return matches.isEmpty() ? "" : Objects.requireNonNull(String.join(" ", matches)); //$NON-NLS-1$ //$NON-NLS-2$
705741
}
742+
706743
}

ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/IntegerDefinition.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public final class IntegerDefinition extends SimpleDatatypeDefinition {
4141
private static final int INT_BASE_8 = 8;
4242
private static final int INT_BASE_2 = 2;
4343
private final long fValue;
44-
private final String fMapping;
44+
private String fMapping;
4545

4646
// ------------------------------------------------------------------------
4747
// Constructors
@@ -107,6 +107,9 @@ public long getValue() {
107107
* @since 4.6
108108
*/
109109
public String getMappings() {
110+
if (fMapping == null) {
111+
fMapping = getDeclaration().getMappingForValue(fValue);
112+
}
110113
return fMapping;
111114
}
112115

0 commit comments

Comments
 (0)