Skip to content

CoreTests: CLI-based test suite selection with benchmarking#793

Merged
Xian55 merged 1 commit into
devfrom
bench/coretests
Mar 28, 2026
Merged

CoreTests: CLI-based test suite selection with benchmarking#793
Xian55 merged 1 commit into
devfrom
bench/coretests

Conversation

@Xian55

@Xian55 Xian55 commented Mar 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • Replace commented-out test selection with CLI-based dictionary dispatch (.\run.ps1 <suite> [args])
  • Add global flags: --log-times, --no-gpu, --no-log-update, --dxgi, --delay <ms>
  • Add percentile stats (p50/p95/p99) to --log-times output
  • Add build.ps1 / run.ps1 helper scripts and CoreTests/CLAUDE.md documentation
  • Fix NpcNames.ToStringF() to handle combined flags

Test position

image

stable image

image

Benchmark Commands

All 8 runs used npc friendly neutral 1000 with --log-times --no-log-update:

# 1/8: DXGI + GPU + delay 10
.\run.ps1 --dxgi --log-times --no-log-update --delay 10 npc friendly neutral 1000

# 2/8: WGC + GPU + delay 10
.\run.ps1 --log-times --no-log-update --delay 10 npc friendly neutral 1000

# 3/8: DXGI + no-GPU + delay 10
.\run.ps1 --dxgi --no-gpu --log-times --no-log-update --delay 10 npc friendly neutral 1000

# 4/8: WGC + no-GPU + delay 10
.\run.ps1 --no-gpu --log-times --no-log-update --delay 10 npc friendly neutral 1000

# 5/8: WGC + GPU + delay 150
.\run.ps1 --log-times --no-log-update --delay 150 npc friendly neutral 1000

# 6/8: WGC + GPU + delay 100
.\run.ps1 --log-times --no-log-update --delay 100 npc friendly neutral 1000

# 7/8: WGC + GPU + delay 15
.\run.ps1 --log-times --no-log-update --delay 15 npc friendly neutral 1000

# 8/8: WGC + GPU + delay 1
.\run.ps1 --log-times --no-log-update --delay 1 npc friendly neutral 1000

Raw Log Output (names.log)

