首页 > 解决方案 > 如何最好地加快 powershell 处理时间(比较对象)

问题描述

我有一个 powershell 脚本,用于Compare-Object对 MD5 校验和列表进行比较/比较……我怎样才能加快速度?它已经运行了几个小时!

$diffmd5 = 
(Compare-Object -ReferenceObject $localmd5 -DifferenceObject $remotefilehash |
 Where-Object { ($_.SideIndicator -eq '=>') } | 
Select-Object -ExpandProperty InputObject)

标签: powershell

解决方案


Compare-Object很方便,但确实很慢;完全避免管道对于最大化性能也很重要。

我建议使用一个实例,它支持在一组无序[1][System.Collections.Generic.HashSet[T]中进行高性能查找: [2]

# Two sample arrays
$localmd5 = 'Foo1', 'Bar1', 'Baz1'
$remotefilehash = 'foo1', 'bar1', 'bar2', 'baz1', 'more'

# Create a hash set from the local hashes.
# Make lookups case-*insensitive*.
# Note: Strongly typing the input array ([string[]]) is a must.
$localHashSet = [System.Collections.Generic.HashSet[string]]::new(
  [string[]] $localmd5,
  [System.StringComparer]::OrdinalIgnoreCase
)

# Loop over all remote hashes to find those not among the local hashes.
$remotefilehash.Where({ -not $localHashSet.Contains($_) })

以上产生 collection 'bar2', 'more'

请注意,如果区分大小写的查找就足够了,这是默认值(对于字符串元素),则简单的强制转换就足以构造散列集:

$localHashSet = [System.Collections.Generic.HashSet[string]] $localmd5

注意:您后来的反馈指出,这$remotefilehash是键值对的哈希表(类似)集合,而不是仅文件哈希字符串的集合,其中存储哈希字符串。在这种情况下:

  • 要查找不同的哈希字符串(注意.Keys获取键值数组的属性访问):

    $remotefilehash.Keys.Where({ -not $localHashSet.Contains($_) })
    
  • 要查找其键不在哈希集中的键值.GetEnumerator()(请注意枚举所有条目(键值对)的调用):

    $remotefilehash.GetEnumerator().Where({ -not $localHashSet.Contains($_.Key) })
    

或者,如果输入集合 (a) 具有相同的大小并且 (b) 具有相应的元素(即,应将一个集合中的元素 1 与另一个集合中的元素 1 进行比较,依此类推),请使用Compare-Objectwith -SyncWindow 0,如图所示在js2010 的有用答案.SideIndicator中,可以选择后续过滤;为了加快操作,-PassThru应该使用开关,它放弃在[pscustomobject]实例中包装不同的对象(.SideIndicator然后将该属性作为NoteProperty成员直接添加到不同的对象中)。


[1] 有一种用于维护排序的相关类型,System.Collections.Generic.SortedSet[T]但是 - 从 .NET 6 开始 -没有用于按输入顺序维护值的内置类型,尽管您可以通过派生来创建自己的类型[System.Collections.ObjectModel.KeyedCollection[TKey, TItem]]

[2] 请注意,哈希- 与哈希不同-没有与其条目关联的值。哈希集是“所有键”,如果您愿意的话 - 它只支持测试键 == 值的存在


推荐阅读