Speedup profiler symbol lookup for 6502

This commit is contained in:
Adrian Conlon 2024-07-01 23:30:30 +01:00
parent 0c8ed57b0d
commit 1321a909d0
6 changed files with 65 additions and 40 deletions

View File

@ -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));

View File

@ -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");
}
}
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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));
}
}
}