1/8: DXGI + GPU + delay 10
2026-03-28 15:48:35.535 +01:00 [INF] Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - Windowed Mode: true - Scale: 1.25
2026-03-28 15:48:35.565 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 15:48:35.641 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 15:48:35.654 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 15:48:35.690 +01:00 [INF] running 1000 samples...
2026-03-28 15:48:44.458 +01:00 [INF] overall | n: 1000 | avg: 3.85 | min: 0.07 | p50: 5.28 | p95: 6.90 | p99: 8.19 | max: 43.61
2026-03-28 15:48:44.458 +01:00 [INF] capture | n: 1000 | avg: 3.54 | min: 0.06 | p50: 4.94 | p95: 6.45 | p99: 7.73 | max: 32.68
2026-03-28 15:48:44.458 +01:00 [INF] updates | n: 1000 | avg: 0.52 | min: 0.24 | p50: 0.44 | p95: 0.84 | p99: 1.51 | max: 33.40
2/8: WGC + GPU + delay 10
2026-03-28 15:48:45.743 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 15:48:45.762 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 15:48:45.825 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 15:48:45.843 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 15:48:45.877 +01:00 [INF] running 1000 samples...
2026-03-28 15:48:51.408 +01:00 [INF] overall | n: 1000 | avg: 0.43 | min: 0.00 | p50: 0.36 | p95: 1.11 | p99: 1.92 | max: 30.61
2026-03-28 15:48:51.408 +01:00 [INF] capture | n: 1000 | avg: 0.19 | min: 0.00 | p50: 0.00 | p95: 0.70 | p99: 1.35 | max: 6.04
2026-03-28 15:48:51.408 +01:00 [INF] updates | n: 1000 | avg: 0.53 | min: 0.23 | p50: 0.37 | p95: 0.83 | p99: 1.66 | max: 24.08
3/8: DXGI + no-GPU + delay 10
2026-03-28 15:48:52.657 +01:00 [INF] Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - Windowed Mode: true - Scale: 1.25
2026-03-28 15:48:52.675 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 15:48:52.690 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 15:48:52.725 +01:00 [INF] running 1000 samples...
2026-03-28 15:49:01.696 +01:00 [INF] overall | n: 1000 | avg: 4.01 | min: 0.06 | p50: 5.28 | p95: 7.70 | p99: 10.27 | max: 63.51
2026-03-28 15:49:01.696 +01:00 [INF] capture | n: 1000 | avg: 3.60 | min: 0.06 | p50: 4.98 | p95: 6.52 | p99: 7.83 | max: 20.93
2026-03-28 15:49:01.696 +01:00 [INF] updates | n: 1000 | avg: 0.68 | min: 0.23 | p50: 0.35 | p95: 2.27 | p99: 3.14 | max: 53.43
4/8: WGC + no-GPU + delay 10
2026-03-28 15:49:02.993 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 15:49:03.012 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 15:49:03.035 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 15:49:03.067 +01:00 [INF] running 1000 samples...
2026-03-28 15:49:08.859 +01:00 [INF] overall | n: 1000 | avg: 0.65 | min: 0.00 | p50: 0.33 | p95: 2.69 | p99: 3.29 | max: 61.42
2026-03-28 15:49:08.859 +01:00 [INF] capture | n: 1000 | avg: 0.18 | min: 0.00 | p50: 0.00 | p95: 0.58 | p99: 0.92 | max: 4.95
2026-03-28 15:49:08.859 +01:00 [INF] updates | n: 1000 | avg: 1.06 | min: 0.22 | p50: 0.35 | p95: 2.74 | p99: 3.27 | max: 56.10
5/8: WGC + GPU + delay 150
2026-03-28 15:49:10.069 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 15:49:10.087 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 15:49:10.143 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 15:49:10.161 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 15:49:10.194 +01:00 [INF] running 1000 samples...
2026-03-28 15:49:15.679 +01:00 [INF] overall | n: 1000 | avg: 0.23 | min: 0.00 | p50: 0.00 | p95: 0.75 | p99: 1.08 | max: 32.21
2026-03-28 15:49:15.679 +01:00 [INF] capture | n: 1000 | avg: 0.19 | min: 0.00 | p50: 0.00 | p95: 0.71 | p99: 1.00 | max: 4.26
2026-03-28 15:49:15.679 +01:00 [INF] updates | n: 1000 | avg: 1.21 | min: 0.29 | p50: 0.45 | p95: 0.75 | p99: 27.50 | max: 27.50
6/8: WGC + GPU + delay 100
2026-03-28 15:49:16.905 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 15:49:16.924 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 15:49:16.989 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 15:49:17.007 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 15:49:17.040 +01:00 [INF] running 1000 samples...
2026-03-28 15:49:22.508 +01:00 [INF] overall | n: 1000 | avg: 0.24 | min: 0.00 | p50: 0.01 | p95: 0.81 | p99: 1.30 | max: 33.51
2026-03-28 15:49:22.508 +01:00 [INF] capture | n: 1000 | avg: 0.18 | min: 0.00 | p50: 0.00 | p95: 0.66 | p99: 1.15 | max: 4.68
2026-03-28 15:49:22.508 +01:00 [INF] updates | n: 1000 | avg: 1.02 | min: 0.34 | p50: 0.44 | p95: 1.30 | p99: 28.42 | max: 28.42
7/8: WGC + GPU + delay 15
2026-03-28 15:49:23.726 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 15:49:23.744 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 15:49:23.803 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 15:49:23.822 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 15:49:23.855 +01:00 [INF] running 1000 samples...
2026-03-28 15:49:29.327 +01:00 [INF] overall | n: 1000 | avg: 0.34 | min: 0.00 | p50: 0.01 | p95: 0.89 | p99: 1.13 | max: 34.18
2026-03-28 15:49:29.327 +01:00 [INF] capture | n: 1000 | avg: 0.16 | min: 0.00 | p50: 0.00 | p95: 0.54 | p99: 0.97 | max: 4.71
2026-03-28 15:49:29.327 +01:00 [INF] updates | n: 1000 | avg: 0.54 | min: 0.24 | p50: 0.34 | p95: 0.54 | p99: 1.02 | max: 30.28
8/8: WGC + GPU + delay 1
2026-03-28 15:49:30.535 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 15:49:30.554 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 15:49:30.612 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 15:49:30.629 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 15:49:30.662 +01:00 [INF] running 1000 samples...
2026-03-28 15:49:36.129 +01:00 [INF] overall | n: 1000 | avg: 0.58 | min: 0.23 | p50: 0.45 | p95: 0.99 | p99: 1.33 | max: 31.30
2026-03-28 15:49:36.129 +01:00 [INF] capture | n: 1000 | avg: 0.17 | min: 0.00 | p50: 0.00 | p95: 0.59 | p99: 0.99 | max: 5.45
2026-03-28 15:49:36.129 +01:00 [INF] updates | n: 1000 | avg: 0.41 | min: 0.22 | p50: 0.35 | p95: 0.62 | p99: 1.02 | max: 25.35

