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

PowerShell7读取GB级单行JSON报OutOfMemoryException异常咨询

问题1:64位PowerShell在约3.6GB内存占用时触发OOM的原因

首先澄清两个核心认知偏差:

  • MaxMemoryPerShellMB配置仅对PowerShell 5.1及更早的Windows PowerShell版本的远程会话生效,跨平台的PowerShell 7+完全不读取该配置项,无论你将其调整为8096还是保持默认的2147483647,都不会对本地运行的pwsh进程内存分配产生任何影响,调整无效果是正常现象。
  • 你观察到的3.6GB内存阈值和32位进程的内存限制没有任何关联。触发OOM的根本原因是读取方式和文件特性不匹配:
    • 你的测试文件是minified格式,整份1.8GB(1,832,252,369字节)的JSON全部存储在单行内,Get-Content默认按换行符切分读取内容,遇到无换行的单行会尝试将整行内容一次性加载为.NET字符串对象。
    • .NET的字符串默认使用UTF-16编码,每个字符占2字节,1.8GB的UTF-8编码文本转换为UTF-16字符串后,实际占用内存恰好约3.6GB,和你观测到的进程内存阈值完全吻合。
    • .NET运行时中,超过85000字节的对象会被分配到大对象堆(LOH),默认场景下大对象堆不会自动执行内存压缩,即使设备总剩余内存充足,只要堆上没有足够大的连续内存块来存放这个3.6GB的字符串,就会直接抛出System.OutOfMemoryException,和进程是32位还是64位没有必然联系。
问题2:PowerShell处理GB级单行minified JSON的可行方案

PowerShell完全可以胜任该场景的处理,核心原则是永远不要尝试将GB级的单行文件一次性全量加载进内存,你仅需要探查结构的话,用流式读取方案内存占用可以稳定在几十MB级别,不需要切换其他工具。

探查文件结构的内置实现(无需额外依赖)

直接调用.NET底层的流式读取API,搭配System.Text.Json.Utf8JsonReader逐字节读取JSON流,仅记录结构信息、不加载全量内容即可。以下是可直接运行的示例脚本,会自动读取JSON前10层、前200个节点生成结构预览,跑1.8GB的文件仅需数秒,内存占用不超过100MB:

# 替换为你的JSON文件路径
$filePath = "D:\test\large_minified.json"
$stream = [System.IO.File]::OpenRead($filePath)
$jsonReader = [System.Text.Json.Utf8JsonReader]::new($stream, [System.Text.Json.JsonReaderOptions]@{
    CommentHandling = [System.Text.Json.JsonCommentHandling]::Skip
})

# 配置探查截断规则,避免读取全文件
$maxExploreDepth = 10
$maxNodeCount = 200
$currentDepth = 0
$currentNodeCount = 0
$isTruncated = $false
$structureOutput = [System.Collections.Generic.List[string]]::new()

while ($jsonReader.Read()) {
    $currentNodeCount++
    if ($currentNodeCount -gt $maxNodeCount -or $currentDepth -gt $maxExploreDepth) {
        $isTruncated = $true
        break
    }
    switch ($jsonReader.TokenType) {
        StartObject {
            $structureOutput.Add(("  " * $currentDepth) + "{")
            $currentDepth++
            break
        }
        EndObject {
            $currentDepth--
            $structureOutput.Add(("  " * $currentDepth) + "}")
            break
        }
        StartArray {
            $structureOutput.Add(("  " * $currentDepth) + "[")
            $currentDepth++
            break
        }
        EndArray {
            $currentDepth--
            $structureOutput.Add(("  " * $currentDepth) + "]")
            break
        }
        PropertyName {
            $structureOutput.Add(("  " * $currentDepth) + "$($jsonReader.GetString()):")
            break
        }
        # 值仅标记类型,不读取具体内容降低内存占用
        String { $structureOutput[-1] += " <string>" }
        Number { $structureOutput[-1] += " <number>" }
        True { $structureOutput[-1] += " <bool=true>" }
        False { $structureOutput[-1] += " <bool=false>" }
        Null { $structureOutput[-1] += " <null>" }
    }
}
$stream.Dispose()

if ($isTruncated) {
    $structureOutput.Add("`n... 结构探查已截断,展示范围为前$maxExploreDepth层、前$maxNodeCount个节点,如需查看更深层结构可调整截断阈值")
}
# 结构结果输出到当前目录的txt文件
$structureOutput | Out-File .\json_structure_preview.txt -Encoding utf8

后续处理注意事项

  • 绝对不要使用Get-Content -Raw读取GB级文件,该参数会强制将整个文件拼接为单个字符串,必然触发大内存分配导致OOM。
  • 绝对不要对GB级JSON直接使用ConvertFrom-Json,该cmdlet会全量反序列化整个JSON为PSCustomObject,1.8GB的JSON反序列化后对象内存占用会超过10GB,性能和内存开销极高。
  • 如果后续需要提取JSON中的特定字段、或者做全量数据处理,仍然可以基于Utf8JsonReader做流式处理:匹配到目标路径时仅读取对应节点的值,处理完成后直接释放对应内存,全程内存占用可以保持在稳定的低水平,性能和原生编译的处理工具没有明显差距。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:48:19