public sealed class LazyDebugStats
Namespace: Moka.Blazor.Json.Models
Properties
| Name | Description |
|---|---|
AvgParseTime |
Average subtree parse time. |
CacheHitRate |
Cache hit rate as a percentage. |
CacheHits |
Number of times a cached subtree was reused. |
CacheMisses |
Number of times a subtree had to be parsed fresh (cache miss). |
CoveragePercent |
Percentage of unique document bytes that have been parsed. |
CumulativeBytesParsed |
Cumulative bytes parsed across all parse calls (may double-count overlapping regions). |
IndexEntries |
Number of entries in the structural index. |
LazyIndexOps |
Number of lazy child-indexing operations. |
MaxParseTime |
Slowest subtree parse. |
MinParseTime |
Fastest subtree parse. |
RecentParses |
Recent parse operations with path, size, and duration. |
SubtreeParseCount |
Total number of subtree parse operations (including overlapping regions). |
TotalBytes |
Total document size in bytes. |
TotalParseTime |
Total time spent parsing subtrees. |
UniqueBytesParsed |
Unique bytes covered by at least one parse (no double-counting). |
AvgParseTime
TimeSpan LazyDebugStats.AvgParseTime { get; }
Average subtree parse time.
CacheHitRate
double LazyDebugStats.CacheHitRate { get; }
Cache hit rate as a percentage.
CacheHits
int LazyDebugStats.CacheHits { get; }
Number of times a cached subtree was reused.
CacheMisses
int LazyDebugStats.CacheMisses { get; }
Number of times a subtree had to be parsed fresh (cache miss).
CoveragePercent
double LazyDebugStats.CoveragePercent { get; }
Percentage of unique document bytes that have been parsed.
CumulativeBytesParsed
long LazyDebugStats.CumulativeBytesParsed { get; set; }
Cumulative bytes parsed across all parse calls (may double-count overlapping regions).
IndexEntries
int LazyDebugStats.IndexEntries { get; set; }
Number of entries in the structural index.
LazyIndexOps
int LazyDebugStats.LazyIndexOps { get; }
Number of lazy child-indexing operations.
MaxParseTime
TimeSpan LazyDebugStats.MaxParseTime { get; set; }
Slowest subtree parse.
MinParseTime
TimeSpan LazyDebugStats.MinParseTime { get; set; }
Fastest subtree parse.
RecentParses
List<LazyParseEntry> LazyDebugStats.RecentParses { get; }
Recent parse operations with path, size, and duration.
SubtreeParseCount
int LazyDebugStats.SubtreeParseCount { get; set; }
Total number of subtree parse operations (including overlapping regions).
TotalBytes
long LazyDebugStats.TotalBytes { get; set; }
Total document size in bytes.
TotalParseTime
TimeSpan LazyDebugStats.TotalParseTime { get; set; }
Total time spent parsing subtrees.
UniqueBytesParsed
long LazyDebugStats.UniqueBytesParsed { get; set; }
Unique bytes covered by at least one parse (no double-counting).
Methods
| Name | Description |
|---|---|
RecordCacheHit() |
Records a cache hit. |
RecordCacheMiss() |
Records a cache miss. |
RecordLazyIndex() |
Records a lazy index operation. |
RecordParse(…) |
Records a subtree parse operation. |
RecordCacheHit()
void LazyDebugStats.RecordCacheHit()
Records a cache hit.
RecordCacheMiss()
void LazyDebugStats.RecordCacheMiss()
Records a cache miss.
RecordLazyIndex()
void LazyDebugStats.RecordLazyIndex()
Records a lazy index operation.
RecordParse(string path, long startOffset, long length, TimeSpan duration)
void LazyDebugStats.RecordParse(string path, long startOffset, long length, TimeSpan duration)
Records a subtree parse operation.
View Source
/// <summary>
/// Debug statistics for lazy JSON document source.
/// Used by Moka.Blazor.Json.Diagnostics to render the debug overlay.
/// </summary>
public sealed class LazyDebugStats
{
private readonly Lock _lock = new();
private readonly List<ParsedRegion> _parsedRegions = [];
private int _cacheHits;
private int _cacheMisses;
private int _lazyIndexOps;
/// <summary>Total document size in bytes.</summary>
public long TotalBytes { get; set; }
/// <summary>Number of entries in the structural index.</summary>
public int IndexEntries { get; set; }
/// <summary>Total number of subtree parse operations (including overlapping regions).</summary>
public int SubtreeParseCount { get; private set; }
/// <summary>Cumulative bytes parsed across all parse calls (may double-count overlapping regions).</summary>
public long CumulativeBytesParsed { get; private set; }
/// <summary>Unique bytes covered by at least one parse (no double-counting).</summary>
public long UniqueBytesParsed { get; private set; }
/// <summary>Number of times a cached subtree was reused.</summary>
public int CacheHits => _cacheHits;
/// <summary>Number of times a subtree had to be parsed fresh (cache miss).</summary>
public int CacheMisses => _cacheMisses;
/// <summary>Number of lazy child-indexing operations.</summary>
public int LazyIndexOps => _lazyIndexOps;
/// <summary>Total time spent parsing subtrees.</summary>
public TimeSpan TotalParseTime { get; private set; }
/// <summary>Fastest subtree parse.</summary>
public TimeSpan MinParseTime { get; private set; } = TimeSpan.MaxValue;
/// <summary>Slowest subtree parse.</summary>
public TimeSpan MaxParseTime { get; private set; }
/// <summary>Average subtree parse time.</summary>
public TimeSpan AvgParseTime => SubtreeParseCount > 0 ? TotalParseTime / SubtreeParseCount : TimeSpan.Zero;
/// <summary>Percentage of unique document bytes that have been parsed.</summary>
public double CoveragePercent => TotalBytes > 0 ? (double)UniqueBytesParsed / TotalBytes * 100 : 0;
/// <summary>Cache hit rate as a percentage.</summary>
public double CacheHitRate
{
get
{
int total = _cacheHits + _cacheMisses;
return total > 0 ? (double)_cacheHits / total * 100 : 0;
}
}
/// <summary>Recent parse operations with path, size, and duration.</summary>
public List<LazyParseEntry> RecentParses { get; } = new(20);
/// <summary>Records a subtree parse operation.</summary>
public void RecordParse(string path, long startOffset, long length, TimeSpan duration)
{
lock (_lock)
{
SubtreeParseCount++;
CumulativeBytesParsed += length;
TotalParseTime += duration;
if (duration < MinParseTime)
{
MinParseTime = duration;
}
if (duration > MaxParseTime)
{
MaxParseTime = duration;
}
InsertSorted(new ParsedRegion(startOffset, startOffset + length));
RecalculateUniqueCoverage();
if (RecentParses.Count >= 20)
{
RecentParses.RemoveAt(0);
}
RecentParses.Add(new LazyParseEntry(path, length, duration));
}
}
/// <summary>Records a cache hit.</summary>
public void RecordCacheHit() => Interlocked.Increment(ref _cacheHits);
/// <summary>Records a cache miss.</summary>
public void RecordCacheMiss() => Interlocked.Increment(ref _cacheMisses);
/// <summary>Records a lazy index operation.</summary>
public void RecordLazyIndex() => Interlocked.Increment(ref _lazyIndexOps);
/// <summary>
/// Inserts a region in sorted order by Start offset using binary search.
/// Avoids re-sorting the entire list on every parse operation.
/// </summary>
private void InsertSorted(ParsedRegion region)
{
int lo = 0, hi = _parsedRegions.Count;
while (lo < hi)
{
int mid = (lo + hi) / 2;
if (_parsedRegions[mid].Start <= region.Start)
{
lo = mid + 1;
}
else
{
hi = mid;
}
}
_parsedRegions.Insert(lo, region);
}
private void RecalculateUniqueCoverage()
{
if (_parsedRegions.Count == 0)
{
UniqueBytesParsed = 0;
return;
}
// _parsedRegions is maintained in sorted order by InsertSorted
long uniqueBytes = 0;
long mergedStart = _parsedRegions[0].Start;
long mergedEnd = _parsedRegions[0].End;
for (int i = 1; i < _parsedRegions.Count; i++)
{
if (_parsedRegions[i].Start <= mergedEnd)
{
mergedEnd = Math.Max(mergedEnd, _parsedRegions[i].End);
}
else
{
uniqueBytes += mergedEnd - mergedStart;
mergedStart = _parsedRegions[i].Start;
mergedEnd = _parsedRegions[i].End;
}
}
uniqueBytes += mergedEnd - mergedStart;
UniqueBytesParsed = uniqueBytes;
}
private readonly record struct ParsedRegion(long Start, long End);
}