Skip to content

Commit

Permalink
Fix parallel parsing of POV demos (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
saul authored Sep 23, 2024
1 parent e98ad9c commit 3dc36fd
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 16 deletions.
6 changes: 5 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
### 0.22.2 (2024-09-22)
### 0.22.3 (2024-09-23)

- Fixed parallel parsing of POV demos ([#92](https://github.com/saul/demofile-net/issues/92))

### 0.22.2 (2024-09-23)

- Fix entities being re-created multiple times ([#91](https://github.com/saul/demofile-net/issues/91))
- Added check to ensure demos are for the correct game (e.g. CsDemoParser reads 'csgo' demos, DeadlockDemoParser reads 'citadel' demos)
Expand Down
83 changes: 69 additions & 14 deletions src/DemoFile.Test/Integration/DemoParserIntegrationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,30 +33,85 @@ public async Task ByTick()
Assert.That(demo.CurrentDemoTick.Value, Is.EqualTo(217866));
}

private static readonly KeyValuePair<string, byte[]>[] CompatibilityCases =
public record CompatibilityTestCase(
string Name,
byte[] DemoFileBytes,
DemoTick ExpectedLastTick)
{
new("v13978", GotvProtocol13978),
new("v13980", GotvProtocol13980),
new("v13987", GotvProtocol13987),
new("v13990_armsrace", GotvProtocol13990ArmsRace),
new("v13990_dm", GotvProtocol13990Deathmatch),
new("v14005", GotvProtocol14005),
new("v14011", GotvProtocol14011),
new("pov_14000", Pov14000),
public override string ToString() => Name;
}

private static readonly CompatibilityTestCase[] CompatibilityCases =
{
new("v13978", GotvProtocol13978, new DemoTick(164)),
new("v13980", GotvProtocol13980, new DemoTick(134)),
new("v13987", GotvProtocol13987, new DemoTick(1106)),
new("v13990_armsrace", GotvProtocol13990ArmsRace, new DemoTick(219)),
new("v13990_dm", GotvProtocol13990Deathmatch, new DemoTick(303)),
new("v14005", GotvProtocol14005, new DemoTick(293)),
new("v14011", GotvProtocol14011, new DemoTick(391)),
new("pov_14000", Pov14000, new DemoTick(127743)),
};

[Test]
public async Task Compatibility(
[Values] ParseMode mode,
[ValueSource(nameof(CompatibilityCases))] KeyValuePair<string, byte[]> testCase)
[ValueSource(nameof(CompatibilityCases))] CompatibilityTestCase testCase)
{
DemoSnapshot ParseSection(CsDemoParser demo)
Func<DemoTick> ParseSection(CsDemoParser demo)
{
var lastTick = DemoTick.PreRecord;
demo.OnCommandFinish += OnCommandFinish;

return () => lastTick;

void OnCommandFinish()
{
demo.OnCommandFinish += OnCommandFinish;
lastTick = demo.CurrentDemoTick;
}
}

DemoTick lastTick;
if (mode == ParseMode.ReadAll)
{
var demo = new CsDemoParser();
var stream = new MemoryStream(testCase.DemoFileBytes);

var getLastTick = ParseSection(demo);

var reader = DemoFileReader.Create(demo, stream);
await reader.ReadAllAsync(default);

lastTick = getLastTick();
}
else if (mode == ParseMode.ByTick)
{
var demo = new CsDemoParser();
var stream = new MemoryStream(testCase.DemoFileBytes);

var getLastTick = ParseSection(demo);

var reader = DemoFileReader.Create(demo, stream);
await reader.StartReadingAsync(default);
while (await reader.MoveNextAsync(default))
{
}

lastTick = getLastTick();
}
else if (mode == ParseMode.ReadAllParallel)
{
var results = await DemoFileReader<CsDemoParser>.ReadAllParallelAsync(testCase.DemoFileBytes, ParseSection, default);

lastTick = results.Select(x => x()).Max();
}
else
{
// no-op - we're just parsing the demo to the end
return new DemoSnapshot();
throw new ArgumentOutOfRangeException(nameof(mode), mode, "Unknown parse mode");
}

await Parse(mode, testCase.Value, ParseSection);
Assert.That(lastTick, Is.EqualTo(testCase.ExpectedLastTick));
}

[TestCase]
Expand Down
15 changes: 15 additions & 0 deletions src/DemoFile/DemoFileReader.Parallel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ await reader.MoveNextCoreAsync(cmd.Command, cmd.IsCompressed, cmd.Size, cancella
}
}

if (reader.FullPackets.Count == 0)
{
var backgroundParser = new TGameParser();
var backgroundReader = new DemoFileReader<TGameParser>(backgroundParser, new MemoryStream(demoFileBytes));

await backgroundReader.StartReadingAsync(cancellationToken).ConfigureAwait(false);
var result = setupSection(backgroundParser);

while (await backgroundReader.MoveNextAsync(cancellationToken).ConfigureAwait(false))
{
}

return new[] {result};
}

var maxParallelism = Environment.ProcessorCount;
var numSections = reader.FullPackets.Count;
var numSectionsPerParser = Math.Max(1, (numSections + maxParallelism - 1) / maxParallelism);
Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "0.22.2",
"version": "0.22.3",
"publicReleaseRefSpec": [
"^refs/heads/main",
"^refs/heads/v\\d+(?:\\.\\d+)?$"
Expand Down

0 comments on commit 3dc36fd

Please sign in to comment.