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文件)。下面是代码样例:
Get-ChildItem -Path D:\ -Filter *.htm -Include *.htm –Recurse
然而,请记住,-Filter使用底层API,因此它工作的速度依赖于这些API。举个例子:
Get-WmiObject -Class Win32_Product `
-Filter 'Vendor LIKE "%Microsoft%"'
在这种情况下,参数-Filter运行较慢,因为Get-WmiObject cmdlet使用Windows管理规范(WMI)脚本API。而这也慢是因为WMI使用WMI查询语言(WQL)进行筛选,这就是筛选与WMI的关系。
减少资源占用
性能优化是降低资源占用以及减少可执行时间。有时,你可以两者兼具。另外一些时候,你必须作出选择。例如,假设你需要列出D盘的文件并对每个文件操作。你可以使用ForEach-Object cmdlet遍历集合中的文件系统对象,如下:
Get-ChildItem -Path D:\ -Recurse | ForEach-Object {…}
其中{…}表示代码将对每个文件执行。当你使用这个cmdlet,在穿越管道界限时每个对象都要经过额外的封装操作,这显著地降低了代码的效率。但是它并不消耗太多的内存,因为每次同时只有一个项目通过管道。
或者,你可以使用foreach迭代循环,如以下代码所示:
foreach($file in (Get-ChildItem -Path D:\ -Recurse)) {...}
其中{…}表示代码将对每个文件执行。这个循环花费了较少的运行时间,因为它避免了管道界限。不过,它在处理所有的文件系统对象之前首先进行收集,因此如果收集的数量很大的话它会消耗过多的系统资源。
Foreach循环更快但却比ForEach-Object cmdlet使用更多的内存。因此,如果你不希望有大的数据集foreach循环通常是一个更好的选择。
以睡眠扼制CPU
触及很多对象的PowerShell代码经常需要很长的执行时间,并且不太容易释放占用的处理器时间。比起在单核CPU时代,这已经少了很多麻烦,但是这依然会导致系统为一个任务长时间等待。如果你的代码消耗了大量的CPU周期,或需要长时间的等待,通常会使用Start-Sleep cmdlet来释放处理器。默认情况下,Start-Sleep操作在数秒之内,但你可以以毫秒为单位指定暂停时间。时钟的分辨率通常不超过10到20毫秒的范围,所以你可能想指定的最短休眠时间是20毫秒。此外,你不需要在每个循环中运行一个睡眠周期;只需每隔几个周期进行释放就足以保证当前CPU对其他工作也是可用的。下面是一个使用Start-Sleep和取余操作符(%)每10个项目释放一次处理器的周期:
$i=0
Get-ChildItem -Recurse |
ForEach-Object{
$i+=1
if($i % 10 –eq 0){sleep -mill 20}
}
一个基本的优化计划
你可以把这些技巧组合成一个基本的脚本优化计划。首先,不必担心优化问题直到脚本完成。其次,如果可能,使用-Filter约束你的脚本读取项目的数量,并使用-Include和-Exclude做进一步调整。这应该同时减少运行时间和资源占用。在这一点上,如果你依然有大数量的项目,考虑使用foreach循环替代ForEach-Object管道元素,从而加速脚本运行。请记住,如果你正在查看成千上万的对象,这可能会引发其他性能问题。最后,如果你的脚本有过多的CPU消耗,你可以在循环核心中使用Start-Sleep来观察执行效果。
自由广告区 |
分类导航 |
邮件新闻资讯: IT业界 | 邮件服务器 | 邮件趣闻 | 移动电邮 电子邮箱 | 反垃圾邮件|邮件客户端|网络安全 行业数据 | 邮件人物 | 网站公告 | 行业法规 网络技术: 邮件原理 | 网络协议 | 网络管理 | 传输介质 线路接入 | 路由接口 | 邮件存储 | 华为3Com CISCO技术 | 网络与服务器硬件 操作系统: Windows 9X | Linux&Uinx | Windows NT Windows Vista | FreeBSD | 其它操作系统 邮件服务器: 程序与开发 | Exchange | Qmail | Postfix Sendmail | MDaemon | Domino | Foxmail KerioMail | JavaMail | Winwebmail |James Merak&VisNetic | CMailServer | WinMail 金笛邮件系统 | 其它 | 反垃圾邮件: 综述| 客户端反垃圾邮件|服务器端反垃圾邮件 邮件客户端软件: Outlook | Foxmail | DreamMail| KooMail The bat | 雷鸟 | Eudora |Becky! |Pegasus IncrediMail |其它 电子邮箱: 个人邮箱 | 企业邮箱 |Gmail 移动电子邮件:服务器 | 客户端 | 技术前沿 邮件网络安全: 软件漏洞 | 安全知识 | 病毒公告 |防火墙 攻防技术 | 病毒查杀| ISA | 数字签名 邮件营销: Email营销 | 网络营销 | 营销技巧 |营销案例 邮件人才:招聘 | 职场 | 培训 | 指南 | 职场 解决方案: 邮件系统|反垃圾邮件 |安全 |移动电邮 |招标 产品评测: 邮件系统 |反垃圾邮件 |邮箱 |安全 |客户端 |