简述PowerShell脚本优化技巧 |
| 发布时间: 2012/7/12 9:23:35 |
|
PowerShell脚本很有用,但有的却消耗大量的内存,或者需要很长的执行时间。下面是关于如何提高此类脚本性能的一些技巧。
最后优化 不要试图在你写代码的时候优化PowerShell脚本。你对代码的优化或许并不明显,或许对最终的性能影响甚微。脚本编写者的时间比起CPU周期更为宝贵。 使用筛选参数 PowerShell会消耗大量的资源,因为许多cmdlet被设计成处理巨大的数据量。所以,如果你在使用一个有筛选参数(-Filter,-Include,或-Exclude)的cmdlet,那就首先使用它。 如果一个cmdlet支持参数-Filter,你要使用它。它对一个对象使用底层API,这意味着代码执行非常快,因为筛选器在cmdlet创建对象之前应用。参数-Include和-Exclude在cmdlet创建对象之后但对象尚未进入PowerShell管道之前应用到对象。因此,它们比-Filter慢,但是他们依然比对象已经进入到PowerShell管道之后进行筛选要快。 有时候你会使用不止一种类型的筛选器。例如,假设你正搜索D盘所有以.htm为文件扩展名的文件。参数-Filter使用传统的Windows文件系统语义,.htm返回所有以.htm为扩展名的文件。Windows API实现这种过滤,这使它非常快。然而,这是传统API的一个极大限制。它们很陈旧,因此会忽略文件扩展名中除了前三个字符以外的其他字符。例如,一个仅仅以-Filter对*.htm的筛选将只返回.htm文件。因此,对于快速筛选,你需要使用-Filter(在装载前削减大量文件)和-Include(只获取.htm文件)。下面是代码样例:
然而,请记住,-Filter使用底层API,因此它工作的速度依赖于这些API。举个例子:
在这种情况下,参数-Filter运行较慢,因为Get-WmiObject cmdlet使用Windows管理规范(WMI)脚本API。而这也慢是因为WMI使用WMI查询语言(WQL)进行筛选,这就是筛选与WMI的关系。 减少资源占用 性能优化是降低资源占用以及减少可执行时间。有时,你可以两者兼具。另外一些时候,你必须作出选择。例如,假设你需要列出D盘的文件并对每个文件操作。你可以使用ForEach-Object cmdlet遍历集合中的文件系统对象,如下:
其中{…}表示代码将对每个文件执行。当你使用这个cmdlet,在穿越管道界限时每个对象都要经过额外的封装操作,这显著地降低了代码的效率。但是它并不消耗太多的内存,因为每次同时只有一个项目通过管道。 或者,你可以使用foreach迭代循环,如以下代码所示:
其中{…}表示代码将对每个文件执行。这个循环花费了较少的运行时间,因为它避免了管道界限。不过,它在处理所有的文件系统对象之前首先进行收集,因此如果收集的数量很大的话它会消耗过多的系统资源。 Foreach循环更快但却比ForEach-Object cmdlet使用更多的内存。因此,如果你不希望有大的数据集foreach循环通常是一个更好的选择。 以睡眠扼制CPU 触及很多对象的PowerShell代码经常需要很长的执行时间,并且不太容易释放占用的处理器时间。比起在单核CPU时代,这已经少了很多麻烦,但是这依然会导致系统为一个任务长时间等待。如果你的代码消耗了大量的CPU周期,或需要长时间的等待,通常会使用Start-Sleep cmdlet来释放处理器。默认情况下,Start-Sleep操作在数秒之内,但你可以以毫秒为单位指定暂停时间。时钟的分辨率通常不超过10到20毫秒的范围,所以你可能想指定的最短休眠时间是20毫秒。此外,你不需要在每个循环中运行一个睡眠周期;只需每隔几个周期进行释放就足以保证当前CPU对其他工作也是可用的。下面是一个使用Start-Sleep和取余操作符(%)每10个项目释放一次处理器的周期:
一个基本的优化计划 你可以把这些技巧组合成一个基本的脚本优化计划。首先,不必担心优化问题直到脚本完成。其次,如果可能,使用-Filter约束你的脚本读取项目的数量,并使用-Include和-Exclude做进一步调整。这应该同时减少运行时间和资源占用。在这一点上,如果你依然有大数量的项目,考虑使用foreach循环替代ForEach-Object管道元素,从而加速脚本运行。请记住,如果你正在查看成千上万的对象,这可能会引发其他性能问题。最后,如果你的脚本有过多的CPU消耗,你可以在循环核心中使用Start-Sleep来观察执行效果。 本文出自:亿恩科技【www.enkj.com】 |
京公网安备41019702002023号