From 70ce4ca4cfb0ce22e01d05926950a64993c7b953 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Mon, 28 Feb 2022 10:16:47 -0500 Subject: [PATCH] GP-1727: Cache viewport spans in DBTraceMemorySpace --- .../database/memory/DBTraceMemorySpace.java | 20 ++++++------- .../trace/util/DefaultTraceTimeViewport.java | 30 ++++++++++++++----- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemorySpace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemorySpace.java index 9da4b8e646..e2fcb0053f 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemorySpace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemorySpace.java @@ -43,8 +43,7 @@ import ghidra.trace.database.thread.DBTraceThread; import ghidra.trace.model.*; import ghidra.trace.model.Trace.*; import ghidra.trace.model.memory.*; -import ghidra.trace.util.TraceChangeRecord; -import ghidra.trace.util.TraceViewportSpanIterator; +import ghidra.trace.util.*; import ghidra.util.*; import ghidra.util.AddressIteratorAdapter; import ghidra.util.database.*; @@ -92,6 +91,8 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace .build() .asMap(); + protected final DefaultTraceTimeViewport viewport; + public DBTraceMemorySpace(DBTraceMemoryManager manager, DBHandle dbh, AddressSpace space, DBTraceSpaceEntry ent) throws IOException, VersionException { this.manager = manager; @@ -126,6 +127,8 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace true); this.blocksByOffset = blockStore.getIndex(OffsetSnap.class, DBTraceMemoryBlockEntry.LOCATION_COLUMN); + + this.viewport = new DefaultTraceTimeViewport(trace); } private void regionCacheEntryRemoved( @@ -387,9 +390,7 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace @Override public Entry getViewState(long snap, Address address) { - TraceViewportSpanIterator spit = new TraceViewportSpanIterator(trace, snap); - while (spit.hasNext()) { - Range span = spit.next(); + for (Range span : viewport.getOrderedSpans(snap)) { TraceMemoryState state = getState(span.upperEndpoint(), address); switch (state) { case KNOWN: @@ -415,9 +416,7 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace @Override public Entry getViewMostRecentStateEntry(long snap, Address address) { - TraceViewportSpanIterator spit = new TraceViewportSpanIterator(trace, snap); - while (spit.hasNext()) { - Range span = spit.next(); + for (Range span: viewport.getOrderedSpans(snap)) { Entry entry = stateMapSpace.reduce(TraceAddressSnapRangeQuery.mostRecent(address, span)) .firstEntry(); @@ -750,9 +749,8 @@ public class DBTraceMemorySpace implements Unfinished, TraceMemorySpace, DBTrace } Map sources = new TreeMap<>(); AddressSet remains = new AddressSet(toRead); - TraceViewportSpanIterator spit = new TraceViewportSpanIterator(trace, snap); - spans: while (spit.hasNext()) { - Range span = spit.next(); + + spans: for (Range span : viewport.getOrderedSpans(snap)) { Iterator arit = getAddressesWithState(span, s -> s == TraceMemoryState.KNOWN).iterator(start, true); while (arit.hasNext()) { diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/DefaultTraceTimeViewport.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/DefaultTraceTimeViewport.java index d008157155..a78a04dbef 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/DefaultTraceTimeViewport.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/util/DefaultTraceTimeViewport.java @@ -100,22 +100,20 @@ public class DefaultTraceTimeViewport implements TraceTimeViewport { } protected final Trace trace; - protected final TraceTimeManager timeManager; /** - * NB: This is the syncing object for the viewport. If there's even a chance an operation may - * need the DB's lock, esp., considering user callbacks, then it must first acquire the - * DB lock. + * NB: This is also the syncing object for the viewport. If there's even a chance an operation + * may need the DB's lock, esp., considering user callbacks, then it must first acquire + * the DB lock. */ - protected final List> ordered = new ArrayList<>(); + protected final List> ordered = new ArrayList<>(List.of(Range.singleton(0L))); protected final RangeSet spanSet = TreeRangeSet.create(); protected final ForSnapshotsListener listener = new ForSnapshotsListener(); protected final ListenerSet changeListeners = new ListenerSet<>(Runnable.class); - protected long snap; + protected long snap = 0; public DefaultTraceTimeViewport(Trace trace) { this.trace = trace; - this.timeManager = trace.getTimeManager(); trace.addCloseListener(listener); trace.addListener(listener); } @@ -263,7 +261,7 @@ public class DefaultTraceTimeViewport implements TraceTimeViewport { RangeSet spanSet = TreeRangeSet.create(); List> ordered = new ArrayList<>(); try (LockHold hold = trace.lockRead()) { - collectForkRanges(timeManager, snap, spanSet, ordered); + collectForkRanges(trace.getTimeManager(), snap, spanSet, ordered); } synchronized (this.ordered) { this.spanSet.clear(); @@ -276,6 +274,9 @@ public class DefaultTraceTimeViewport implements TraceTimeViewport { } public void setSnap(long snap) { + if (this.snap == snap) { + return; + } this.snap = snap; refreshSnapRanges(); } @@ -326,6 +327,19 @@ public class DefaultTraceTimeViewport implements TraceTimeViewport { } } + public List> getOrderedSpans() { + synchronized (ordered) { + return List.copyOf(ordered); + } + } + + public List> getOrderedSpans(long snap) { + synchronized (ordered) { + setSnap(snap); + return getOrderedSpans(); + } + } + @Override public List getOrderedSnaps() { synchronized (ordered) {