如何在Windows多进程运行Brotli批量压缩文件至S3?
Windows环境下多进程并行Brotli压缩方案
针对单线程Brotli压缩CPU利用率低的问题,以下提供几种在Windows环境下实现8-10个并行压缩进程的方案:
一、批处理实现(原生Windows支持)
通过统计当前运行的Brotli进程数,控制并发上限,充分利用CPU资源:
@echo off setlocal enabledelayedexpansion :: 配置参数 set "max_processes=10" :: 最大并发进程数 set "source_dir=." :: 源文件目录(当前目录) set "output_dir=E:\output\brotli" :: 压缩文件输出目录 :: 自动创建输出目录 if not exist "%output_dir%" mkdir "%output_dir%" set "count=0" :: 递归遍历所有文件 for /R "%source_dir%" %%f in (*.*) do ( :: 等待直到当前进程数低于上限 :wait_loop for /f %%p in ('tasklist /fi "imagename eq brotli.exe" ^| find /c /v ""') do set "current_processes=%%p" if !current_processes! geq !max_processes! goto wait_loop :: 后台启动Brotli压缩进程 start /b "" "brotli" -Z "--output=%output_dir%\%%~nf" "%%f" set /a count+=1 ) :: 等待所有压缩进程完成 :wait_all_done tasklist /fi "imagename eq brotli.exe" | find /i "brotli.exe" >nul if not errorlevel 1 goto wait_all_done echo 所有文件压缩完成 endlocal
说明:
start /b让Brotli在后台运行,不阻塞批处理流程- 通过
tasklist实时统计Brotli进程数,超过上限则等待 - 原批处理中的
(*.)修正为(*.*),避免只匹配无扩展名的文件
二、PowerShell实现(推荐,控制更精准)
PowerShell提供更灵活的并发控制能力,分两个版本适配不同PowerShell环境:
1. PowerShell 7+版本(推荐,语法简洁)
利用ForEach-Object -Parallel原生支持并发控制:
# 配置参数 $maxConcurrent = 10 $sourceDir = "." $outputDir = "E:\output\brotli" # 自动创建输出目录 if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir | Out-Null } # 获取所有需要压缩的文件(递归遍历) $files = Get-ChildItem -Path $sourceDir -File -Recurse # 并行压缩,限制并发数 $files | ForEach-Object -Parallel { $outputPath = Join-Path $using:outputDir $_.BaseName & brotli -Z "--output=$outputPath" $_.FullName } -ThrottleLimit $maxConcurrent Write-Host "所有文件压缩完成"
2. PowerShell 5.x版本(兼容旧系统)
通过Start-Job和进程状态检测实现并发控制:
# 配置参数 $maxConcurrent = 10 $sourceDir = "." $outputDir = "E:\output\brotli" # 自动创建输出目录 if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir | Out-Null } $files = Get-ChildItem -Path $sourceDir -File -Recurse $runningJobs = @() foreach ($file in $files) { # 等待直到并发数低于上限 while ($runningJobs.Where({$_.State -eq 'Running'}).Count -ge $maxConcurrent) { Start-Sleep -Seconds 1 # 清理已完成的作业 $runningJobs = $runningJobs | Where-Object { $_.State -ne 'Completed' } } # 启动后台压缩作业 $job = Start-Job -ScriptBlock { $outputPath = Join-Path $using:outputDir $using:file.BaseName & brotli -Z "--output=$outputPath" $using:file.FullName } $runningJobs += $job } # 等待所有作业完成并清理 Wait-Job -Job $runningJobs | Out-Null Receive-Job -Job $runningJobs | Out-Null Remove-Job -Job $runningJobs Write-Host "所有文件压缩完成"
通用注意事项
- 确保
brotli.exe已添加到系统PATH,或在代码中使用完整路径(如"C:\Tools\brotli.exe") - 输出目录路径需有写入权限,避免压缩失败
- 可根据CPU核心数调整
max_processes或maxConcurrent的值(建议设置为核心数的1-1.5倍)
内容的提问来源于stack exchange,提问作者Horia Hodis
相关产品推荐
相关产品推荐

