Automate JetStream 2 runs while pinning Chrome to one logical CPU at a time.
This project is useful for comparing per-core performance (or per-thread behavior) on a Windows system.
This started as a troubleshooting tool for recurring Chromium-based browser crashes with the error STATUS_ACCESS_VIOLATION.
Pinning each benchmark run to one logical CPU and logging results per core makes it easier to spot core-specific patterns, such as repeat crashes or unusual slowdowns, and can help identify a potentially faulty CPU core rather than a broader browser or system issue.
- Launches Chrome through Selenium for each CPU index.
- Pins Chrome processes to a single logical CPU using processor affinity.
- Clicks JetStream's Start Test button automatically.
- Waits for the benchmark result.
- Writes completed benchmark scores to
cpucoreprobe-scores.csv. - Writes failed/cancelled runs and diagnostics to
cpucoreprobe-errors.csv. - Handles
Ctrl+Cgracefully and records cancellation status.
cpucoreprobe.ps1- thin launcher script (CLI entry point).src/CPUCoreProbe/CPUCoreProbe.psm1- module loader and export surface.src/CPUCoreProbe/Public/Start-CPUCoreProbeRun.ps1- orchestration entry function.src/CPUCoreProbe/Private/*.ps1- internal helpers (config, browser, diagnostics, control flow).cpucoreprobe.config.json- runtime defaults (CPU range, timeouts, URL, Chrome args/paths).cpucoreprobe-scores.csv- completed run scores output file (created/appended automatically).cpucoreprobe-errors.csv- failed/cancelled run diagnostics output file (created/appended automatically).tools/chromedriver/.../chromedriver.exe- bundled ChromeDriver location.
- Windows
- PowerShell 5.1+ (works from Windows PowerShell)
- Google Chrome installed
- ChromeDriver major version matching installed Chrome major version
- Selenium PowerShell module
Install Selenium module (current user):
Install-Module Selenium -Scope CurrentUserFrom the repo root (C:\src\CPUCoreProbe):
.\cpucoreprobe.ps1To test only one CPU index from the terminal, pass the parameter flag:
.\cpucoreprobe.ps1 -CpuIndex 8To test an explicit CPU range from the terminal, pass start/end parameters:
.\cpucoreprobe.ps1 -StartCpuIndex 0 -EndCpuIndex 31The script will:
- Validate Selenium, Chrome, and ChromeDriver.
- Load runtime defaults from
cpucoreprobe.config.json. - Iterate CPU indexes in the configured range (
$cpuStartIndexto$cpuEndIndex). - Run JetStream once per CPU index.
- Append completed scores to
output.scoresCsvPathand failures/diagnostics tooutput.errorsCsvPath.
The script reads cpucoreprobe.config.json from the repository root.
Configurable values:
benchmark.urlbenchmark.buttonTimeoutSecbenchmark.resultTimeoutSecbenchmark.postNavigationDelaySecbenchmark.pollIntervalSecbenchmark.betweenRunsDelaySeccpu.defaultStartIndexcpu.defaultEndIndexchrome.driverSearchRootchrome.pathschrome.argumentsoutput.scoresCsvPathoutput.errorsCsvPathruntime.cancellationPollMsruntime.chromeProcessLookbackSecdiagnostics.enableProcDumpdiagnostics.procDumpPathdiagnostics.dumpOutputPathdiagnostics.dumpTypediagnostics.maxDumpsPerRundiagnostics.firstChanceExceptionsdiagnostics.includeBreakpointsdiagnostics.monitorTimeoutSec
Notes:
chrome.pathsis evaluated in order; first existing path is used.- Environment variables in paths are supported (for example
%LOCALAPPDATA%\\Google\\Chrome\\Application\\chrome.exe). chrome.driverSearchRoot,output.scoresCsvPath, andoutput.errorsCsvPathcan be relative to the repository root or absolute paths.- The config file is required; the script exits if the file is missing or invalid.
- Default layout keeps CSV outputs in
resultsand writes ProcDump artifacts underlogs.
CPUCoreProbe can automatically run ProcDump during each CPU test run and save crash dumps when Chrome crashes with unhandled exceptions.
How it works:
- Before each run, CPUCoreProbe starts a ProcDump monitor for
chrome.exe. - During the run, ProcDump captures dump files when exception triggers match.
- In cleanup, CPUCoreProbe stops ProcDump and records dump metadata in CSV.
Key settings:
diagnostics.enableProcDump: enable integrated dump capture.diagnostics.procDumpPath: path toprocdump.exe.diagnostics.dumpOutputPath: base folder for run dump artifacts. CPUCoreProbe creates a per-script-run subfolder (run-YYYYMMDD-HHMMSS) and stores that invocation's dump/log files beneath it.diagnostics.dumpType:Mini,MiniPlus, orFull.diagnostics.maxDumpsPerRun: max dumps per run.diagnostics.firstChanceExceptions: whentrue, captures first-chance exceptions (-e 1); otherwise second-chance (-e).diagnostics.includeBreakpoints: whentrue, include debug breakpoint exceptions (-b).diagnostics.exceptionFilters: include-filter strings passed to ProcDump (-f) to target specific crash exceptions.diagnostics.monitorTimeoutSec: max wait on monitor shutdown during cleanup.
Notes:
- ProcDump capture is best-effort. If ProcDump cannot start or attach, benchmark runs still continue and the reason is written to CSV diagnostics fields.
- Default config keeps ProcDump disabled (
diagnostics.enableProcDump=false) until you opt in. - Keep runs isolated from personal browsing, because cleanup logic can terminate recently-started Chrome processes.
CPU range can be configured in two ways:
- Default values in
cpucoreprobe.config.json(cpu.defaultStartIndexandcpu.defaultEndIndex). - Runtime parameters:
-StartCpuIndex <n> -EndCpuIndex <m>.
How it works:
- The range is inclusive, so
0and31runs CPUs0..31. - Set
8and15to test only CPUs8..15. - Use
-CpuIndex <n>when launching the script to run only CPU<n>. -CpuIndexand range parameters are separate parameter sets; combining them fails during parameter binding.cpuStartIndexmust be>= 0.cpuEndIndexmust be>= cpuStartIndex.cpuEndIndexmust be less than your machine's logical CPU count.
If values are invalid, the script exits early with a clear error message.
cpucoreprobe-scores.csv rows include:
TimestampCpuIndexScoreStatus
cpucoreprobe-errors.csv rows include:
TimestampCpuIndexStatusErrorCodeErrorMessageDumpCaptureStatusDumpCountDumpFilesDumpRunPathDumpTypeDumpLogPathDumpMonitorMessage
Notes:
cpucoreprobe-scores.csvreceives completed runs with a captured numeric score.Statusis one ofCompleted,Failed, orCancelled.cpucoreprobe-errors.csvreceives non-completed runs, includingErrorCodeand diagnostic columns.DumpCaptureStatusisDisabled,Captured,NoDump, or an error status such asToolMissing/StartFailed.- The script does not create per-run profile folders under the repository.
- Affinity mask is computed with
1L -shl $i. - The script targets the inclusive range defined by
$cpuStartIndexand$cpuEndIndex.
The script looks for ChromeDriver in this order:
- Bundled driver under
tools\chromedriver\...\chromedriver.exe(recursive search). chromedriver.exeavailable onPATH.
If Chrome major version and ChromeDriver major version do not match, the script exits with an error.
This script is local automation, but there are still security risks to be aware of:
-
Browser state and local data:
- Chrome may still use normal browser storage/state while automation runs.
- Mitigation: run benchmarks on a dedicated test account or machine when investigating crashes.
-
Third-party dependency trust:
- The script executes
chromedriver.exeand the Selenium module. A tampered binary/module could execute arbitrary code as your user. - Mitigation: only use trusted ChromeDriver builds, pin versions where possible, and keep dependencies updated.
- The script executes
-
Process control side effects:
- Cleanup logic kills recently started Chrome processes. On a shared machine or during parallel Chrome usage, this may terminate unrelated sessions.
- Mitigation: run in a dedicated test environment and avoid personal browsing during test runs.
-
Remote content execution risk:
- The benchmark page is loaded from
https://browserbench.org/JetStream/. If the source is compromised, malicious page content could run in the browser context. - Mitigation: run only against trusted HTTPS targets and keep Chrome patched.
- The benchmark page is loaded from
General guidance:
- Run this script as a standard user (not elevated) unless admin rights are explicitly required.
- Prefer isolated test machines/VMs for repeated crash investigation.
- Review script changes before running updates from external sources.
-
Selenium PowerShell module is not installed- Run:
Install-Module Selenium -Scope CurrentUser
- Run:
-
Chrome executable not found- Install Google Chrome, or edit
chrome.pathsincpucoreprobe.config.json.
- Install Google Chrome, or edit
-
Chrome/ChromeDriver mismatch- Install a ChromeDriver build matching your Chrome major version.
-
Start button not found/clickable- JetStream page layout may have changed. Update selectors in
Invoke-StartTestClick.
- JetStream page layout may have changed. Update selectors in
-
Result not detected within ... seconds- Run may have stalled, network may be unstable, or selectors in
Get-ResultTextmay need updates.
- Run may have stalled, network may be unstable, or selectors in
-
ProcDump executable not found- Install ProcDump and set
diagnostics.procDumpPathto a validprocdump.exepath.
- Install ProcDump and set
-
ProcDump monitor unavailable- Check
DumpCaptureStatus,DumpMonitorMessage, andDumpLogPathcolumns in CSV for failure details.
- Check
- Close heavy background apps before testing.
- Keep power plan consistent (for example, High performance).
- Run multiple passes and compare medians, not single runs.
- Avoid interacting with the machine during benchmark execution.
Add a license file if you plan to share or accept contributions publicly.