Powershell: foreach-object Memory usage

Created on 6 Apr 2020  ·  3Comments  ·  Source: PowerShell/PowerShell

Steps to reproduce

Eventually it was killed

10..60000|foreach-object -ThrottleLimit 15 -parallel {
if(Test-Connection “127.0.0.1” -TcpPort $_ -TimeoutSeconds 1){
“$ip listening to port $_”
}
}

Expected behavior


Actual behavior

20200406_151832-out


Environment data

PSVersion                      7.1.0-preview.1
PSEdition                      Core
GitCommitId                    7.1.0-preview.1
OS                             Linux 3.10.0-1062.18.1.el7.x86_64 … Platform                       Unix                                PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3                                 SerializationVersion           1.1.0.1                             WSManStackVersion              3.0
Area-Cmdlets-Core Issue-Question Resolution-Answered WG-Engine-Performance

Most helpful comment

I don't know what "eventually it was killed" means or where "actual behavior" animation comes from.
But this sounds like the CLR is not collecting free'd memory quick enough. You can alleviate this to some degree by inserting '[gc]::Collect()' into your loop.

Or, you can use the new foreach-object -parallel that re-uses runspaces, which greatly reduces memory use. It has been checked into the preview 1 branch, but is not yet part of the preview release. I am not sure when the preview release will be updated but you can clone the master branch and build it yourself if you want to try it out.

See: PR #12122

The new foreach-object -parallel re-uses runspaces by default but you can revert to the previous behavior by selecting the -UseNewRunspace parameter switch. You can also verify that you are using the new version of foreach-object -parallel by checking if this parameter switch is available.

# Runspace reuse is automatic
1..1000 | foreach-object -parallel { "Hello: $_" }

# Revert to old behavior where new runspace is created/discarded for each loop iteration
1..1000 | foreach-object -parallel { "Hello: $_" } -UseNewRunspace

All 3 comments

/cc @PaulHigin

I don't know what "eventually it was killed" means or where "actual behavior" animation comes from.
But this sounds like the CLR is not collecting free'd memory quick enough. You can alleviate this to some degree by inserting '[gc]::Collect()' into your loop.

Or, you can use the new foreach-object -parallel that re-uses runspaces, which greatly reduces memory use. It has been checked into the preview 1 branch, but is not yet part of the preview release. I am not sure when the preview release will be updated but you can clone the master branch and build it yourself if you want to try it out.

See: PR #12122

The new foreach-object -parallel re-uses runspaces by default but you can revert to the previous behavior by selecting the -UseNewRunspace parameter switch. You can also verify that you are using the new version of foreach-object -parallel by checking if this parameter switch is available.

# Runspace reuse is automatic
1..1000 | foreach-object -parallel { "Hello: $_" }

# Revert to old behavior where new runspace is created/discarded for each loop iteration
1..1000 | foreach-object -parallel { "Hello: $_" } -UseNewRunspace

This issue has been marked as answered and has not had any activity for 1 day. It has been closed for housekeeping purposes.

Was this page helpful?
0 / 5 - 0 ratings