Skip to content

Commit

Permalink
Better reports (#103)
Browse files Browse the repository at this point in the history
* better reports

* better stats
  • Loading branch information
Scooletz committed Jun 23, 2023
1 parent 0c3d404 commit 74a0f5d
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 29 deletions.
34 changes: 24 additions & 10 deletions src/Paprika.Runner/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Paprika.Runner;

public static class Program
{
private const int BlockCount = PersistentDb ? 20_000 : 3_000;
private const int BlockCount = PersistentDb ? 25_000 : 3_000;
private const int AccountsPerBlock = 1000;
private const int MaxReorgDepth = 64;
private const int FinalizeEvery = 32;
Expand All @@ -28,7 +28,7 @@ public static class Program
private const long DbFileSize = PersistentDb ? 256 * Gb : 16 * Gb;
private const long Gb = 1024 * 1024 * 1024L;

private static readonly TimeSpan FlushEvery = TimeSpan.FromSeconds(30);
private static readonly TimeSpan FlushEvery = TimeSpan.FromSeconds(5);

private const int LogEvery = BlockCount / NumberOfLogs;

Expand Down Expand Up @@ -81,7 +81,8 @@ public static async Task Main(String[] args)
}

Console.WriteLine("Initializing db of size {0}GB", DbFileSize / Gb);
Console.WriteLine("Starting benchmark. Flush buffer every: {0}ms", ((int)FlushEvery.TotalMilliseconds).ToString());
Console.WriteLine("Starting benchmark. Flush buffer every: {0}ms",
((int)FlushEvery.TotalMilliseconds).ToString());

PagedDb db = PersistentDb
? PagedDb.MemoryMappedDb(DbFileSize, MaxReorgDepth, dataPath)
Expand Down Expand Up @@ -147,8 +148,9 @@ public static async Task Main(String[] args)

if (actual != expected)
{
throw new InvalidOperationException($"Invalid account state for account number {i} with address {key.ToString()}. " +
$"The expected value is {expected} while the actual is {actual}!");
throw new InvalidOperationException(
$"Invalid account state for account number {i} with address {key.ToString()}. " +
$"The expected value is {expected} while the actual is {actual}!");
}

if (UseStorageEveryNAccounts > 0 && i % UseStorageEveryNAccounts == 0)
Expand Down Expand Up @@ -185,6 +187,9 @@ public static async Task Main(String[] args)
// the final report
ReportReading(counter);

// statistics
layout[info].Update(new Panel("Gathering statistics...").Header("Paprika tree statistics").Expand());

var stats = new StatisticsReporter();
read.Report(stats);
var table = new Table();
Expand All @@ -202,9 +207,18 @@ public static async Task Main(String[] args)
}

var mb = (long)stats.PageCount * Page.PageSize / 1024 / 1024;
var report = new Layout().SplitRows(
new Layout(new Paragraph($"General stats:\n1. Size of this Paprika tree: {mb}MB")).Size(3),
new Layout(table.Expand()));

var types = string.Join(", ", stats.PageTypes.Select(kvp => $"{kvp.Key}: {kvp.Value}"));
var report = new Layout()
.SplitRows(
new Layout(
new Rows(
new Text("General stats:"),
new Text($"1. Size of this Paprika tree: {mb}MB"),
new Text($"2. Types of pages: {types}"),
WriteHistogram(stats.PageAge, "2. Age of pages: ")))
.Size(5),
new Layout(table.Expand()));

layout[info].Update(new Panel(report).Header("Paprika tree statistics").Expand());

Expand Down Expand Up @@ -244,15 +258,15 @@ void ReportReading(int i)

private static Random BuildRandom() => new(RandomSeed);

private static IRenderable WriteHistogram(HistogramBase histogram)
private static IRenderable WriteHistogram(HistogramBase histogram, string prefix = "")
{
string Percentile(int percentile, string color)
{
var value = histogram.GetValueAtPercentile(percentile);
return $"[{color}]P{percentile}: {value,2}[/] ";
}

return new Markup(Percentile(50, "green") + Percentile(90, "yellow") + Percentile(95, "red"));
return new Markup(prefix + Percentile(50, "green") + Percentile(90, "yellow") + Percentile(95, "red"));
}

