[玩转系统] 构建 PowerShell 以提高速度
作者:精品下载站 日期:2024-12-14 13:01:40 浏览:14 分类:玩电脑
构建 PowerShell 以提高速度
在每个脚本编写者的旅程中,脚本永远不够快。为了解决这个问题,我们将介绍一些如何使 Powershell 速度达到最高速度的方法。
我们不会在本文中介绍多线程 PowerShell 脚本。您可以在《PowerShell 多线程:深入探讨》一文中阅读所有相关内容。在本文中,我们将重点关注测量性能、加速循环、使用数组提高速度等等!
测量 PowerShell 速度
至关重要的是,在进行性能测试时,您可以可靠地测试和重新测试代码并在测试之间获得相似的性能数据。 PowerShell 包含 Measure-Command
cmdlet,它允许您运行脚本块并测量运行时间。
在大多数情况下,您只需在 Expression
参数脚本块内使用代码运行 Measure-Command
即可获得所需内容。但是,如果您的代码可能已经可以快速运行,并且您在几十毫秒或更短的时间内测量差异,则可能需要像下面的代码一样循环您的代码。
在此示例中,您希望 Get-ChildItem 命令能够快速完成,但如果将代码放入循环中并多次运行相同的操作,您可以更轻松地判断毫秒差异。
foreach ($i in 1..1000) {
Get-ChildItem
}
如果您的代码将被重复使用(例如在包含数百万个项目的循环中),您可能会精确地测量性能。在这种情况下,每个循环 10 毫秒的差异可能意味着数小时的执行时间。
作为这种差异的示例,您可以使用下面的脚本块创建一个文件并获取该文件的文件哈希 3 次。由于获取文件哈希的性能取决于许多变量,因此很容易显示多次运行相同命令时可能看到的微小差异。
New-Item .\test.txt
Measure-Command {Get-FileHash .\test.txt}
Measure-Command {Get-FileHash .\test.txt}
Measure-Command {Get-FileHash .\test.txt}
您会期望这段代码每次运行时大约在同一时间完成,因为它做同样的事情。以下是运行测试的结果。
这种速度差异可能是由于多种原因造成的,包括运行代码的设备上的负载、结果缓存、设备正在使用的存储上的负载、内存或分页文件的使用情况,或者设备上任何其他正在运行的任务设备。
在这种情况下,可以通过在循环中运行代码来更好地了解其平均执行情况而不是选择单个实例,从而受益匪浅。
Foreach-Object 与 Foreach 循环速度
虽然循环经常用于处理许多项目,但当出现性能问题时,它们可能成为确凿的证据。
以此脚本块为例。它循环 10,000 次,并输出前一个数字的乘积和输入的当前数字。该示例可以在任何机器上轻松重复,并且可以通过更改命令循环次数来快速扩展。
1..10000 | ForEach-Object {
if ($Last) { $Last * $_ }
$Last = $_
}
这是上面代码的输出:
虽然在许多情况下这已经足够快了,但如果相同的代码运行数十万或数百万次,则可能会导致严重的延迟。您可以改为使用 foreach
语句,如下所示:
foreach ($Num in 1..10000) {
if ($Last) { $Last * $Num }
$Last = $Num
}
此代码提供相同的输出,但由于使用了 foreach
语句而不是 ForEach-Object
。
您的性能差异结果将根据循环中的具体代码而有所不同,但您应该亲自尝试一下。
为了更快地执行,有时您可以完全省略循环,而只依赖管道来执行整组命令。下面是一些代码,它将循环遍历目录中的所有文件,并使用 foreach
语句获取每个文件的文件哈希值。
运行 Get-ChildItem 命令时,它会输出有关文件的信息,包括文件的路径。这可以通过 Get-FileHash 命令直接通过管道使用。
foreach ($File in Get-ChildItem) {
Get-FileHash $File
}
编写此代码的更好方法是在没有循环的单个管道中,如下所示:
Get-ChildItem | Get-FileHash
这些代码集会输出相同的内容,但后者显示出巨大的性能提升。
这个包含 Get-ChildItem
和 Get-FileHash
的示例表明,您应该在可以的情况下从代码中删除循环,并利用管道替换它们。
在 PowerShell 中管理循环以提高速度将极大地提高性能。
数组与列表:PowerShell Speed++
从某些代码中收集结果以供以后使用是很常见的。如下所示的内容在互联网上传播的许多代码中经常使用。它运行我们在前面部分中使用的相同代码来输出当前数字和先前数字的乘积。在这种情况下,代码还将输出添加到$Array
。
$Array = @()
foreach ($Num in 1..10000) {
if ($Last) { $Array += $Last * $Num }
$Last = $Num
}
在此示例中,输出将保存到 $Array
中以供稍后使用或输出所有结果。
您应该使用 ArrayList 对象,而不是使用数组。使用的语法略有不同。首先,您需要使用 New-Object System.Collections.ArrayList
专门定义 ArrayList。您还需要使用 .Add()
方法,而不是像使用数组那样使用 +=
方法。以下是使用 ArrayList 而不是普通数组的更新代码块:
$ArrayList = New-Object System.Collections.ArrayList
foreach ($Num in 1..10000) {
if ($Last) { $ArrayList.Add($Last * $Num) }
$Last = $Num
}
以下是上述代码的结果。
标准数组无法扩展其中对象的数量。通过使用+=
,PowerShell 创建一个更大的新数组,并将旧数据和新数据复制到其中。只需执行几次此操作是添加到数组的快速方法,但在这种情况下,如果发生数千次,则会极大地影响性能。
随着您使用更大量的数据,这种性能差异会继续扩大。对于 100,000 个项目而不是 10,000 个项目,执行时间差异几乎为 5 分钟与半秒。不过,这种性能差异也存在相反的情况,如果您只处理少数项目,则差异很小。
在上面的两个示例中,您将命令的输出保存到变量中。使用变量来保存输出很常见,但在大多数情况下不是必需的。通过跳过将输出保存到变量,您可以看到相对于保存到 ArrayList 的另一个小好处。
通过跳过将输出保存到变量的步骤,输出将在计算时发送,而不是输出。
请注意如何创建列表和数组。如果这样做,您将大大提高 PowerShell 脚本的速度。
向左过滤
PowerShell 中最常见的命令之一是 Where-Object
,它用于过滤另一个命令的输出。虽然它非常强大,但只应在需要的地方使用它。确保尽可能“向左过滤”,以提高 PowerShell 脚本的速度。
虽然上面列出的其他选项需要权衡,您会因速度而失去一些便利,但通常建议使用左侧过滤来提高性能。无论您在 PowerShell 中做什么,您都应该尽快过滤掉大量数据。
例如,下面的代码块用于获取文件夹中的项目,然后过滤到以数字 1 开头的项目。
Get-ChildItem | Where-Object {$_.Name -like '1*'}
上面的代码只用了 422 毫秒就完成了,但它仍然可以做得更好。您可以使用以下命令在命令内进行过滤,而不是在命令运行后进行过滤:
Get-ChildItem -Filter 1*
您将收到相同的输出,但它将减少通过管道处理的数据量,因此它会在 30 毫秒内完成。这种巨大的差异是由于过滤器的执行方式造成的。在第一个示例中,每个目录文件都被传递给 Where-Object
命令以确定是否应该继续。在第二个示例中,Get-ChildItem
在沿管道发送的任何结果之前过滤结果。
从 PowerShell 3 开始,您可以在没有脚本块的情况下使用 Where-Object
。根据您使用的脚本块,它可能会稍微提高执行速度。在下面的代码中,平均只节省了 10ms。回到最初的示例,非脚本块格式如下所示:
Get-ChildItem | Where-Object Name -like '1*'
使用非脚本块语法获得的微小收益可能不值得失去与 PowerShell 2 的向后兼容性,因为有多少系统仍在运行它。不过,在 PowerShell 4 中,还有另一个选项,即使用 .Where()
方法。这只能用于集合,因此语法与其他选项有很大不同。下面是使用 .Where()
方法的同一示例:
(Get-ChildItem).Where({$_.Name -like '1*'})
此选项比前面提到的其他选项完成得快得多。这种性能差异表明,如果您使用的 cmdlet 不支持筛选器参数,并且您不需要支持旧版本的 PowerShell,则使用 .Where()
方法可能是最佳选择速度的最佳选择。
话虽如此,.Where()
方法可能有点难以阅读,因此您可以选择更标准的 Where-Object {}
格式以获得更好的可读性,具体取决于它对您的情况有多大影响。
错误先检查
无论您正在访问的系统是否可用或现在是否可用,您可能都需要执行某些操作。如果您提前检查错误,您将提高 PowerShell 脚本的速度,仅仅是因为效率的提高。
例如,如果文件存在,您希望将其删除;如果文件不存在,则不执行任何操作。您可以使用类似下面的代码。它将循环遍历当前目录中标记为 1 到 10000 的所有文件,并删除它们(如果存在)。
foreach ($Item in 1..10000) {Remove-Item $Item}
上述代码的缺点是,如果文件不存在,您将收到错误。您可能会想通过使用 -ErrorAction SilentlyContinue
来消除此错误,这样就不再抛出该错误,如下所示:
foreach ($Item in 1..10000) {Remove-Item $Item -ErrorAction SilentlyContinue}
使用 -ErrorAction
参数来静默错误会遇到很多问题,例如,如果存在除文件不存在之外的问题,您将永远不会知道,而无需进行额外的故障排除。除此之外,虽然您没有看到错误,但它仍然在后台抛出,这会造成一些性能影响。运行上面的代码会产生以下输出。
您可以先检查文件是否存在,然后仅在存在时删除它,而不是盲目地尝试删除它存在或不存在的文件:
foreach ($Item in 1..10000) {
if (Test-Path $Item) { Remove-Item $Item }
}
起初,您可能认为检查文件是否存在比尝试删除它需要更长的时间。正如您在这里所看到的,它几乎用了一半的时间就完成了,并且您还可以获得额外的好处,即能够使用正确的错误检测和处理可能发生的其他错误。
使用 if
语句先检查文件是否存在并不总能提高性能。如果您的代码每百万次尝试中仅尝试删除一次不存在的文件,那么不每次都进行检查会更快。尽管如此,这确实允许您稍后轻松添加错误处理。
总结
通过我们介绍的所有 PowerShell 速度调整,您可以改进代码以更有效地运行它。在某些情况下,您可能不会注意到由于使用小数据集而导致的运行时差异。尽管如此,如果您将代码提供给其他人,他们可能会从更高效的代码中获得显着的改进。
由于无法确定您的代码将来将如何使用,因此提高您的代码效率永远不会有什么坏处。因此,虽然您可能无法看到更改代码以提高性能的差异,但其他人可能会欣赏将来的工作。
其中一些建议确实有一些缺点,例如兼容性较低或可读性较差,但会产生更快的代码。因此,某些代码只有在需要更好的性能时才需要优化,但这对于大多数优化技术来说都是一样的。
补充阅读
要更深入地了解 Array 和 ArrayList 之间的差异,您可以查看这篇文章。如需多线程处理 PowerShell 代码的帮助,您可以查看此处。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag