151 lines
4.4 KiB
C#
151 lines
4.4 KiB
C#
using BenchmarkDotNet.Attributes;
|
|
using BenchmarkDotNet.Configs;
|
|
using BenchmarkDotNet.Jobs;
|
|
using ZB.MOM.WW.CBDD.Bson;
|
|
using ZB.MOM.WW.CBDD.Core.Collections;
|
|
using ZB.MOM.WW.CBDD.Core.Storage;
|
|
|
|
namespace ZB.MOM.WW.CBDD.Tests.Benchmark;
|
|
|
|
[SimpleJob]
|
|
[InProcess]
|
|
[MemoryDiagnoser]
|
|
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
|
|
[HtmlExporter]
|
|
[JsonExporterAttribute.Full]
|
|
public class CompactionBenchmarks
|
|
{
|
|
/// <summary>
|
|
/// Gets or sets the number of documents used per benchmark iteration.
|
|
/// </summary>
|
|
[Params(2_000)]
|
|
public int DocumentCount { get; set; }
|
|
|
|
private string _dbPath = string.Empty;
|
|
private string _walPath = string.Empty;
|
|
private StorageEngine _storage = null!;
|
|
private BenchmarkTransactionHolder _transactionHolder = null!;
|
|
private DocumentCollection<Person> _collection = null!;
|
|
private List<ObjectId> _insertedIds = [];
|
|
|
|
/// <summary>
|
|
/// Prepares benchmark state and seed data for each iteration.
|
|
/// </summary>
|
|
[IterationSetup]
|
|
public void Setup()
|
|
{
|
|
var id = Guid.NewGuid().ToString("N");
|
|
_dbPath = Path.Combine(AppContext.BaseDirectory, $"bench_compaction_{id}.db");
|
|
_walPath = Path.ChangeExtension(_dbPath, ".wal");
|
|
|
|
_storage = new StorageEngine(_dbPath, PageFileConfig.Small);
|
|
_transactionHolder = new BenchmarkTransactionHolder(_storage);
|
|
_collection = new DocumentCollection<Person>(_storage, _transactionHolder, new PersonMapper());
|
|
|
|
_insertedIds.Clear();
|
|
for (var i = 0; i < DocumentCount; i++)
|
|
{
|
|
var person = CreatePerson(i);
|
|
var insertedId = _collection.Insert(person);
|
|
_insertedIds.Add(insertedId);
|
|
}
|
|
|
|
_transactionHolder.CommitAndReset();
|
|
_storage.Checkpoint();
|
|
|
|
for (var i = _insertedIds.Count - 1; i >= _insertedIds.Count / 3; i--)
|
|
{
|
|
_collection.Delete(_insertedIds[i]);
|
|
}
|
|
|
|
_transactionHolder.CommitAndReset();
|
|
_storage.Checkpoint();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cleans up benchmark resources and temporary files after each iteration.
|
|
/// </summary>
|
|
[IterationCleanup]
|
|
public void Cleanup()
|
|
{
|
|
_transactionHolder?.Dispose();
|
|
_storage?.Dispose();
|
|
|
|
if (File.Exists(_dbPath)) File.Delete(_dbPath);
|
|
if (File.Exists(_walPath)) File.Delete(_walPath);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Benchmarks reclaimed file bytes reported by offline compaction.
|
|
/// </summary>
|
|
/// <returns>The reclaimed file byte count.</returns>
|
|
[Benchmark(Baseline = true)]
|
|
[BenchmarkCategory("Compaction_Offline")]
|
|
public long OfflineCompact_ReclaimedBytes()
|
|
{
|
|
var stats = _storage.Compact(new CompactionOptions
|
|
{
|
|
OnlineMode = false,
|
|
EnableTailTruncation = true,
|
|
DefragmentSlottedPages = true,
|
|
NormalizeFreeList = true
|
|
});
|
|
|
|
return stats.ReclaimedFileBytes;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Benchmarks tail bytes truncated by offline compaction.
|
|
/// </summary>
|
|
/// <returns>The truncated tail byte count.</returns>
|
|
[Benchmark]
|
|
[BenchmarkCategory("Compaction_Offline")]
|
|
public long OfflineCompact_TailBytesTruncated()
|
|
{
|
|
var stats = _storage.Compact(new CompactionOptions
|
|
{
|
|
OnlineMode = false,
|
|
EnableTailTruncation = true,
|
|
DefragmentSlottedPages = true,
|
|
NormalizeFreeList = true
|
|
});
|
|
|
|
return stats.TailBytesTruncated;
|
|
}
|
|
|
|
private static Person CreatePerson(int i)
|
|
{
|
|
return new Person
|
|
{
|
|
Id = ObjectId.NewObjectId(),
|
|
FirstName = $"First_{i}",
|
|
LastName = $"Last_{i}",
|
|
Age = i % 90,
|
|
Bio = BuildPayload(i),
|
|
CreatedAt = DateTime.UnixEpoch.AddSeconds(i),
|
|
Balance = i * 1.5m,
|
|
HomeAddress = new Address
|
|
{
|
|
Street = $"{i} Long Street",
|
|
City = "Compaction City",
|
|
ZipCode = "90000"
|
|
}
|
|
};
|
|
}
|
|
|
|
private static string BuildPayload(int seed)
|
|
{
|
|
var builder = new System.Text.StringBuilder(2500);
|
|
for (var i = 0; i < 80; i++)
|
|
{
|
|
builder.Append("compact-");
|
|
builder.Append(seed.ToString("D6"));
|
|
builder.Append('-');
|
|
builder.Append(i.ToString("D3"));
|
|
builder.Append('|');
|
|
}
|
|
|
|
return builder.ToString();
|
|
}
|
|
}
|