Powershell 从函数返回字节数组时内存消耗高

Powershell 从函数返回字节数组时内存消耗高,powershell,Powershell,我正在尝试下载一个10MB的文件,并将其存储为一个数组以供进一步处理 当直接调用(新对象System.Net.WebClient)下载数据(“”)时,一切看起来都很好。但是如果我把它包装在一个函数中并返回调用内存的结果,内存占用就会增加到500mb左右 我使用的函数: function My-Download { param ( [Parameter(Mandatory = $True, Position = 1)] [String] $UrlCode )

我正在尝试下载一个10MB的文件,并将其存储为一个数组以供进一步处理

当直接调用
(新对象System.Net.WebClient)下载数据(“”
)时,一切看起来都很好。但是如果我把它包装在一个函数中并返回调用内存的结果,内存占用就会增加到500mb左右

我使用的函数:

function My-Download {
    param (
        [Parameter(Mandatory = $True, Position = 1)] [String] $UrlCode
    )
    (New-Object System.Net.WebClient).DownloadData($UrlCode)
}
$x = My-Download("https://file-examples.com/wp-content/uploads/2017/04/file_example_MP4_1280_10MG.mp4")
我将其包装在函数中的原因是,在返回数据之前,我还对数据进行了额外的处理,但即使是这个小示例也说明了这个问题

调用
$x=(新对象System.Net.WebClient)。下载数据(“https://file-examples.com/wp-content/uploads/2017/04/file_example_MP4_1280_10MG.mp4“”
结果为83MB:

调用上述函数会产生500MB的结果:

内存使用率如此之高的原因是什么?我可以做些什么来优化它

Powershell版本:

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      17134  407

[System.Net.WebClient]
类型的
.DownloadData()
方法返回字节数组(
[byte[]]

  • 如果将调用该方法的输出直接分配给变量,变量按原样接收该字节数组

  • 相反,如果对该方法的调用用于从函数生成隐式输出,
    [byte[]]
    数组的元素将一个接一个地发送到管道(byte By byte)。
    管道背后的设计意图是支持流式、对象对对象的处理,而不是收集所有结果优先的行为,当输出变为可用处理时,这种行为会一个接一个地以执行速度换取内存限制

将函数的输出分配给变量后,PowerShell会隐式收集常规
[object[]]
数组中的各个输出对象(在本例中为字节)

换句话说:最初的
[byte[]]
数组是先枚举的,后来才收集到另一个数组中,尽管是
[object[]]
类型的数组,但在您的场景中这显然是不必要和低效的

有两种方法可以选择退出此隐式枚举:

  • 您可以使用概念上明确的
    Write output-NoEnumerate调用来禁止输出数组(集合)的枚举,而不是隐式输出:

  • Write Output-NoEnumerate(新对象系统.Net.WebClient)。下载数据($UrlCode)

  • 一种更模糊、但更简洁、更快速的替代方法是将隐式输出与辅助的单元素包装数组相结合,这会导致PowerShell仅枚举包装数组,并传递包装数组,如问题注释中所示:

  • ,(新对象系统.Net.WebClient)。下载数据($UrlCode)

  • 是PowerShell的数组构造运算符(the),它以一元形式将RHS封装在单个元素数组中(类型为
    [object[]]


调用函数时不要使用括号。相反,请使用单个空格字符<代码>$x=我的下载”https://...“。另外,参数位置的第一个索引是0,而不是1。这似乎并不能解决问题。
(新对象系统.Net.WebClient)。DownloadData($UrlCode)
->,(新对象系统.Net.WebClient)。DownloadData($UrlCode),非常感谢,这很有效!逗号是什么意思?没有逗号会发生什么?@hurlenko-该位置的逗号运算符将数组包装在项目右侧。这导致PoSh的“展开收藏”功能展开外部收藏,而不展开内部收藏。显然,将集合分成几个部分进行传递是内存使用的来源我甚至不想去调查那件事。。。[咧嘴笑]