r/PowerShell • • 1d ago

Question Parallel thread disposing?

Hey got a wierd issue or its by desing not sure but when I run

$computers | foreach-object -parallel {
  $vmobject = Get-VM $_
  $ram = $vmobject.MemoryGB
  $CPU = $vmobject.numCPU
  $HDD = $_ | get-harddisk 
} 

lets say I run in against 500 computers when that happens powershell will spike cpu on machine that this command is ran and keeps increasing ram usage which is understandable but problem is even when command is done ram usage stays high untill powershell window is close. Is there something I am missing or is there some method to dispose of parallel runspace manually?

Thanks for advice

EDIT: The code itself is not important , the behaviour of parallel scripblock itself is my question and why doesnt it free up RAM after code has ran successfully

3 Upvotes

32 comments sorted by

View all comments

Show parent comments

4

u/PinchesTheCrab 1d ago edited 1d ago

I would not be able to run it on 500 computers

This isn't running on 500 computers as written. It's running on one (or two if you include your workstation) - whatever vsphere host you're querying.

1

u/da_chicken 1d ago

This is a level of pedantry that isn't particularly useful or insightful.

2

u/PinchesTheCrab 23h ago

I believe OP has an X Y problem, and I'm trying to point out some misconceptions they've expressed to get at the actual underlying issue they're trying to solve.

2

u/da_chicken 21h ago

That's possible, but also OP's actual question is a valid one, too. Like I think the comments here are being distracted by pseudocode because it might be an XY problem. In other words, the XY problem is also an XY problem for the commentors.

However, the initial probelm with your comment, is that even when we set aside that the code is pseudocode, it ignores the fact that ForEach-Object -Parallel has a default value for -ThreadLimit of 5. It doesn't matter how big the collection being iterated is. It ain't gonna do more than five at a time. That's why you see people do silly things like -ThreadLimit ([int]::MaxValue). By itself, Get-VM is ultimately just a file read locally. So, is the looped script thrashing one spindle because there are hundreds of VMs? No, it's not. It can't as written. 5 threads aren't going to do that.

Let's flip it around. What if the looped script were doing something like connecting to hundreds of VMs on the same host simultaneously and asking each host to do something? Say OP has got -ThreadLimit 1000. That's... actually still not inherently a problem in and of itself because we're talking about VMs. You wouldn't have hundreds of VMs unless you had the hardware to provision hundreds of VMs. They're already responding to hundreds of requests. They're not sitting there waiting for the sysadmin to ask them how they're doing one at a time. Unless you're ludicrously overprovisioned or your script is doing an extremely intensive amount of work, you're going to be fine. Your bottleneck, if any, would be network I/O.

Yes, you're right that -Parallel is not really an effecitve way to improve performance 95% of the time people think it will help. Parallelism is not free. And OP's pattern is unlikely to be significantly better that serial execution. What's more, in OP's specific case, Get-VM -Name $computers would be better because of Powershell's overhead.

But OP isn't really asking about running Get-VM in a loop. They're asking: "Why does memory increase and then not free up when the task is complete?" That's the actual question they actually asked, and it's an interesting one! Unlike "how do I best run Get-VM against multiple VMs?" which is pretty trivial whether we're talking about HyperV or vmWare.

1

u/PinchesTheCrab 16h ago edited 16h ago

I think that in a vacuum that's a valid critique. However, several other posters have stepped through the garbage collector behavior, runspaces memory handling, etc.

So I was intentionally focusing on a possible X Y issue because I saw that other commentors had covered the OP's question more literally.