Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Further imrpove RamSearch performance
- switch _watchList from a List to an array - more Domain.EnterExit usage
- Loading branch information
Showing
1 changed file
with
85 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,10 +14,10 @@ public class RamSearchEngine | |
{ | ||
private Compare _compareTo = Compare.Previous; | ||
|
||
private List<IMiniWatch> _watchList = new List<IMiniWatch>(); | ||
private IMiniWatch[] _watchList; | ||
private readonly SearchEngineSettings _settings; | ||
private readonly UndoHistory<IEnumerable<IMiniWatch>> _history = new UndoHistory<IEnumerable<IMiniWatch>>(true, new List<IMiniWatch>()); //TODO use IList instead of IEnumerable and stop calling `.ToList()` (i.e. cloning) on reads and writes? | ||
private bool _isSorted = true; // Tracks whether or not the list is sorted by address, if it is, binary search can be used for finding watches | ||
private readonly UndoHistory<IEnumerable<IMiniWatch>> _history = new UndoHistory<IEnumerable<IMiniWatch>>(true, new List<IMiniWatch>()); //TODO use IList instead of IEnumerable and stop calling `.ToArray()` (i.e. cloning) on reads and writes? | ||
private bool _isSorted = true; // Tracks whether or not the array is sorted by address, if it is, binary search can be used for finding watches | ||
|
||
public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomains) | ||
{ | ||
|
@@ -55,53 +55,56 @@ public void Start() | |
listSize /= (int)_settings.Size; | ||
} | ||
|
||
_watchList = new List<IMiniWatch>((int)listSize); | ||
_watchList = new IMiniWatch[listSize]; | ||
|
||
switch (_settings.Size) | ||
using (Domain.EnterExit()) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
Morilli
Author
Collaborator
|
||
{ | ||
default: | ||
case WatchSize.Byte: | ||
for (int i = 0; i < domain.Size; i++) | ||
{ | ||
if (_settings.IsDetailed()) | ||
{ | ||
_watchList.Add(new MiniByteWatchDetailed(domain, i)); | ||
} | ||
else | ||
switch (_settings.Size) | ||
{ | ||
default: | ||
case WatchSize.Byte: | ||
for (int i = 0; i < domain.Size; i++) | ||
{ | ||
_watchList.Add(new MiniByteWatch(domain, i)); | ||
if (_settings.IsDetailed()) | ||
{ | ||
_watchList[i] = new MiniByteWatchDetailed(domain, i); | ||
} | ||
else | ||
{ | ||
_watchList[i] = new MiniByteWatch(domain, i); | ||
} | ||
} | ||
} | ||
|
||
break; | ||
case WatchSize.Word: | ||
for (int i = 0; i < domain.Size - 1; i += _settings.CheckMisAligned ? 1 : 2) | ||
{ | ||
if (_settings.IsDetailed()) | ||
{ | ||
_watchList.Add(new MiniWordWatchDetailed(domain, i, _settings.BigEndian)); | ||
} | ||
else | ||
break; | ||
case WatchSize.Word: | ||
for (int i = 0; i < domain.Size - 1; i += _settings.CheckMisAligned ? 1 : 2) | ||
{ | ||
_watchList.Add(new MiniWordWatch(domain, i, _settings.BigEndian)); | ||
if (_settings.IsDetailed()) | ||
{ | ||
_watchList[i] = new MiniWordWatchDetailed(domain, i, _settings.BigEndian); | ||
} | ||
else | ||
{ | ||
_watchList[i] = new MiniWordWatch(domain, i, _settings.BigEndian); | ||
} | ||
} | ||
} | ||
|
||
break; | ||
case WatchSize.DWord: | ||
for (int i = 0; i < domain.Size - 3; i += _settings.CheckMisAligned ? 1 : 4) | ||
{ | ||
if (_settings.IsDetailed()) | ||
break; | ||
case WatchSize.DWord: | ||
for (int i = 0; i < domain.Size - 3; i += _settings.CheckMisAligned ? 1 : 4) | ||
{ | ||
_watchList.Add(new MiniDWordWatchDetailed(domain, i, _settings.BigEndian)); | ||
} | ||
else | ||
{ | ||
_watchList.Add(new MiniDWordWatch(domain, i, _settings.BigEndian)); | ||
if (_settings.IsDetailed()) | ||
{ | ||
_watchList[i] = new MiniDWordWatchDetailed(domain, i, _settings.BigEndian); | ||
} | ||
else | ||
{ | ||
_watchList[i] = new MiniDWordWatch(domain, i, _settings.BigEndian); | ||
} | ||
} | ||
} | ||
|
||
break; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
|
@@ -122,29 +125,32 @@ public void Start() | |
|
||
public int DoSearch() | ||
{ | ||
int before = _watchList.Count; | ||
int before = _watchList.Length; | ||
|
||
_watchList = _compareTo switch | ||
using (Domain.EnterExit()) | ||
{ | ||
Compare.Previous => ComparePrevious(_watchList).ToList(), | ||
Compare.SpecificValue => CompareSpecificValue(_watchList).ToList(), | ||
Compare.SpecificAddress => CompareSpecificAddress(_watchList).ToList(), | ||
Compare.Changes => CompareChanges(_watchList).ToList(), | ||
Compare.Difference => CompareDifference(_watchList).ToList(), | ||
_ => ComparePrevious(_watchList).ToList() | ||
}; | ||
|
||
if (_settings.PreviousType == PreviousType.LastSearch) | ||
{ | ||
SetPreviousToCurrent(); | ||
_watchList = _compareTo switch | ||
{ | ||
Compare.Previous => ComparePrevious(_watchList).ToArray(), | ||
Compare.SpecificValue => CompareSpecificValue(_watchList).ToArray(), | ||
Compare.SpecificAddress => CompareSpecificAddress(_watchList).ToArray(), | ||
Compare.Changes => CompareChanges(_watchList).ToArray(), | ||
Compare.Difference => CompareDifference(_watchList).ToArray(), | ||
_ => ComparePrevious(_watchList).ToArray() | ||
}; | ||
|
||
if (_settings.PreviousType == PreviousType.LastSearch) | ||
{ | ||
SetPreviousToCurrent(); | ||
} | ||
} | ||
|
||
if (UndoEnabled) | ||
{ | ||
_history.AddState(_watchList.ToList()); | ||
_history.AddState(_watchList.ToArray()); | ||
} | ||
|
||
return before - _watchList.Count; | ||
return before - _watchList.Length; | ||
} | ||
|
||
public bool Preview(long address) | ||
|
@@ -164,7 +170,7 @@ public bool Preview(long address) | |
}; | ||
} | ||
|
||
public int Count => _watchList.Count; | ||
public int Count => _watchList.Length; | ||
|
||
public SearchMode Mode => _settings.Mode; | ||
|
||
|
@@ -198,12 +204,12 @@ public void Update() | |
{ | ||
if (_settings.IsDetailed()) | ||
{ | ||
using (_settings.Domain.EnterExit()) | ||
{ | ||
foreach (IMiniWatchDetails watch in _watchList) | ||
{ | ||
watch.Update(_settings.PreviousType, _settings.Domain, _settings.BigEndian); | ||
} | ||
using (_settings.Domain.EnterExit()) | ||
{ | ||
foreach (IMiniWatchDetails watch in _watchList) | ||
{ | ||
watch.Update(_settings.PreviousType, _settings.Domain, _settings.BigEndian); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -225,7 +231,7 @@ public void SetPreviousType(PreviousType type) | |
|
||
public void SetPreviousToCurrent() | ||
{ | ||
_watchList.ForEach(w => w.SetPreviousToCurrent(_settings.Domain, _settings.BigEndian)); | ||
Array.ForEach(_watchList, w => w.SetPreviousToCurrent(_settings.Domain, _settings.BigEndian)); | ||
} | ||
|
||
public void ClearChangeCounts() | ||
|
@@ -247,7 +253,7 @@ public void RemoveSmallWatchRange(IEnumerable<Watch> watches) | |
{ | ||
if (UndoEnabled) | ||
{ | ||
_history.AddState(_watchList.ToList()); | ||
_history.AddState(_watchList.ToArray()); | ||
} | ||
|
||
var addresses = watches.Select(w => w.Address); | ||
|
@@ -258,11 +264,11 @@ public void RemoveRange(IEnumerable<int> indices) | |
{ | ||
if (UndoEnabled) | ||
{ | ||
_history.AddState(_watchList.ToList()); | ||
_history.AddState(_watchList.ToArray()); | ||
} | ||
|
||
var removeList = indices.Select(i => _watchList[i]); // This will fail after int.MaxValue but RAM Search fails on domains that large anyway | ||
_watchList = _watchList.Except(removeList).ToList(); | ||
_watchList = _watchList.Except(removeList).ToArray(); | ||
} | ||
|
||
public void RemoveAddressRange(IEnumerable<long> addresses) | ||
|
@@ -274,7 +280,7 @@ public void AddRange(IEnumerable<long> addresses, bool append) | |
{ | ||
if (!append) | ||
{ | ||
_watchList.Clear(); | ||
Array.Clear(_watchList, 0, _watchList.Length); | ||
} | ||
|
||
var list = _settings.Size switch | ||
|
@@ -294,13 +300,13 @@ public void Sort(string column, bool reverse) | |
switch (column) | ||
{ | ||
case WatchList.Address: | ||
_watchList = _watchList.OrderBy(w => w.Address, reverse).ToList(); | ||
_watchList = _watchList.OrderBy(w => w.Address, reverse).ToArray(); | ||
break; | ||
case WatchList.Value: | ||
_watchList = _watchList.OrderBy(w => GetValue(w.Address), reverse).ToList(); | ||
_watchList = _watchList.OrderBy(w => GetValue(w.Address), reverse).ToArray(); | ||
break; | ||
case WatchList.Prev: | ||
_watchList = _watchList.OrderBy(w => w.Previous, reverse).ToList(); | ||
_watchList = _watchList.OrderBy(w => w.Previous, reverse).ToArray(); | ||
break; | ||
case WatchList.ChangesCol: | ||
if (_settings.IsDetailed()) | ||
|
@@ -309,12 +315,12 @@ public void Sort(string column, bool reverse) | |
.Cast<IMiniWatchDetails>() | ||
.OrderBy(w => w.ChangeCount, reverse) | ||
.Cast<IMiniWatch>() | ||
.ToList(); | ||
.ToArray(); | ||
} | ||
|
||
break; | ||
case WatchList.Diff: | ||
_watchList = _watchList.OrderBy(w => GetValue(w.Address) - w.Previous, reverse).ToList(); | ||
_watchList = _watchList.OrderBy(w => GetValue(w.Address) - w.Previous, reverse).ToArray(); | ||
break; | ||
} | ||
} | ||
|
@@ -333,26 +339,26 @@ public bool UndoEnabled | |
|
||
public int Undo() | ||
{ | ||
int origCount = _watchList.Count; | ||
int origCount = _watchList.Length; | ||
if (UndoEnabled) | ||
{ | ||
_watchList = _history.Undo().ToList(); | ||
return _watchList.Count - origCount; | ||
_watchList = _history.Undo().ToArray(); | ||
return _watchList.Length - origCount; | ||
} | ||
|
||
return _watchList.Count; | ||
return _watchList.Length; | ||
} | ||
|
||
public int Redo() | ||
{ | ||
int origCount = _watchList.Count; | ||
int origCount = _watchList.Length; | ||
if (UndoEnabled) | ||
{ | ||
_watchList = _history.Redo().ToList(); | ||
return origCount - _watchList.Count; | ||
_watchList = _history.Redo().ToArray(); | ||
return origCount - _watchList.Length; | ||
} | ||
|
||
return _watchList.Count; | ||
return _watchList.Length; | ||
} | ||
|
||
private IEnumerable<IMiniWatch> ComparePrevious(IEnumerable<IMiniWatch> watchList) | ||
|
IIRC you can do
using var _ = Domain.EnterExit();
to avoid indentation? Obviously it delays the disposal until the end of the scope but it would have been the same in this case.