You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何VM桌面RDP的PowerShell控制台I/O比PSSession慢?

PowerShell文件I/O性能异常问题排查与解决

问题背景

编写应用测试自动化脚本时遇到如下异常:

  • 脚本逻辑:运行应用至崩溃、压缩日志并循环执行
  • 性能差异:处理GB级verbose日志时,SplitFile函数在RDP访问的VM桌面PowerShell控制台中运行极慢(约每分钟1KB),但在本地通过Enter-PSSession建立的远程会话中运行速度正常
  • 关联问题:后续的Compress-Archive操作也因相同原因运行缓慢

附上SplitFile函数代码:

function SplitFile {
param (
    [ValidateScript({Test-Path $_})]
    $path = "textwriteroutput.log"
)
$file = get-item $path
$parent = Split-Path $file
$Extension = [System.IO.Path]::GetExtension($file)
$Name = [System.IO.Path]::GetFileNameWithoutExtension($file) 

$dir = mkdir (Join-Path -Path $parent -ChildPath $Name)

[int]$count = 0
[int]$lines = 0

$linesplit = 20000
$reader = [System.IO.StreamReader]::new($file)

$outFilePath = Join-Path -Path $dir -ChildPath "${name}_$count.$extension"

$writer = [System.IO.StreamWriter]::new($outFilePath)

try {
    while ( $line = $reader.ReadLine() ) {
        $lines++
        $writer.WriteLine("$line") 
        if ( $lines -ge $linesplit ) {
            $lines = 0
            $writer.Flush()
            $writer.Close()
            $count++
            $outFilePath = Join-Path -Path $dir -ChildPath "${name}_$count.$extension"
            $writer = [System.IO.StreamWriter]::new($outFilePath)
        }
    }
}
finally {
    $writer.Close()
    $reader.Close()
}

return $dir

}

环境差异原因分析

1. UI渲染开销差异

RDP桌面的PowerShell控制台是带UI的交互式会话,所有脚本输出(包括隐性的调试/追踪信息)都会被定向到UI窗口,触发窗口逐行渲染逻辑。处理大文件时,这种渲染会占用大量CPU和内存,严重拖慢I/O操作。

而Enter-PSSession是无UI的远程管理会话,没有本地UI渲染负担,所有I/O操作直接在服务器端执行,性能不受UI同步影响。

2. 系统资源优先级不同

  • RDP桌面会话属于交互式用户会话,系统默认分配较低的后台资源优先级,当负载较高时,I/O操作会被优先让给前台UI进程。
  • Enter-PSSession属于远程管理会话,默认使用更高的资源调度优先级,文件I/O能获得更多磁盘带宽和CPU时间片。

3. 控制台缓冲区消耗

RDP桌面的PowerShell控制台默认启用大缓冲区保存历史输出,脚本执行时产生的隐性输出会不断扩容缓冲区,额外消耗内存和磁盘I/O。远程PSSession无此缓冲区负担,输出不会被持久化到本地缓存。

桌面环境性能优化方案

1. 抑制控制台输出

运行脚本时将所有输出重定向到$null,避免UI渲染开销:

SplitFile -path "your-large-log.log" > $null 2>&1

或在脚本开头添加全局抑制配置:

$ErrorActionPreference = "SilentlyContinue"
$ProgressPreference = "SilentlyContinue"

2. 使用非交互式控制台运行

通过powershell.exe的非交互参数启动脚本,完全绕过UI控制台:

powershell.exe -NonInteractive -File "your-script.ps1"

或用后台进程启动:

Start-Process powershell.exe -ArgumentList "-NonInteractive -File 'your-script.ps1'" -NoNewWindow -Wait

3. 优化SplitFile函数I/O逻辑

减少频繁的文件打开/关闭操作,改用批量写入:

function SplitFile {
param (
    [ValidateScript({Test-Path $_})]
    $path = "textwriteroutput.log"
)
$file = Get-Item $path
$parent = Split-Path $file
$extension = [System.IO.Path]::GetExtension($file)
$name = [System.IO.Path]::GetFileNameWithoutExtension($file) 

$dir = mkdir (Join-Path -Path $parent -ChildPath $name) -Force

[int]$count = 0
[int]$lines = 0
$linesplit = 20000
$lineBuffer = @()

$reader = [System.IO.StreamReader]::new($file.FullName)

try {
    while ( $line = $reader.ReadLine() ) {
        $lineBuffer += $line
        $lines++
        if ( $lines -ge $linesplit ) {
            $outFilePath = Join-Path -Path $dir -ChildPath "${name}_$count.$extension"
            [System.IO.File]::WriteAllLines($outFilePath, $lineBuffer)
            $lineBuffer = @()
            $lines = 0
            $count++
        }
    }
    # 写入剩余行
    if ($lineBuffer.Count -gt 0) {
        $outFilePath = Join-Path -Path $dir -ChildPath "${name}_$count.$extension"
        [System.IO.File]::WriteAllLines($outFilePath, $lineBuffer)
    }
}
finally {
    $reader.Close()
}

return $dir
}

4. 优化Compress-Archive操作

  • 抑制输出并使用快速压缩级别:
Compress-Archive -Path "log-folder\*" -DestinationPath "logs.zip" -Force -CompressionLevel Fastest > $null 2>&1
  • 用非交互式会话执行压缩命令。

5. 调整RDP会话资源优先级

在VM本地组策略中调整:

  1. 打开gpedit.msc,导航到计算机配置 > 管理模板 > Windows组件 > 远程桌面服务 > 远程桌面会话主机 > 会话时间限制,禁用不必要的会话限制
  2. 进入计算机配置 > 管理模板 > 系统 > 性能选项,提高“后台应用程序的优先级提升”值

内容的提问来源于stack exchange,提问作者ConstantSaxophones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 09:35:23