mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2025-02-19 01:30:29 +00:00
Speedup profiler symbol lookup for 6502
This commit is contained in:
parent
0c8ed57b0d
commit
1321a909d0
@ -505,12 +505,12 @@ namespace EightBit
|
||||
|
||||
private bool TryGetLabel(ushort absolute, out string name)
|
||||
{
|
||||
return this.symbols.TryGetQualifiedLabel(absolute, out name);
|
||||
return this.symbols.TryGetQualifiedLabelByAddress(absolute, out name);
|
||||
}
|
||||
|
||||
private string MaybeGetLabel(ushort absolute)
|
||||
{
|
||||
return this.symbols.MaybeGetQualifiedLabel(absolute);
|
||||
return this.symbols.MaybeGetQualifiedLabelByAddress(absolute);
|
||||
}
|
||||
|
||||
private string MaybeGetCodeLabel(ushort absolute)
|
||||
@ -534,7 +534,7 @@ namespace EightBit
|
||||
|
||||
private bool TryGetConstant(ushort value, out string name)
|
||||
{
|
||||
return this.symbols.TryGetQualifiedEquate(value, out name);
|
||||
return this.symbols.TryGetQualifiedEquateyValue(value, out name);
|
||||
}
|
||||
|
||||
private string ConvertConstantByte(ushort address) => this.ConvertConstant(this.GetByte(address));
|
||||
|
@ -4,10 +4,12 @@
|
||||
{
|
||||
namespace Symbols
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class IdentifiableSection : Section
|
||||
{
|
||||
[SectionProperty("id")]
|
||||
public int ID => this.TakeInteger("id");
|
||||
public int ID { get; private set; }
|
||||
|
||||
protected IdentifiableSection(Parser container)
|
||||
: base(container)
|
||||
@ -74,6 +76,12 @@
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public override void Parse(IDictionary<string, string> entries)
|
||||
{
|
||||
base.Parse(entries);
|
||||
this.ID = this.TakeInteger("id");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,8 @@
|
||||
|
||||
private static IEnumerable<T> SelectNameMatching<T>(string name, IEnumerable<T> items) where T : NamedSection => from item in items where item.Name == name select item;
|
||||
|
||||
private static IEnumerable<T> SelectIdMatching<T>(int id, IEnumerable<T> items) where T : IdentifiableSection => from item in items where item.ID == id select item;
|
||||
|
||||
#region Label lookup
|
||||
|
||||
public void AddLabel(Symbol symbol)
|
||||
@ -76,19 +78,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
private List<Symbol> LookupLabels(int address) => this.Addresses.TryGetValue(address, out var symbols) ? symbols : [];
|
||||
private List<Symbol> LookupLabelsByAddress(int address) => this.Addresses.TryGetValue(address, out var symbols) ? symbols : [];
|
||||
|
||||
public Symbol? LookupLabel(int address)
|
||||
public Symbol? LookupLabelByAddress(int address)
|
||||
{
|
||||
var labels = this.LookupLabels(address);
|
||||
var labels = this.LookupLabelsByAddress(address);
|
||||
return labels.Count > 0 ? labels[0] : null;
|
||||
}
|
||||
|
||||
private IEnumerable<Symbol> LookupLabels(string name) => SelectNameMatching(name, this.Labels);
|
||||
private IEnumerable<Symbol> LookupLabelsByName(string name) => SelectNameMatching(name, this.Labels);
|
||||
|
||||
public Symbol? LookupLabel(string name)
|
||||
public Symbol? LookupLabelByName(string name)
|
||||
{
|
||||
var labels = this.LookupLabels(name).ToList();
|
||||
var labels = this.LookupLabelsByName(name).ToList();
|
||||
return labels.Count > 0 ? labels[0] : null;
|
||||
}
|
||||
|
||||
private IEnumerable<Symbol> LookupLabelsByID(int id) => SelectIdMatching(id, this.Labels);
|
||||
|
||||
public Symbol? LookupLabelByID(int id)
|
||||
{
|
||||
var labels = this.LookupLabelsByID(id).ToList();
|
||||
return labels.Count > 0 ? labels[0] : null;
|
||||
}
|
||||
|
||||
@ -119,11 +129,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
private List<Symbol> LookupEquates(int constant) => this.Constants.TryGetValue(constant, out var symbols) ? symbols : [];
|
||||
private List<Symbol> LookupEquatesByValue(int constant) => this.Constants.TryGetValue(constant, out var symbols) ? symbols : [];
|
||||
|
||||
public Symbol? LookupEquate(int constant)
|
||||
public Symbol? LookupEquateByValue(int constant)
|
||||
{
|
||||
var equates = this.LookupEquates(constant);
|
||||
var equates = this.LookupEquatesByValue(constant);
|
||||
return equates.Count > 0 ? equates[0] : null;
|
||||
}
|
||||
|
||||
@ -131,7 +141,7 @@
|
||||
|
||||
#region Scope lookup
|
||||
|
||||
private int LocateScope(int address)
|
||||
private int LocateScopeByAddress(int address)
|
||||
{
|
||||
var low = 0;
|
||||
var high = this.AddressableScopes.Count - 1;
|
||||
@ -168,12 +178,20 @@
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Scope? LookupScope(int address)
|
||||
public Scope? LookupScopeByAddress(int address)
|
||||
{
|
||||
var index = _scopeAddressCache[address] ?? (_scopeAddressCache[address] = this.LocateScope(address));
|
||||
var index = _scopeAddressCache[address] ?? (_scopeAddressCache[address] = this.LocateScopeByAddress(address));
|
||||
return index == -1 ? null : this.AddressableScopes[index.Value];
|
||||
}
|
||||
|
||||
private IEnumerable<Scope> LookupScopesByID(int id) => SelectIdMatching(id, this.Scopes);
|
||||
|
||||
public Scope? LookupScopeByID(int id)
|
||||
{
|
||||
var scopes = this.LookupScopesByID(id).ToList();
|
||||
return scopes.Count > 0 ? scopes[0] : null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Scope evaluation
|
||||
@ -229,18 +247,18 @@
|
||||
|
||||
#region Qualified symbol lookup
|
||||
|
||||
public bool TryGetQualifiedLabel(ushort absolute, out string label)
|
||||
public bool TryGetQualifiedLabelByAddress(ushort absolute, out string label)
|
||||
{
|
||||
var symbol = this.LookupLabel(absolute);
|
||||
var symbol = this.LookupLabelByAddress(absolute);
|
||||
label = PrefixNamespace(symbol);
|
||||
return symbol != null;
|
||||
}
|
||||
|
||||
public string MaybeGetQualifiedLabel(ushort absolute) => this.TryGetQualifiedLabel(absolute, out var label) ? label : string.Empty;
|
||||
public string MaybeGetQualifiedLabelByAddress(ushort absolute) => this.TryGetQualifiedLabelByAddress(absolute, out var label) ? label : string.Empty;
|
||||
|
||||
public bool TryGetQualifiedEquate(ushort value, out string name)
|
||||
public bool TryGetQualifiedEquateyValue(ushort value, out string name)
|
||||
{
|
||||
var symbol = this.LookupEquate(value);
|
||||
var symbol = this.LookupEquateByValue(value);
|
||||
name = PrefixNamespace(symbol);
|
||||
return symbol != null;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
namespace M6502.Test
|
||||
{
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using EightBit;
|
||||
@ -147,8 +148,7 @@ namespace M6502.Test
|
||||
{
|
||||
if (this.oldPC != this.CPU.PC)
|
||||
{
|
||||
this.oldPC.Low = this.CPU.PC.Low;
|
||||
this.oldPC.High = this.CPU.PC.High;
|
||||
this.oldPC.Assign(this.CPU.PC);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -163,7 +163,7 @@ namespace M6502.Test
|
||||
{
|
||||
var cycles = this.CPU.Cycles;
|
||||
this.cyclesPolled += cycles;
|
||||
System.Diagnostics.Debug.Assert(cycles > 0, "Invalid pollingcycle count");
|
||||
Debug.Assert(cycles > 0, "Invalid pollingcycle count");
|
||||
if (this.cyclesPolled > this.configuration.PollingTickInterval)
|
||||
{
|
||||
this.cyclesPolled = 0;
|
||||
@ -202,8 +202,9 @@ namespace M6502.Test
|
||||
private void Profiler_EmitScope(object? sender, ProfileScopeEventArgs e)
|
||||
{
|
||||
var proportion = (double)e.Cycles / this.profiler.TotalCycleCount;
|
||||
Console.Out.Write(string.Format(CultureInfo.InvariantCulture, "\t[{0:P2}][{1:d9}][{2:d9}]\t{3}\n", proportion, e.Cycles, e.Count, e.Scope));
|
||||
Console.Out.Write(string.Format(CultureInfo.InvariantCulture, "\t[{0:P2}][{1:d9}][{2:d9}]\t{3}\n", proportion, cycles, count, name));
|
||||
var scope = this.symbols.LookupScopeByID(e.ID);
|
||||
Debug.Assert(scope != null);
|
||||
Console.Out.Write(string.Format(CultureInfo.InvariantCulture, "\t[{0:P2}][{1:d9}][{2:d9}]\t{3}\n", proportion, e.Cycles, e.Count, scope.Name));
|
||||
}
|
||||
|
||||
private void Profiler_EmitLine(object? sender, ProfileLineEventArgs e)
|
||||
|
@ -1,8 +1,8 @@
|
||||
namespace EightBit
|
||||
{
|
||||
public class ProfileScopeEventArgs(string scope, int cycles, int count) : EventArgs
|
||||
public class ProfileScopeEventArgs(int id, int cycles, int count) : EventArgs
|
||||
{
|
||||
public string Scope { get; } = scope;
|
||||
public int ID { get; } = id;
|
||||
|
||||
public int Cycles { get; } = cycles;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
private readonly int[] addressProfiles = new int[0x10000];
|
||||
private readonly int[] addressCounts = new int[0x10000];
|
||||
|
||||
private readonly Dictionary<string, int> scopeCycles = [];
|
||||
private readonly Dictionary<int, int> scopeCycles = []; // ID -> Cycles
|
||||
|
||||
private readonly M6502 processor;
|
||||
private readonly Disassembler disassembler;
|
||||
@ -94,13 +94,12 @@
|
||||
this.OnStartingScopeOutput();
|
||||
try
|
||||
{
|
||||
foreach (var (name, cycles) in this.scopeCycles)
|
||||
foreach (var (id, cycles) in this.scopeCycles)
|
||||
{
|
||||
Debug.Assert(name != null);
|
||||
var symbol = this.symbols.LookupLabel(name);
|
||||
var symbol = this.symbols.LookupLabelByID(id);
|
||||
Debug.Assert(symbol != null);
|
||||
var count = this.addressCounts[symbol.Value];
|
||||
this.OnEmitScope(name, cycles, count);
|
||||
this.OnEmitScope(id, cycles, count);
|
||||
}
|
||||
}
|
||||
finally
|
||||
@ -124,14 +123,13 @@
|
||||
|
||||
this.addressProfiles[this.executingAddress] += this.processor.Cycles;
|
||||
|
||||
var scope = this.symbols.LookupScope(this.executingAddress);
|
||||
var scope = this.symbols.LookupScopeByAddress(this.executingAddress);
|
||||
if (scope != null)
|
||||
{
|
||||
var name = scope.Name;
|
||||
Debug.Assert(name != null);
|
||||
if (!this.scopeCycles.TryAdd(name, 0))
|
||||
var id = scope.ID;
|
||||
if (!this.scopeCycles.TryAdd(id, 0))
|
||||
{
|
||||
this.scopeCycles[name] += this.processor.Cycles;
|
||||
this.scopeCycles[id] += this.processor.Cycles;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -171,9 +169,9 @@
|
||||
this.EmitLine?.Invoke(this, new ProfileLineEventArgs(source, cycles, count));
|
||||
}
|
||||
|
||||
private void OnEmitScope(string scope, int cycles, int count)
|
||||
private void OnEmitScope(int id, int cycles, int count)
|
||||
{
|
||||
this.EmitScope?.Invoke(this, new ProfileScopeEventArgs(scope, cycles, count));
|
||||
this.EmitScope?.Invoke(this, new ProfileScopeEventArgs(id, cycles, count));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user