Analysis

WGC vs DXGI (GPU enabled, delay 10)

Metric DXGI WGC Improvement
overall p50 5.28ms 0.36ms WGC 14.7x faster
overall p95 6.90ms 1.11ms WGC 6.2x faster
capture p50 4.94ms 0.00ms WGC near-zero
capture p95 6.45ms 0.70ms WGC 9.2x faster
updates p50 0.44ms 0.37ms ~same

WGC is massively faster — DXGI screen capture is the bottleneck (~5ms per frame vs near-zero for WGC).

GPU vs CPU (WGC, delay 10)

Metric GPU CPU Improvement
overall p50 0.36ms 0.33ms ~same
overall p95 1.11ms 2.69ms GPU 2.4x faster
updates p50 0.37ms 0.35ms ~same
updates p95 0.83ms 2.74ms GPU 3.3x faster

GPU provides consistency — similar median performance but significantly fewer latency spikes at p95/p99.

Delay Impact (WGC, GPU)

Metric delay 150 delay 100 delay 15 delay 1
overall p50 0.00ms 0.01ms 0.01ms 0.45ms
overall p95 0.75ms 0.81ms 0.89ms 0.99ms
updates p99 27.50ms 28.42ms 1.02ms 1.02ms

Lower delay = more consistent — delay 150/100 have massive p99 spikes (~28ms) likely from frame timing boundaries, while delay 15/1 stay under 1ms at p99. Delay 15 is the sweet spot.

Test plan

  • dotnet build -c Release compiles with 0 errors
  • .\run.ps1 shows available suites
  • .\run.ps1 npc friendly neutral 1000 runs with correct args
  • .\run.ps1 --log-times --no-log-update npc 1000 shows percentile stats
  • .\run.ps1 --dxgi npc 100 uses DXGI capture
  • .\run.ps1 --no-gpu npc 100 uses CPU path
  • All 8 benchmark configurations ran successfully

Round 2: GPU Utilization Monitoring (nvidia-smi)

Same 8 configurations re-run with nvidia-smi dmon -s u -d 1 sampling GPU utilization every second during each benchmark. Hardware: NVIDIA GeForce GTX 1070.

Monitoring Script

GPU utilization was sampled using nvidia-smi dmon running in background during each benchmark:

