Dan*_*eny 2 powershell performance powershell-3.0
我在 PowerShell 中编写了一些屏幕抓取代码,并惊讶于解析几个 HTML 表需要大约 30 秒。我把它拆开,试图弄清楚所有的时间都花在哪里了,它似乎在getElementsByTagName通话中。
我在下面包含了一个脚本,在我的家庭桌面、我的工作桌面和我的家庭平板上,每次迭代大约需要 1-2 秒(完整的结果粘贴在下面)。但是,PowerShell 社区中的其他人报告的时间要短得多(每次迭代只有几毫秒)。
我正在努力寻找缩小问题范围的任何方法,并且似乎没有 OS/PS/.NET/IE 版本的模式。
我目前运行的桌面是全新的 Windows 8 安装,仅安装了 PS3 和 .NET 4.5(以及所有 Windows 更新补丁)。没有 Visual Studio。没有 PowerShell 配置文件。
$url = "http://www.icy-veins.com/restoration-shaman-wow-pve-healing-gear-loot-best-in-slot"
$response = (iwr $url).ParsedHtml
# Loop through the h2 tags
$response.body.getElementsByTagName("h2") | foreach {
# Get the table that comes after the heading
$slotTable = $_.nextSibling
# Grab the rows from the table, skipping the first row (column headers)
measure-command { $rows = $slotTable.getElementsByTagName("tr") | select -Skip 1 } | select TotalMilliseconds
}
Run Code Online (Sandbox Code Playgroud)
我的桌面上的结果(工作 PC 和 slate 给出的结果几乎相同):
TotalMilliseconds
-----------------
1575.7633
2371.5566
1073.7552
2307.8844
1779.5518
1063.9977
1588.5112
1372.4927
1248.7245
1718.3555
3283.843
2931.1616
2557.8595
1230.5093
995.2934
Run Code Online (Sandbox Code Playgroud)
但是,Google+ PowerShell 社区中的一些人报告了这样的结果:
TotalMilliseconds
-----------------
76.9098
112.6745
56.6522
140.5845
84.9599
48.6669
79.9283
73.4511
94.0683
81.4443
147.809
139.2805
111.4078
56.3881
41.3386
Run Code Online (Sandbox Code Playgroud)
我试过 PowerShell ISE 和标准控制台,没有区别。对于正在完成的工作,这些时间似乎有点过分,从Google+ 社区中的帖子来看,它可以更快!
您是否尝试禁用进度?
$ProgressPreference = "SilentlyContinue"
Run Code Online (Sandbox Code Playgroud)
就我而言,这解决了Invoke-WebRequest.
我在 64 位模式下运行脚本时同样缓慢,但在 32 位模式下运行时,一切都非常快!
\n\nLee Holmes 能够重现这个问题,这是他的文章
\n\n“问题在于,他\xe2\x80\x99 将 COM 对象通过管道传输到另一个 cmdlet \xe2\x80\x93(在本例中为 Select-Object)。当发生这种情况时,我们会尝试通过属性名称绑定参数。枚举 a 的属性名称COM 对象非常慢\xe2\x80\x93,因此我们\xe2\x80\x99 将 86% 的时间花费在两个非常基本的 CLR API 调用上:
\n\n(\xe2\x80\xa6)\n// 从 COM 类型获取函数描述\ntypeinfo.GetFuncDesc(index, out pFuncDesc);\n(\xe2\x80\xa6)\n// 从 COM 类型获取函数名称COM 函数描述\ntypeinfo.GetDocumentation(funcdesc.memid, out strName, out strDoc, out id, out strHelp);\n(\xe2\x80\xa6)
\n\n我们也许可以通过缓存来做一些聪明的事情。
\n\n解决方法是不通过管道输入 Select-Object,而是使用语言功能:
\n\n# Grab the rows from the table, skipping the first row (column headers)\n$allRows = @($slotTable.getElementsByTagName("tr"))\n$rows = $allRows[1..$allRows.Count]\nRun Code Online (Sandbox Code Playgroud)\n\n”
\n