private static int Writer(Blockchain blockchain, Keccak bigStorageAccount, Random random,
Expand Down
4 changes: 2 additions & 2 deletions src/Paprika/Store/DataPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,11 @@ public void Report(IReporter reporter, IPageResolver resolver, int level)
if (emptyBuckets == 0)
{
// all filled
reporter.Report(level, Payload.BucketCount, new HashingMap(Data.DataSpan).Count);
reporter.ReportDataUsage(level, Payload.BucketCount, new HashingMap(Data.DataSpan).Count);
}
else
{
reporter.Report(level, Payload.BucketCount - emptyBuckets,
reporter.ReportDataUsage(level, Payload.BucketCount - emptyBuckets,
new NibbleBasedMap(Data.DataSpan).Count);
}
}
Expand Down
22 changes: 19 additions & 3 deletions src/Paprika/Store/IReporter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HdrHistogram;
using System.Runtime.InteropServices;
using HdrHistogram;

namespace Paprika.Store;

Expand All @@ -7,15 +8,23 @@ namespace Paprika.Store;
/// </summary>
public interface IReporter
{
void Report(int level, int filledBuckets, int entriesPerPage);
void ReportDataUsage(int level, int filledBuckets, int entriesPerPage);

/// <summary>
/// Reports how many batches ago the page was updated.
/// </summary>
void ReportPage(uint ageInBatches, PageType type);
}

public class StatisticsReporter : IReporter
{
public readonly SortedDictionary<int, Level> Levels = new();
public readonly Dictionary<PageType, int> PageTypes = new();
public int PageCount = 0;

public void Report(int level, int filledBuckets, int entriesPerPage)
public readonly IntHistogram PageAge = new(1_000_000_000, 5);

public void ReportDataUsage(int level, int filledBuckets, int entriesPerPage)
{
if (Levels.TryGetValue(level, out var lvl) == false)
{
Expand All @@ -28,6 +37,13 @@ public void Report(int level, int filledBuckets, int entriesPerPage)
lvl.Entries.RecordValue(entriesPerPage);
}

public void ReportPage(uint ageInBatches, PageType type)
{
PageAge.RecordValue(ageInBatches);
var value = PageTypes.GetValueOrDefault(type);
PageTypes[type] = value + 1;
}

public class Level
{
public readonly IntHistogram ChildCount = new(1000, 5);
Expand Down
42 changes: 28 additions & 14 deletions src/Paprika/Store/PagedDb.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Runtime.InteropServices;
using Nethermind.Int256;
using Paprika.Crypto;
using Paprika.Data;
using Paprika.Store.PageManagers;
Expand Down Expand Up @@ -44,7 +43,9 @@ public class PagedDb : IPageResolver, IDb, IDisposable
private readonly Counter<long> _writes;
private readonly Counter<long> _commits;
private readonly Histogram<float> _commitDuration;
private readonly Histogram<int> _commitPageCount;
private readonly Histogram<int> _commitPageCountTotal;
private readonly Histogram<int> _commitPageCountReused;
private readonly Histogram<int> _commitPageCountNewlyAllocated;
private readonly MetricsExtensions.IAtomicIntGauge _dbSize;

// pool
Expand Down Expand Up @@ -76,7 +77,11 @@ private PagedDb(IPageManager manager, byte historyDepth)
_writes = _meter.CreateCounter<long>("Writes", "Writes", "The number of writes db handles");
_commits = _meter.CreateCounter<long>("Commits", "Commits", "The number of batch commits db handles");
_commitDuration = _meter.CreateHistogram<float>("Commit duration", "ms", "The time it takes to perform a commit");
_commitPageCount = _meter.CreateHistogram<int>("Commit page count", "pages",
_commitPageCountTotal = _meter.CreateHistogram<int>("Commit page count (total)", "pages",
"The number of pages flushed during the commit");
_commitPageCountReused = _meter.CreateHistogram<int>("Commit page count (reused)", "pages",
"The number of pages flushed during the commit");
_commitPageCountNewlyAllocated = _meter.CreateHistogram<int>("Commit page count (new)", "pages",
"The number of pages flushed during the commit");
}

Expand All @@ -96,7 +101,12 @@ private void ReportCommit(TimeSpan elapsed)

private void ReportDbSize(int megabytes) => _dbSize.Set(megabytes);

private void ReportPageCountPerCommit(int pageCount) => _commitPageCount.Record(pageCount);
private void ReportPageCountPerCommit(int totalPageCount, int reused, int newlyAllocated)
{
_commitPageCountTotal.Record(totalPageCount);
_commitPageCountReused.Record(reused);
_commitPageCountNewlyAllocated.Record(newlyAllocated);
}

private void RootInit()
{
Expand Down Expand Up @@ -143,7 +153,7 @@ public IReadOnlyBatch BeginReadOnlyBatch()
lock (_batchLock)
{
var batchId = Root.Header.BatchId;
var batch = new ReadOnlyBatch(this, batchId, Root.Data.AccountPages.ToArray(), Root.Data.Metadata);
var batch = new ReadOnlyBatch(this, batchId, Root.Data.AccountPages.ToArray(), Root.Data.Metadata, Root.Data.NextFreePage);
_batchesReadOnly.Add(batch);
return batch;
}
Expand Down Expand Up @@ -234,11 +244,14 @@ class ReadOnlyBatch : IReadOnlyBatch, IReadOnlyBatchContext
private bool _disposed;

private readonly DbAddress[] _rootDataPages;
private readonly DbAddress _nextFreePage;

public ReadOnlyBatch(PagedDb db, uint batchId, DbAddress[] rootDataPages, Metadata metadata)
public ReadOnlyBatch(PagedDb db, uint batchId, DbAddress[] rootDataPages, Metadata metadata,
DbAddress nextFreePage)
{
_db = db;
_rootDataPages = rootDataPages;
_nextFreePage = nextFreePage;
BatchId = batchId;
Metadata = metadata;
}
Expand Down Expand Up @@ -279,6 +292,13 @@ public void Report(IReporter reporter)
new DataPage(GetAt(addr)).Report(reporter, this, 1);
}
}

for (uint i = _db._historyDepth; i < _nextFreePage.Raw; i++)
{
ref readonly var header = ref GetAt(DbAddress.Page(i)).Header;
var pageBatchId = header.BatchId;
reporter.ReportPage(BatchId - pageBatchId, header.PageType);
}
}

public uint BatchId { get; }
Expand Down Expand Up @@ -401,13 +421,7 @@ private void CheckDisposed()

public void Report(IReporter reporter)
{
foreach (var addr in _root.Data.AccountPages)
{
if (addr.IsNull == false)
{
new DataPage(GetAt(addr)).Report(reporter, this, 1);
}
}
throw new NotImplementedException();
}

public async ValueTask Commit(CommitOptions options)
Expand All @@ -419,7 +433,7 @@ public async ValueTask Commit(CommitOptions options)
// memoize the abandoned so that it's preserved for future uses
MemoizeAbandoned();

_db.ReportPageCountPerCommit(_written.Count);
_db.ReportPageCountPerCommit(_written.Count, _metrics.PagesReused, _metrics.PagesAllocated);

await _db._manager.FlushPages(_written, options);

Expand Down

0 comments on commit 74a0f5d

Please sign in to comment.