function Run-Benchmark {
    param([string]$Label, [string]$RunArgs)

    Write-Host "=== $Label ==="
    Write-Host "CMD: dotnet run --no-build -c Release -- $RunArgs"

    # Start nvidia-smi sampling in background (1 sample/sec)
    $gpuLog = [System.IO.Path]::GetTempFileName()
    $nvProc = Start-Process -FilePath "nvidia-smi" -ArgumentList "dmon -s u -d 1" `
        -RedirectStandardOutput $gpuLog -WindowStyle Hidden -PassThru

    # Run benchmark and measure wall time
    $elapsed = Measure-Command {
        Invoke-Expression "dotnet run --no-build -c Release -- $RunArgs | Out-Null"
    }

    Start-Sleep -Milliseconds 500
    Stop-Process -Id $nvProc.Id -Force -ErrorAction SilentlyContinue
    Start-Sleep -Milliseconds 300

    # Parse GPU utilization from nvidia-smi dmon output (column 2 = sm utilization)
    $gpuSamples = Get-Content $gpuLog | Where-Object { $_ -match "^\s+\d" } | ForEach-Object {
        ($_ -split "\s+" | Where-Object { $_ -ne "" })[1]
    } | ForEach-Object { [int]$_ }
    Remove-Item $gpuLog -Force -ErrorAction SilentlyContinue

    $wallSec = $elapsed.TotalSeconds
    if ($gpuSamples.Count -gt 0) {
        $gpuAvg = ($gpuSamples | Measure-Object -Average).Average
        $gpuMax = ($gpuSamples | Measure-Object -Maximum).Maximum
        $gpuMin = ($gpuSamples | Measure-Object -Minimum).Minimum
        Write-Host ("  Wall: {0:F1}s | GPU: avg={1:F0}% min={2}% max={3}% ({4} samples)" -f
            $wallSec, $gpuAvg, $gpuMin, $gpuMax, $gpuSamples.Count)
    }
}

$configs = @(
    @{ Label="1/8: DXGI + GPU + delay 10";    RunArgs="--dxgi --log-times --no-log-update --delay 10 npc friendly neutral 1000" },
    @{ Label="2/8: WGC + GPU + delay 10";     RunArgs="--log-times --no-log-update --delay 10 npc friendly neutral 1000" },
    @{ Label="3/8: DXGI + no-GPU + delay 10"; RunArgs="--dxgi --no-gpu --log-times --no-log-update --delay 10 npc friendly neutral 1000" },
    @{ Label="4/8: WGC + no-GPU + delay 10";  RunArgs="--no-gpu --log-times --no-log-update --delay 10 npc friendly neutral 1000" },
    @{ Label="5/8: WGC + GPU + delay 150";    RunArgs="--log-times --no-log-update --delay 150 npc friendly neutral 1000" },
    @{ Label="6/8: WGC + GPU + delay 100";    RunArgs="--log-times --no-log-update --delay 100 npc friendly neutral 1000" },
    @{ Label="7/8: WGC + GPU + delay 15";     RunArgs="--log-times --no-log-update --delay 15 npc friendly neutral 1000" },
    @{ Label="8/8: WGC + GPU + delay 1";      RunArgs="--log-times --no-log-update --delay 1 npc friendly neutral 1000" }
)

foreach ($cfg in $configs) {
    Run-Benchmark -Label $cfg.Label -RunArgs $cfg.RunArgs
}

Commands (identical to Round 1)

# 1/8: DXGI + GPU + delay 10
dotnet run --no-build -c Release -- --dxgi --log-times --no-log-update --delay 10 npc friendly neutral 1000

# 2/8: WGC + GPU + delay 10
dotnet run --no-build -c Release -- --log-times --no-log-update --delay 10 npc friendly neutral 1000

# 3/8: DXGI + no-GPU + delay 10
dotnet run --no-build -c Release -- --dxgi --no-gpu --log-times --no-log-update --delay 10 npc friendly neutral 1000

# 4/8: WGC + no-GPU + delay 10
dotnet run --no-build -c Release -- --no-gpu --log-times --no-log-update --delay 10 npc friendly neutral 1000

# 5/8: WGC + GPU + delay 150
dotnet run --no-build -c Release -- --log-times --no-log-update --delay 150 npc friendly neutral 1000

# 6/8: WGC + GPU + delay 100
dotnet run --no-build -c Release -- --log-times --no-log-update --delay 100 npc friendly neutral 1000

# 7/8: WGC + GPU + delay 15
dotnet run --no-build -c Release -- --log-times --no-log-update --delay 15 npc friendly neutral 1000

# 8/8: WGC + GPU + delay 1
dotnet run --no-build -c Release -- --log-times --no-log-update --delay 1 npc friendly neutral 1000

Combined Results: Timing + GPU Utilization

# Config Wall GPU avg GPU max overall p50 overall p95 capture p50 updates p50
1 DXGI + GPU + delay 10 10.5s 18% 36% 5.40ms 6.97ms 4.98ms 0.46ms
2 WGC + GPU + delay 10 7.0s 14% 29% 0.40ms 1.01ms 0.00ms 0.39ms
3 DXGI + no-GPU + delay 10 10.2s 11% 26% 5.30ms 6.94ms 4.99ms 0.34ms
4 WGC + no-GPU + delay 10 7.2s 14% 32% 0.34ms 2.50ms 0.00ms 0.34ms
5 WGC + GPU + delay 150 6.9s 9% 11% 0.01ms 0.63ms 0.00ms 0.43ms
6 WGC + GPU + delay 100 6.9s 9% 12% 0.01ms 0.76ms 0.00ms 0.46ms
7 WGC + GPU + delay 15 6.8s 10% 14% 0.01ms 0.95ms 0.00ms 0.36ms
8 WGC + GPU + delay 1 6.8s 12% 16% 0.47ms 1.09ms 0.00ms 0.34ms

Raw Log Output (names.log - Round 2)

1/8: DXGI + GPU + delay 10
2026-03-28 16:06:27.438 +01:00 [INF] Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - Windowed Mode: true - Scale: 1.25
2026-03-28 16:06:27.473 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 16:06:27.546 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 16:06:27.560 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 16:06:27.595 +01:00 [INF] running 1000 samples...
2026-03-28 16:06:36.366 +01:00 [INF] overall | n: 1000 | avg: 3.85 | min: 0.99 | p50: 5.40 | p95: 6.97 | p99: 7.74 | max: 42.08
2026-03-28 16:06:36.366 +01:00 [INF] capture | n: 1000 | avg: 3.56 | min: 0.99 | p50: 4.98 | p95: 6.51 | p99: 7.11 | max: 10.89
2026-03-28 16:06:36.366 +01:00 [INF] updates | n: 1000 | avg: 0.56 | min: 0.24 | p50: 0.46 | p95: 0.80 | p99: 1.01 | max: 30.29
2/8: WGC + GPU + delay 10
2026-03-28 16:06:38.636 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 16:06:38.656 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 16:06:38.721 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 16:06:38.741 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 16:06:38.775 +01:00 [INF] running 1000 samples...
2026-03-28 16:06:44.235 +01:00 [INF] overall | n: 1000 | avg: 0.40 | min: 0.00 | p50: 0.40 | p95: 1.01 | p99: 1.29 | max: 30.06
2026-03-28 16:06:44.235 +01:00 [INF] capture | n: 1000 | avg: 0.18 | min: 0.00 | p50: 0.00 | p95: 0.66 | p99: 0.99 | max: 4.53
2026-03-28 16:06:44.235 +01:00 [INF] updates | n: 1000 | avg: 0.47 | min: 0.25 | p50: 0.39 | p95: 0.70 | p99: 1.02 | max: 25.16
3/8: DXGI + no-GPU + delay 10
2026-03-28 16:06:46.271 +01:00 [INF] Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - Windowed Mode: true - Scale: 1.25
2026-03-28 16:06:46.288 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 16:06:46.308 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 16:06:46.345 +01:00 [INF] running 1000 samples...
2026-03-28 16:06:55.227 +01:00 [INF] overall | n: 1000 | avg: 3.96 | min: 1.07 | p50: 5.30 | p95: 6.94 | p99: 9.06 | max: 76.25
2026-03-28 16:06:55.228 +01:00 [INF] capture | n: 1000 | avg: 3.63 | min: 1.07 | p50: 4.99 | p95: 6.46 | p99: 8.76 | max: 9.65
2026-03-28 16:06:55.228 +01:00 [INF] updates | n: 1000 | avg: 0.54 | min: 0.23 | p50: 0.34 | p95: 0.83 | p99: 2.65 | max: 66.49
4/8: WGC + no-GPU + delay 10
2026-03-28 16:06:57.409 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 16:06:57.429 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 16:06:57.455 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 16:06:57.488 +01:00 [INF] running 1000 samples...
2026-03-28 16:07:03.211 +01:00 [INF] overall | n: 1000 | avg: 0.63 | min: 0.00 | p50: 0.34 | p95: 2.50 | p99: 3.14 | max: 57.59
2026-03-28 16:07:03.212 +01:00 [INF] capture | n: 1000 | avg: 0.17 | min: 0.00 | p50: 0.00 | p95: 0.57 | p99: 1.03 | max: 4.17
2026-03-28 16:07:03.212 +01:00 [INF] updates | n: 1000 | avg: 1.01 | min: 0.24 | p50: 0.34 | p95: 2.71 | p99: 3.25 | max: 52.93
5/8: WGC + GPU + delay 150
2026-03-28 16:07:05.361 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 16:07:05.380 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 16:07:05.442 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 16:07:05.462 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 16:07:05.495 +01:00 [INF] running 1000 samples...
2026-03-28 16:07:10.947 +01:00 [INF] overall | n: 1000 | avg: 0.22 | min: 0.00 | p50: 0.01 | p95: 0.63 | p99: 1.04 | max: 31.60
2026-03-28 16:07:10.947 +01:00 [INF] capture | n: 1000 | avg: 0.17 | min: 0.00 | p50: 0.00 | p95: 0.58 | p99: 1.04 | max: 5.17
2026-03-28 16:07:10.947 +01:00 [INF] updates | n: 1000 | avg: 1.18 | min: 0.31 | p50: 0.43 | p95: 0.99 | p99: 25.76 | max: 25.76
6/8: WGC + GPU + delay 100
2026-03-28 16:07:13.088 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 16:07:13.107 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 16:07:13.175 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 16:07:13.193 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 16:07:13.227 +01:00 [INF] running 1000 samples...
2026-03-28 16:07:18.648 +01:00 [INF] overall | n: 1000 | avg: 0.24 | min: 0.00 | p50: 0.01 | p95: 0.76 | p99: 1.07 | max: 26.31
2026-03-28 16:07:18.648 +01:00 [INF] capture | n: 1000 | avg: 0.19 | min: 0.00 | p50: 0.00 | p95: 0.70 | p99: 1.01 | max: 4.43
2026-03-28 16:07:18.648 +01:00 [INF] updates | n: 1000 | avg: 0.88 | min: 0.30 | p50: 0.46 | p95: 1.08 | p99: 21.39 | max: 21.39
7/8: WGC + GPU + delay 15
2026-03-28 16:07:20.757 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 16:07:20.775 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 16:07:20.834 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 16:07:20.852 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 16:07:20.888 +01:00 [INF] running 1000 samples...
2026-03-28 16:07:26.349 +01:00 [INF] overall | n: 1000 | avg: 0.34 | min: 0.00 | p50: 0.01 | p95: 0.95 | p99: 1.56 | max: 29.62
2026-03-28 16:07:26.349 +01:00 [INF] capture | n: 1000 | avg: 0.18 | min: 0.00 | p50: 0.00 | p95: 0.63 | p99: 1.28 | max: 3.94
2026-03-28 16:07:26.349 +01:00 [INF] updates | n: 1000 | avg: 0.45 | min: 0.25 | p50: 0.36 | p95: 0.49 | p99: 0.81 | max: 25.31
8/8: WGC + GPU + delay 1
2026-03-28 16:07:28.413 +01:00 [INF] WGC initialized - Rectangle [ X=5, Y=40, Width=1024, Height=768 ] - ClientOffset: (1, 38) - Borderless: false
2026-03-28 16:07:28.432 +01:00 [INF] Suite: npc | Args: friendly, neutral, 1000
2026-03-28 16:07:28.487 +01:00 [INF] [GpuLineSegmentProvider] GPU compute shader initialized
2026-03-28 16:07:28.505 +01:00 [INF] [NpcNameFinder] type = Friendly, Neutral | mode = Fuzzy
2026-03-28 16:07:28.537 +01:00 [INF] running 1000 samples...
2026-03-28 16:07:33.991 +01:00 [INF] overall | n: 1000 | avg: 0.60 | min: 0.22 | p50: 0.47 | p95: 1.09 | p99: 1.43 | max: 31.43
2026-03-28 16:07:33.991 +01:00 [INF] capture | n: 1000 | avg: 0.17 | min: 0.00 | p50: 0.00 | p95: 0.57 | p99: 1.06 | max: 5.39
2026-03-28 16:07:33.991 +01:00 [INF] updates | n: 1000 | avg: 0.43 | min: 0.22 | p50: 0.34 | p95: 0.82 | p99: 1.16 | max: 25.55

GPU Utilization Analysis

DXGI vs WGC GPU impact:

  • DXGI + GPU uses 18% avg GPU vs WGC + GPU at 14% — DXGI screen capture itself consumes extra GPU
  • DXGI runs take 10.5s wall time vs WGC at 7.0s — 50% longer overall

GPU compute shader impact:

  • no-GPU runs (3, 4) still show ~11-14% GPU — this is baseline WoW/desktop rendering, not the benchmark
  • GPU compute shader adds only ~3-4% GPU utilization on top of baseline

Delay vs GPU utilization:

  • Higher delays (150, 100) = lower GPU avg (9%) — more idle time between iterations
  • Lower delays (15, 1) = higher GPU avg (10-12%) — tighter iteration loop keeps GPU busier
  • All WGC runs stay well under 20% GPU — the GTX 1070 is barely taxed

🤖 Generated with Claude Code

Replace commented-out test selection with dictionary-based CLI dispatch.
Each test suite is now selectable via command-line args with configurable
parameters (NpcNames, iteration count, delay, GPU/CPU, DXGI/WGC).

Changes:
- Add suite dictionary with Action<string[]> for extensible dispatch
- Add global flags: --log-times, --no-gpu, --no-log-update, --dxgi, --delay
- Add percentile stats (p50/p95/p99) to --log-times output
- Add PPather suite with expansion arg
- Parameterize LogEachUpdate in Test_NpcNameFinder
- Change screen field to IWowScreen to support DXGI/WGC toggle
- Fix NpcNames.ToStringF() to handle combined flags via ToString()
- Add build.ps1 and run.ps1 helper scripts
- Add CoreTests/CLAUDE.md with usage documentation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Xian55 Xian55 added refactor This ticket concerns the possible simplification of code/data. enhancement This pull request implements a new feature. labels Mar 28, 2026
@Xian55
Xian55 merged commit b82b61e into dev Mar 28, 2026
1 check passed
@Xian55
Xian55 deleted the bench/coretests branch March 28, 2026 15:29
@Xian55 Xian55 added the ai Artificial Intelligence tool has been contributed. label Mar 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai Artificial Intelligence tool has been contributed. enhancement This pull request implements a new feature. refactor This ticket concerns the possible simplification of code/data.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant