Skip to content

Commit 597b45c

Browse files
committed
perf: switched to jom for windows builds
1 parent b74e0f7 commit 597b45c

12 files changed

Lines changed: 308 additions & 36 deletions

File tree

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
1-
name: Setup
1+
name: Setup Windows build tools
22
runs:
33
using: composite
44
steps:
5-
- name: Setup MySQL
6-
shell: cmd
7-
run: |
8-
mysqld --initialize-insecure
9-
mysqld --install
10-
net start MySQL
11-
mysql --port=3306 --user=root --password="" -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'Password12!'; FLUSH PRIVILEGES;"
12-
- name: Setup MSSQL
5+
- name: Install jom
136
shell: pwsh
147
run: |
15-
choco install sql-server-express -y --no-progress --install-arguments="/SECURITYMODE=SQL /SAPWD=Password12!"
16-
- name: Setup PostgreSQL
8+
$jomDirectory = Join-Path $env:RUNNER_TEMP "jom"
9+
$jomArchive = Join-Path $env:RUNNER_TEMP "jom.zip"
10+
Invoke-WebRequest https://download.qt.io/official_releases/jom/jom_1_1_7.zip -OutFile $jomArchive
11+
if ((Get-FileHash $jomArchive -Algorithm SHA256).Hash -ne "4C8AF345586A9A08FBFD2F613FCAC748226D91A75627AA3581B297DD513046FE") {
12+
throw "Unexpected jom archive checksum"
13+
}
14+
Expand-Archive $jomArchive -DestinationPath $jomDirectory
15+
$jomDirectory | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
16+
- name: Install sccache
17+
if: ${{ env.CLANG_TOOLSET != '1' }}
1718
shell: pwsh
1819
run: |
19-
$postgresService = if ($env:PHP_BUILD_CRT -eq "vs18") { "postgresql-x64-17" } else { "postgresql-x64-14" }
20-
Set-Service -Name $postgresService -StartupType manual -Status Running
21-
pwsh -Command { $env:PGPASSWORD="root"; & "$env:PGBIN\psql" -U postgres -c "ALTER USER postgres WITH PASSWORD 'Password12!';" }
20+
$sccacheDirectory = Join-Path $env:RUNNER_TEMP "sccache-bin"
21+
$sccacheCacheDirectory = Join-Path $env:RUNNER_TEMP "sccache"
22+
$sccacheArchive = Join-Path $env:RUNNER_TEMP "sccache.zip"
23+
Invoke-WebRequest https://github.com/mozilla/sccache/releases/download/v0.15.0/sccache-v0.15.0-x86_64-pc-windows-msvc.zip -OutFile $sccacheArchive
24+
if ((Get-FileHash $sccacheArchive -Algorithm SHA256).Hash -ne "DCF489090AA5EF4C7D145E8B29F759124C803D636C3107F397BD50D425B5F341") {
25+
throw "Unexpected sccache archive checksum"
26+
}
27+
Expand-Archive $sccacheArchive -DestinationPath $sccacheDirectory
28+
(Join-Path $sccacheDirectory "sccache-v0.15.0-x86_64-pc-windows-msvc") |
29+
Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
30+
"SCCACHE_DIR=$sccacheCacheDirectory" |
31+
Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

.github/matrix.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
['name' => 'PHP-8.2', 'ref' => 'PHP-8.2', 'version' => [8, 2]],
99
];
1010

11+
// Temporary while profiling Windows CI builds. Remove after this work is complete.
12+
const WINDOWS_ONLY_CI = true;
13+
const WINDOWS_SINGLE_VARIANT_CI = true;
14+
1115
function get_branch_commit_cache_file_path(): string {
1216
return dirname(__DIR__) . '/branch-commit-cache.json';
1317
}
@@ -180,13 +184,21 @@ function select_jobs($repository, $trigger, $nightly, $labels, $php_version, $re
180184

181185
$labels = json_decode($argv[4] ?? '[]', true) ?? [];
182186
$labels = array_column($labels, 'name');
183-
$all_variations = $nightly || in_array('CI: All variations', $labels, true);
187+
$all_variations = WINDOWS_ONLY_CI || $nightly || in_array('CI: All variations', $labels, true);
184188

185189
$repository = $argv[5] ?? null;
186190

187191
foreach ($branches as &$branch) {
188192
$php_version = $branch['version'][0] . '.' . $branch['version'][1];
189193
$branch['jobs'] = select_jobs($repository, $trigger, $nightly, $labels, $php_version, $branch['ref'], $all_variations);
194+
if (WINDOWS_ONLY_CI) {
195+
$branch['jobs'] = array_intersect_key($branch['jobs'], ['WINDOWS' => true]);
196+
if (WINDOWS_SINGLE_VARIANT_CI) {
197+
$branch['jobs']['WINDOWS']['matrix']['include'] = [
198+
$branch['jobs']['WINDOWS']['matrix']['include'][0],
199+
];
200+
}
201+
}
190202
$branch['config']['ubuntu_version'] = version_compare($php_version, '8.5', '>=') ? '24.04' : '22.04';
191203
}
192204

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
$ErrorActionPreference = "Stop"
2+
3+
$databaseSetup = Join-Path $PSScriptRoot "setup_test_databases.ps1"
4+
$databaseJob = Start-Job -FilePath $databaseSetup
5+
6+
try {
7+
$buildStopwatch = [System.Diagnostics.Stopwatch]::StartNew()
8+
& (Join-Path $PSScriptRoot "build.bat")
9+
$buildExitCode = $LASTEXITCODE
10+
$buildStopwatch.Stop()
11+
Write-Host "PHP build duration: $($buildStopwatch.Elapsed)"
12+
13+
$databaseWaitStopwatch = [System.Diagnostics.Stopwatch]::StartNew()
14+
Wait-Job -Job $databaseJob | Out-Null
15+
$databaseWaitStopwatch.Stop()
16+
Write-Host "Database wait after PHP build: $($databaseWaitStopwatch.Elapsed)"
17+
18+
$databaseState = $databaseJob.State
19+
$databaseError = $databaseJob.ChildJobs[0].JobStateInfo.Reason
20+
Receive-Job -Job $databaseJob -ErrorAction Continue
21+
22+
if ($buildExitCode -ne 0) {
23+
throw "PHP build exited with code $buildExitCode"
24+
}
25+
if ($databaseState -ne "Completed") {
26+
throw "Test database setup failed: $databaseError"
27+
}
28+
} finally {
29+
if ($databaseJob.State -eq "Running") {
30+
Stop-Job -Job $databaseJob
31+
}
32+
Remove-Job -Job $databaseJob
33+
}

.github/scripts/windows/build_task.bat

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ if "%CLANG_TOOLSET%" equ "1" (
4141

4242
cmd /c configure.bat ^
4343
--enable-snapshot-build ^
44+
--enable-parallel-build ^
4445
--disable-debug-pack ^
4546
--without-analyzer ^
4647
--enable-object-out-dir=%PHP_BUILD_OBJ_DIR% ^
@@ -49,9 +50,23 @@ cmd /c configure.bat ^
4950
--disable-test-ini
5051
if %errorlevel% neq 0 exit /b 3
5152

52-
nmake /NOLOGO
53+
if "%CLANG_TOOLSET%" equ "1" goto build_clang
54+
55+
sccache --zero-stats
56+
jom /NOLOGO CC="sccache cl.exe"
57+
if %errorlevel% neq 0 exit /b 3
58+
jom /NOLOGO CC="sccache cl.exe" comtest.dll
5359
if %errorlevel% neq 0 exit /b 3
54-
nmake /NOLOGO comtest.dll
60+
sccache --show-stats
61+
sccache --stop-server
62+
goto build_complete
63+
64+
:build_clang
65+
jom /NOLOGO
5566
if %errorlevel% neq 0 exit /b 3
67+
jom /NOLOGO comtest.dll
68+
if %errorlevel% neq 0 exit /b 3
69+
70+
:build_complete
5671

5772
exit /b 0
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
$ErrorActionPreference = "Stop"
2+
3+
function Invoke-NativeCommand {
4+
param(
5+
[string] $Description,
6+
[string] $FilePath,
7+
[string[]] $ArgumentList
8+
)
9+
10+
& $FilePath @ArgumentList
11+
if ($LASTEXITCODE -ne 0) {
12+
throw "$Description exited with code $LASTEXITCODE"
13+
}
14+
}
15+
16+
$totalStopwatch = [System.Diagnostics.Stopwatch]::StartNew()
17+
$sqlServerStopwatch = [System.Diagnostics.Stopwatch]::StartNew()
18+
19+
Invoke-NativeCommand "SQL Server Express installation" "choco.exe" @(
20+
"install",
21+
"sql-server-express",
22+
"--version=2022.16.0.20260305",
23+
"-y",
24+
"--no-progress",
25+
"--install-arguments=/SECURITYMODE=SQL /SAPWD=Password12!"
26+
)
27+
$sqlServerStopwatch.Stop()
28+
Write-Host "SQL Server Express setup duration: $($sqlServerStopwatch.Elapsed)"
29+
30+
$mysqlStopwatch = [System.Diagnostics.Stopwatch]::StartNew()
31+
Invoke-NativeCommand "MySQL initialization" "mysqld.exe" @("--initialize-insecure")
32+
Invoke-NativeCommand "MySQL service installation" "mysqld.exe" @("--install")
33+
Invoke-NativeCommand "MySQL service startup" "net.exe" @("start", "MySQL")
34+
Invoke-NativeCommand "MySQL root account setup" "mysql.exe" @(
35+
"--port=3306",
36+
"--user=root",
37+
"-e",
38+
"ALTER USER 'root'@'localhost' IDENTIFIED BY 'Password12!'; FLUSH PRIVILEGES;"
39+
)
40+
$mysqlStopwatch.Stop()
41+
Write-Host "MySQL setup duration: $($mysqlStopwatch.Elapsed)"
42+
43+
$postgresStopwatch = [System.Diagnostics.Stopwatch]::StartNew()
44+
$postgresService = if ($env:PHP_BUILD_CRT -eq "vs18") { "postgresql-x64-17" } else { "postgresql-x64-14" }
45+
Set-Service -Name $postgresService -StartupType Manual -Status Running
46+
$env:PGPASSWORD = "root"
47+
Invoke-NativeCommand "PostgreSQL account setup" "$env:PGBIN\psql.exe" @(
48+
"-U",
49+
"postgres",
50+
"-c",
51+
"ALTER USER postgres WITH PASSWORD 'Password12!';"
52+
)
53+
$postgresStopwatch.Stop()
54+
Write-Host "PostgreSQL setup duration: $($postgresStopwatch.Elapsed)"
55+
56+
$totalStopwatch.Stop()
57+
Write-Host "Total database setup duration: $($totalStopwatch.Elapsed)"

.github/workflows/test-suite.yml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -857,21 +857,43 @@ jobs:
857857
PLATFORM: ${{ matrix.x64 && 'x64' || 'x86' }}
858858
THREAD_SAFE: "${{ matrix.zts && '1' || '0' }}"
859859
INTRINSICS: "${{ matrix.zts && 'AVX2' || '' }}"
860-
PARALLEL: -j2
860+
PARALLEL: -j4
861861
OPCACHE: "${{ matrix.opcache && '1' || '0' }}"
862862
ASAN: "${{ matrix.asan && '1' || '0' }}"
863863
CLANG_TOOLSET: "${{ matrix.clang && '1' || '0' }}"
864+
SCCACHE_CACHE_SIZE: 1G
865+
SCCACHE_IGNORE_SERVER_IO_ERROR: "1"
866+
SCCACHE_CACHE_KEY: windows-sccache-v2-php${{ join(fromJson(inputs.branch).version, '.') }}-${{ fromJson(inputs.branch).jobs.WINDOWS.config.vs_crt_version }}-${{ matrix.x64 && 'x64' || 'x86' }}-zts${{ matrix.zts && '1' || '0' }}-asan${{ matrix.asan && '1' || '0' }}-${{ github.sha }}
867+
SCCACHE_CACHE_RESTORE_PREFIX: windows-sccache-v2-php${{ join(fromJson(inputs.branch).version, '.') }}-${{ fromJson(inputs.branch).jobs.WINDOWS.config.vs_crt_version }}-${{ matrix.x64 && 'x64' || 'x86' }}-zts${{ matrix.zts && '1' || '0' }}-asan${{ matrix.asan && '1' || '0' }}-
864868
steps:
865869
- name: git config
866870
run: git config --global core.autocrlf false && git config --global core.eol lf
867871
- name: git checkout
868872
uses: actions/checkout@v6
869873
with:
870874
ref: ${{ fromJson(inputs.branch).ref }}
871-
- name: Setup
875+
- name: Setup Windows build tools
872876
uses: ./.github/actions/setup-windows
873-
- name: Build
874-
run: .github/scripts/windows/build.bat
877+
- name: Restore MSVC compiler cache
878+
if: ${{ !matrix.clang }}
879+
continue-on-error: true
880+
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
881+
with:
882+
path: ${{ runner.temp }}\sccache
883+
key: ${{ env.SCCACHE_CACHE_KEY }}
884+
restore-keys: ${{ env.SCCACHE_CACHE_RESTORE_PREFIX }}
885+
- name: Build PHP while preparing test databases
886+
shell: pwsh
887+
run: .github/scripts/windows/build_and_setup_test_databases.ps1
888+
# Pull request caches are isolated to the PR merge ref and cannot update
889+
# caches used by the base branch or other pull requests.
890+
- name: Save MSVC compiler cache
891+
if: ${{ !matrix.clang }}
892+
continue-on-error: true
893+
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
894+
with:
895+
path: ${{ runner.temp }}\sccache
896+
key: ${{ env.SCCACHE_CACHE_KEY }}
875897
- name: Test
876898
run: .github/scripts/windows/test.bat
877899
FREEBSD:

ext/com_dotnet/Makefile.frag.w32

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@ $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.c: ext\com_dotnet\tests\comt
22
-md $(BUILD_DIR)\ext\com_dotnet\tests\comtest
33
midl /nologo /h $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.h /iid $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.c /tlb $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.tlb ext\com_dotnet\tests\comtest\comtest.idl
44

5+
!if "$(PARALLEL_BUILD)" == "yes"
6+
$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.obj: ext\com_dotnet\tests\comtest\comtest.cpp $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.c
7+
$(PHP_CL) /nologo /c /Fo$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.obj /I $(BUILD_DIR)\ext\com_dotnet\tests\comtest ext\com_dotnet\tests\comtest\comtest.cpp
8+
9+
$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.obj: $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.c
10+
$(PHP_CL) /nologo /c /Fo$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.obj $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.c
11+
!else
512
$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.obj $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.obj: ext\com_dotnet\tests\comtest\comtest.cpp $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.c
613
$(PHP_CL) /nologo /c /Fo$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.obj /I $(BUILD_DIR)\ext\com_dotnet\tests\comtest ext\com_dotnet\tests\comtest\comtest.cpp
714
$(PHP_CL) /nologo /c /Fo$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.obj $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.c
15+
!endif
816

917
$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.dll: $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.obj $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.obj ext\com_dotnet\tests\comtest\comtest.def
1018
"$(LINK)" /nologo /dll /out:$(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.dll $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest.obj $(BUILD_DIR)\ext\com_dotnet\tests\comtest\comtest_i.obj /def:ext\com_dotnet\tests\comtest\comtest.def OleAut32.lib

ext/json/Makefile.frag.w32

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1+
!if "$(PARALLEL_BUILD)" == "yes"
2+
ext\json\php_json_scanner_defs.h: ext\json\json_scanner.c
3+
ext\json\json_scanner.c: ext\json\json_scanner.re ext\json\json_parser.tab.h
4+
$(RE2C) $(RE2C_FLAGS) -t ext/json/php_json_scanner_defs.h -bci -o ext/json/json_scanner.c ext/json/json_scanner.re
5+
6+
ext\json\json_parser.tab.h: ext\json\json_parser.tab.c
7+
ext\json\json_parser.tab.c: ext\json\json_parser.y
8+
$(BISON) $(BISON_FLAGS) --defines -l ext/json/json_parser.y -o ext/json/json_parser.tab.c
9+
!else
110
ext\json\json_scanner.c ext\json\php_json_scanner_defs.h: ext\json\json_scanner.re ext\json\json_parser.tab.h
211
$(RE2C) $(RE2C_FLAGS) -t ext/json/php_json_scanner_defs.h -bci -o ext/json/json_scanner.c ext/json/json_scanner.re
312

413
ext\json\json_parser.tab.c ext\json\json_parser.tab.h: ext\json\json_parser.y
514
$(BISON) $(BISON_FLAGS) --defines -l ext/json/json_parser.y -o ext/json/json_parser.tab.c
15+
!endif

ext/standard/Makefile.frag.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ext\standard\url_scanner_ex.c: ext\standard\url_scanner_ex.re
66
cd $(PHP_SRC_DIR)
77
$(RE2C) $(RE2C_FLAGS) -b -o ext/standard/url_scanner_ex.c ext/standard/url_scanner_ex.re
88

9-
$(BUILD_DIR)\ext\standard\basic_functions.obj: $(PHP_SRC_DIR)\Zend\zend_language_parser.h
9+
$(BUILD_DIR)\ext\standard\basic_functions.obj: Zend\zend_language_parser.h
1010

1111
$(PHP_SRC_DIR)\ext\standard\tests\helpers\bad_cmd.exe: $(PHP_SRC_DIR)\ext\standard\tests\helpers\bad_cmd.c
1212
cd $(PHP_SRC_DIR)\ext\standard\tests\helpers

0 commit comments

Comments
 (0)