Skip to content

fix:

fix: #47

Workflow file for this run

name: Performance Comparison
on:
workflow_dispatch:
push:
paths:
- 'main.cpp'
- '.github/workflows/perf-compare.yml'
pull_request:
paths:
- 'main.cpp'
- '.github/workflows/perf-compare.yml'
permissions:
contents: read
jobs:
perf-comparison:
runs-on: windows-latest
steps:
- name: Checkout this repo
uses: actions/checkout@v4
with:
path: win-witr-cpp
# Install pranshuparmar's witr (Go version)
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 'stable'
- name: Clone and build pranshuparmar's witr
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
git clone https://github.com/pranshuparmar/witr.git witr-go
cd witr-go
go build -o witr.exe
if ($LASTEXITCODE -ne 0) { exit 1 }
Write-Host "Built pranshuparmar's witr (Go version)"
.\witr.exe --version
# Install m-de-graaff's witr-win (Rust version)
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
# Note: Using @stable intentionally to test against latest Rust version
- name: Clone and build m-de-graaff's witr-win
continue-on-error: true
id: rust_build
shell: pwsh
run: |
$ErrorActionPreference = "Continue"
git clone https://github.com/m-de-graaff/witr-win.git witr-rust
cd witr-rust
cargo build --release 2>&1 | Out-Host
if ($LASTEXITCODE -ne 0) {
Write-Warning "Rust version failed to build - will be skipped in comparison"
exit 1
}
# The binary name is witr-win.exe, not witr.exe
if (Test-Path "target/release/witr-win.exe") {
Copy-Item "target/release/witr-win.exe" "../witr-rust.exe"
Write-Host "Built m-de-graaff's witr-win (Rust version)"
..\witr-rust.exe --version
} else {
Write-Warning "Rust binary not found - build may have failed"
exit 1
}
# Build this repo's win-witr (C++ version)
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
- name: Compile win-witr
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
cd win-witr-cpp
cl /O2 /GL /std:c++20 /EHsc main.cpp /DUNICODE /D_UNICODE /Fe:win-witr.exe
if ($LASTEXITCODE -ne 0) { exit 1 }
Write-Host "Built win-witr (C++ version)"
.\win-witr.exe --version
# Run performance comparison tests
- name: Run Performance Comparison
shell: pwsh
run: |
# Enable ANSI colors for win-witr C++ output
$env:force_ansi = 1
Write-Host ""
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "WITR PERFORMANCE COMPARISON" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""
# Add all executables to variables for easy access
$witrGo = "$PWD\witr-go\witr.exe"
$witrRust = "$PWD\witr-rust.exe"
$witrCpp = "$PWD\win-witr-cpp\win-witr.exe"
# Check which versions are available
$hasRust = Test-Path $witrRust
if (-not $hasRust) {
Write-Warning "Rust version not available - it failed to build. Comparison will only include Go and C++ versions."
Write-Host ""
}
# Test processes - use common Windows processes that should exist
$testProcesses = @(
"explorer",
"winlogon",
"lsass",
"csrss",
"services",
"svchost",
"smss",
"wininit",
"dwm",
"RuntimeBroker",
"SearchIndexer",
"spoolsv",
"taskhostw",
"fontdrvhost",
"conhost"
)
Write-Host "Testing process lookup performance on $($testProcesses.Count) processes" -ForegroundColor Yellow
Write-Host ""
# First, show sample output from each tool for svchost process
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "SAMPLE OUTPUT COMPARISON (svchost)" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "--- Go version output ---" -ForegroundColor Green
& $witrGo svchost
Write-Host ""
if ($hasRust) {
Write-Host "--- Rust version output ---" -ForegroundColor Green
& $witrRust svchost
Write-Host ""
}
Write-Host "--- C++ version output ---" -ForegroundColor Green
& $witrCpp svchost
Write-Host ""
Write-Host ""
# Results storage
$results = @{
"Go" = @()
"Rust" = @()
"C++" = @()
}
# Run tests for each process
foreach ($process in $testProcesses) {
Write-Host "Testing: $process" -ForegroundColor White
Write-Host "----------------------------------------" -ForegroundColor Gray
# Test Go version
Write-Host " Go version:" -ForegroundColor Green -NoNewline
$goTime = Measure-Command { & $witrGo $process 2>&1 | Out-Null }
$goMs = [Math]::Round($goTime.TotalMilliseconds, 2)
Write-Host " $goMs ms" -ForegroundColor Cyan
$results["Go"] += $goMs
# Test Rust version (if available)
if ($hasRust) {
Write-Host " Rust version:" -ForegroundColor Green -NoNewline
$rustTime = Measure-Command { & $witrRust $process 2>&1 | Out-Null }
$rustMs = [Math]::Round($rustTime.TotalMilliseconds, 2)
Write-Host " $rustMs ms" -ForegroundColor Cyan
$results["Rust"] += $rustMs
}
# Test C++ version
Write-Host " C++ version:" -ForegroundColor Green -NoNewline
$cppTime = Measure-Command { & $witrCpp $process 2>&1 | Out-Null }
$cppMs = [Math]::Round($cppTime.TotalMilliseconds, 2)
Write-Host " $cppMs ms" -ForegroundColor Cyan
$results["C++"] += $cppMs
Write-Host ""
}
# Calculate and display totals
Write-Host ""
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "TOTAL RESULTS" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan
$goTotal = ($results["Go"] | Measure-Object -Sum).Sum
$rustTotal = if ($hasRust) { ($results["Rust"] | Measure-Object -Sum).Sum } else { 0 }
$cppTotal = ($results["C++"] | Measure-Object -Sum).Sum
Write-Host ""
Write-Host "Total time for $($testProcesses.Count) process lookups:" -ForegroundColor Yellow
Write-Host " Go (pranshuparmar/witr): $([Math]::Round($goTotal, 2)) ms" -ForegroundColor Green
if ($hasRust) {
Write-Host " Rust (m-de-graaff/witr-win): $([Math]::Round($rustTotal, 2)) ms" -ForegroundColor Green
} else {
Write-Host " Rust (m-de-graaff/witr-win): N/A (build failed)" -ForegroundColor Yellow
}
Write-Host " C++ (supervoidcoder/win-witr): $([Math]::Round($cppTotal, 2)) ms" -ForegroundColor Green
Write-Host ""
# Calculate averages
$goAvg = [Math]::Round($goTotal / $testProcesses.Count, 2)
$rustAvg = if ($hasRust) { [Math]::Round($rustTotal / $testProcesses.Count, 2) } else { 0 }
$cppAvg = [Math]::Round($cppTotal / $testProcesses.Count, 2)
Write-Host "Average time per lookup:" -ForegroundColor Yellow
Write-Host " Go: $goAvg ms" -ForegroundColor Green
if ($hasRust) {
Write-Host " Rust: $rustAvg ms" -ForegroundColor Green
}
Write-Host " C++: $cppAvg ms" -ForegroundColor Green
Write-Host ""
# Determine winner
$times = @{
"Go (pranshuparmar/witr)" = $goTotal
"C++ (supervoidcoder/win-witr)" = $cppTotal
}
if ($hasRust) {
$times["Rust (m-de-graaff/witr-win)"] = $rustTotal
}
$winner = $times.GetEnumerator() | Sort-Object Value | Select-Object -First 1
$slowest = $times.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 1
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "🏆 FASTEST: $($winner.Name)" -ForegroundColor Green
Write-Host "🐌 SLOWEST: $($slowest.Name)" -ForegroundColor Red
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""
# Calculate speed differences using times instead of percentages
Write-Host "Performance comparison:" -ForegroundColor Yellow
# C++ vs Go
if ($cppTotal -gt 0 -and $goTotal -gt 0) {
$cppVsGoTimes = [Math]::Round($goTotal / $cppTotal, 1)
if ($cppVsGoTimes -ge 1.1) {
Write-Host " C++ is $($cppVsGoTimes)x faster than Go" -ForegroundColor Green
} elseif ($cppVsGoTimes -le 0.9) {
$goVsCppTimes = [Math]::Round($cppTotal / $goTotal, 1)
Write-Host " Go is $($goVsCppTimes)x faster than C++" -ForegroundColor Red
} else {
Write-Host " C++ and Go have similar performance" -ForegroundColor Yellow
}
}
# C++ vs Rust
if ($hasRust -and $cppTotal -gt 0 -and $rustTotal -gt 0) {
$cppVsRustTimes = [Math]::Round($rustTotal / $cppTotal, 1)
if ($cppVsRustTimes -ge 1.1) {
Write-Host " C++ is $($cppVsRustTimes)x faster than Rust" -ForegroundColor Green
} elseif ($cppVsRustTimes -le 0.9) {
$rustVsCppTimes = [Math]::Round($cppTotal / $rustTotal, 1)
Write-Host " Rust is $($rustVsCppTimes)x faster than C++" -ForegroundColor Red
} else {
Write-Host " C++ and Rust have similar performance" -ForegroundColor Yellow
}
}
Write-Host ""
# Also test --version and --help commands for completeness
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "COMMAND PERFORMANCE TESTS" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""
# Test --version
Write-Host "Testing --version command:" -ForegroundColor Yellow
$goVersionTime = Measure-Command { & $witrGo --version | Out-Null }
Write-Host " Go: $([Math]::Round($goVersionTime.TotalMilliseconds, 2)) ms" -ForegroundColor Green
if ($hasRust) {
$rustVersionTime = Measure-Command { & $witrRust --version | Out-Null }
Write-Host " Rust: $([Math]::Round($rustVersionTime.TotalMilliseconds, 2)) ms" -ForegroundColor Green
}
$cppVersionTime = Measure-Command { & $witrCpp --version | Out-Null }
Write-Host " C++: $([Math]::Round($cppVersionTime.TotalMilliseconds, 2)) ms" -ForegroundColor Green
Write-Host ""
# Test --help
Write-Host "Testing --help command:" -ForegroundColor Yellow
$goHelpTime = Measure-Command { & $witrGo --help | Out-Null }
Write-Host " Go: $([Math]::Round($goHelpTime.TotalMilliseconds, 2)) ms" -ForegroundColor Green
if ($hasRust) {
$rustHelpTime = Measure-Command { & $witrRust --help | Out-Null }
Write-Host " Rust: $([Math]::Round($rustHelpTime.TotalMilliseconds, 2)) ms" -ForegroundColor Green
}
$cppHelpTime = Measure-Command { & $witrCpp --help | Out-Null }
Write-Host " C++: $([Math]::Round($cppHelpTime.TotalMilliseconds, 2)) ms" -ForegroundColor Green
Write-Host ""
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "Performance comparison complete!" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan