Memory Management in PowerShell

For limited work in SharePoint PowerShell, memory is freed when the PowerShell session is closed. If your script ignores memory management, everything usually just works fine. But what happens when you alter metadata for hundreds of thousands of documents within thousands of document libraries in one PowerShell script?

Doing a simple $web.update() is not enough. In fact the implications are more significant than just memory. The SharePoint Object Model doesn’t just hold onto the memory. It also keeps the Content DB transaction open on SQL Server. The result is a growing Transaction log, until the transaction is completed. The transaction log is not flushed until the memory is explicitly released. I know, because my script started consuming tens of GBs, until I ran out of Transaction Log space.

In addition to the normal $var.update() and $var.dispose(), you want to use Start-Assignment/Stop-Assignment both locally through a named Assignment Object, and also Globally at the start/end of the script.  If you monitor SQL Transaction Logs, as well as memory utilization, the results are remarkable.  Note that you will not be able to access any of the script objects (of course) after the script run, so consider adding these as the final touch after debugging.

Here’s what to add to your scripts to keep both memory management and SQL transaction management lean and mean:

 # avoid problems, try to add in SharePoint snap-in, but don't complain if it's already loaded 
Add-PSSnapin "Microsoft.SharePoint.PowerShell"-ErrorAction SilentlyContinue
 # this frees up all assignments if you end it at end of script 
Start-SPAssignment –Global
#sample function, that cleans up after itself
function Reset-SPstuff ($WebUrl)
{
 $FuncAssign =Start-SPAssignment #start of a named assignment object
  #Here's how to allocate an object using an assignment:
$web=$FuncAssign | Get-SPWeb$WebUrl
 #your function... 
$web.Dispose()
$FuncAssign | Stop-SPAssignment    #release the named assignment object
 }
 # here's the main part of script, 
$site =... 
 #for any variable you do use without a named assignment, try to dispose of it after use:
try {$site.Dispose();} catch {Write-Host"can't dispose Site $($site.title) object"}
 # very important to end the assignment of anything from within this script between Start/Stop assignment: 
Stop-SPAssignment –Global
1 reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *