The existing trace framework only had a flat text formatter, so every question became 'dump millions of lines, then grep'. This session that cost a long wrong detour. Add, all observe-only (parity preserved): - HistogramTraceSink: execution counts per opcode AND per call-site (script:pc) with a sample operand. Dumped sorted after the run. This is what instantly showed the 493k headless 'sleep's are INPUTNAME.BIN:0x1c3 (a name-entry poll loop), not the opening. - TraceSinkBase: tracks the frame stack -> attributes each step to its REAL script (nested call-script frames included) = the 'which script is this pc in?' answer a bare step trace can't give. - TextTraceSink: op-filter (--trace-ops sleep,draw-texture,...) + script:pc tags. - CompositeTraceSink: fan-out (text + histogram + Godot's call-script queue). - OpcodeTable.ByLabel: mnemonic -> opcode for --trace-ops. - CLI: --trace-histogram, --trace-ops, robust --trace-file (mkdir -p). - Godot: --trace-histogram <file> profiles the REAL run (headless flow diverges: real run to page 1 is 562 steps / 0 sleeps vs headless 2M steps / 493k sleeps). - Also: --sleep-scale <f> debug knob to slow the paced opening for inspection. Engine 56/56 (4 new); sweep parity 284/13; Godot builds + dogfooded end-to-end. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
23 lines
972 B
C#
23 lines
972 B
C#
namespace Age.Engine.Model;
|
|
public sealed class OpcodeTable
|
|
{
|
|
private readonly IReadOnlyDictionary<int, (string Label, int Argc)> _t;
|
|
public OpcodeTable(IReadOnlyDictionary<int, (string, int)> t) => _t = t;
|
|
public int Count => _t.Count;
|
|
public bool TryGet(int op, out string label, out int argc)
|
|
{
|
|
if (_t.TryGetValue(op, out var e)) { label = e.Label; argc = e.Argc; return true; }
|
|
label = ""; argc = -1; return false;
|
|
}
|
|
public string Label(int op) => _t.TryGetValue(op, out var e) ? e.Label : "";
|
|
public int Argc(int op) => _t.TryGetValue(op, out var e) ? e.Argc : -1;
|
|
|
|
/// <summary>Reverse lookup: opcode by mnemonic label (e.g. "sleep" -> 0xc8), or null if none.
|
|
/// Used by --trace-ops to let a diagnostic filter name ops by mnemonic instead of raw hex.</summary>
|
|
public int? ByLabel(string label)
|
|
{
|
|
foreach (var kv in _t) if (kv.Value.Label == label) return kv.Key;
|
|
return null;
|
|
}
|
|
}
|