Recommendations for writing custom scripts

Most cmdlets and scripts return information efficiently without any special handling or any noticeable effect on performance. If you plan to write custom scripts that could potentially return large data sets, however, you should consider ways to improve performance. For example, if you are writing a script that exports a large number of zones or reports on a large number of users, you might want to use the following recommendations as guidelines.

  • When testing the performance of the script, use the standard Measure-Command cmdlet to accurately measure cmdlet and script performance.

    The Measure-Command cmdlet ignores the time it takes to print all of the results returned to the PowerShell console. In many cases, the execution of a script is efficient, but rendering the results in the PowerShell console might make the cmdlet or script performance seem unacceptable.

  • Consider how you want to balance memory usage and performance when using the PowerShell pipeline if your cmdlet or script returns large data collections.

    For example, you might use foreach in a script instead of using the pipeline to improve performance.

    Use syntax similar to this:

    foreach ($cmd in Get-CdmUserProfile -Zone $z) { action_on_each_cmd }

    Instead of:

    Get-CdmUserProfile -Zone $z | action_on_each_cmd

    However, if you choose not to use the pipeline, you should keep in mind that all of the returned objects stay in memory and might cause an out-of-memory error. Therefore, you should try to maintain balance between the scripts memory usage and performance.

  • Cache the data, if possible, by writing the results to a file.

    For example, to add 1000 users to a zone use syntax similar to this to get a zone once:

    $zone = Get-CdmZone -Dn "cn=QA,cn=Zones,dc=ajax,dc=org"
    $profile1 = New-CdmUserProfile -Zone $zone -User user1@ajax.org -Uid 10001
    ...
    $profile1000 = New-CdmUserProfile -Zone $zone -User user1000@ajax.org -Uid 11000

    Instead of using syntax like this, which gets the zone from its distinguished name (DN) for every user:

    $profile1 = New-CdmUserProfile -Zone "cn=QA,cn=Zones,dc=ajax,dc=org" ‑User user1@domain.com -Uid 10001
    ...
    $profile1000 = New-CdmUserProfile -Zone "cn=QA,cn=Zones,dc=ajax,dc=org" ‑User user1000@domain.com -Uid 11000
  • Use Export-Csv instead of Out-File if possible. The Export-Csv cmdlet writes results to a file faster than the Out-File cmdlet.
  • If you are writing a script that generates a very large data set—for example, reporting information for a global zone—you might want to use the native .NET FileStream function. The FileStream function is the fastest way to write content to a file.

    For example, you might use a code snipper like this:

    $fs = New-Object IO.FileStream <file>, 'Append','Write','Read'
    $fw = New-Object System.IO.StreamWriter $fs
    $zone = Get-CdmZone -Dn "cn=global,cn=Zones,dc=ajax,dc=org"
    foreach ($cz in $zone) {$fw.WriteLine("{0} {1}", $cz.Name, $cz.Type)}
    $fw.Close()
    $fs.Dispose()