Tree Create Sequential - ANTIPATTERN (slow by design)
Sequential create tree hierarchy - deliberate ANTIPATTERN demo.
This example is SLOW BY DESIGN: it saves ~100 tree nodes one CreateChildAsync at a time,
paying a full save pipeline (key allocation, hash, values insert, commit) per node, to give
E088 (bulk AddNewObjectsAsync, one round-trip for the whole level) a baseline to beat.
Do NOT copy this shape into application code - use the bulk API of E088.
Structure:
This example is SLOW BY DESIGN: it saves ~100 tree nodes one CreateChildAsync at a time,
paying a full save pipeline (key allocation, hash, values insert, commit) per node, to give
E088 (bulk AddNewObjectsAsync, one round-trip for the whole level) a baseline to beat.
Do NOT copy this shape into application code - use the bulk API of E088.
Structure:
- 1 root (TechCorp)
- 10 regional offices
- 50 departments (5 per office)
- 40 teams (4 per first 10 departments)
await redb.SyncSchemeAsync<DepartmentProps>();
// Run E087 first to cleanup existing data
// Measure sequential creation
var sw = Stopwatch.StartNew();
var count = await CreateTreeSequentially(redb);
sw.Stop();
var rate = count * 1000 / Math.Max(sw.ElapsedMilliseconds, 1);
Console.WriteLine($"[E089] ANTIPATTERN demo: {count} nodes saved one round-trip each on purpose - compare with E088 (bulk).");
CreateTreeSequentially
private static async Task<int> CreateTreeSequentially(IRedbService redb)
{
var count = 0;
// Level 0: Root
var root = CreateDept("TechCorp", "CORP", "Headquarters", 50_000_000m);
root.id = await redb.SaveAsync(root);
count++;
// Level 1: Regional offices
var offices = new TreeRedbObject<DepartmentProps>[OfficeCount];
for (int i = 0; i < OfficeCount; i++)
{
var city = Cities[i % Cities.Length];
offices[i] = CreateDept($"{city} Office", $"OFF-{i + 1:D2}", $"Regional office {city}", 5_000_000m - i * 200_000m);
offices[i].id = await redb.CreateChildAsync(offices[i], root);
count++;
}
// Level 2: Departments in each office
var depts = new List<TreeRedbObject<DepartmentProps>>();
for (int o = 0; o < OfficeCount; o++)
{
for (int d = 0; d < DeptPerOffice; d++)
{
var deptName = Departments[d % Departments.Length];
var dept = CreateDept($"{deptName} {o + 1}-{d + 1}", $"DEPT-{o + 1:D2}-{d + 1:D2}", deptName, 1_000_000m - d * 100_000m);
dept.id = await redb.CreateChildAsync(dept, offices[o]);
depts.Add(dept);
count++;
}
}
// Level 3: Teams in first 10 departments
for (int d = 0; d < TeamsForFirstDepts && d < depts.Count; d++)
{
for (int t = 0; t < TeamsPerDept; t++)
{
var teamName = Teams[t % Teams.Length];
var team = CreateDept($"{teamName} Team {d + 1}-{t + 1}", $"TEAM-{d + 1:D2}-{t + 1:D2}", teamName, 300_000m - t * 50_000m);
await redb.CreateChildAsync(team, depts[d]);
count++;
}
}
return count;
}
PG Pro
10089ms(101)
postgres.ef
774ms(101)
postgres.pro.repeat
9983ms(101)
postgres.pro.cache
10135ms(101)
postgres.ef.repeat
649ms(101)
MS Pro
6385ms(101)
mssql.pro.repeat
8599ms(101)
mssql.pro.cache
6427ms(101)
sqlite.pro
509ms(101)
sqlite.pro.repeat
588ms(101)
sqlite.pro.cache
478ms(101)