Powershell 2和.NET:针对极大的哈希表进行优化?

Lar*_*old 3 powershell hashtable powershell-2.0

我正在涉足Powershell并且对.NET完全陌生.

我正在运行一个以空哈希表开头的PS脚本.哈希表将增长到至少15,000到20,000个条目.哈希表的键将是字符串形式的电子邮件地址,值将是布尔值.(我只需要跟踪我是否看过电子邮件地址.)

到目前为止,我一直在增加哈希表一个条目.我检查以确保键值对不存在(PS将在这种情况下出错),然后我添加该对.

这是我们谈论的代码部分:

...
    if ($ALL_AD_CONTACTS[$emailString] -ne $true) {
      $ALL_AD_CONTACTS += @{$emailString = $true}
    }
...
Run Code Online (Sandbox Code Playgroud)

我想知道从PowerShell或.NET的角度来看是否有任何可以做的事情可以优化这个哈希表的性能,如果你知道它会提前很大,比如15,000到20,000个条目或更多.

谢谢!

Emp*_*LII 5

Measure-Command使用一组20 000个随机单词进行了一些基本测试.

各个结果如下所示,但总的来说,通过首先使用单个条目分配新哈希表来添加到一个哈希表是非常低效的:)尽管选项2到5之间有一些小的效率提升,但一般来说它们都执行了差不多.

如果我选择,我可能会倾向于选项5的简单性(Add每个字符串只需一次调用),但我测试的所有替代方案似乎都可行.

$chars = [char[]]('a'[0]..'z'[0])
$words = 1..20KB | foreach {
  $count = Get-Random -Minimum 15 -Maximum 35
  -join (Get-Random $chars -Count $count)
}

# 1) Original, adding to hashtable with "+=".
#     TotalSeconds: ~800
Measure-Command {
  $h = @{}
  $words | foreach { if( $h[$_] -ne $true ) { $h += @{ $_ = $true } } }
}

# 2) Using sharding among sixteen hashtables.
#     TotalSeconds: ~3
Measure-Command {
  [hashtable[]]$hs = 1..16 | foreach { @{} }
  $words | foreach {
    $h = $hs[$_.GetHashCode() % 16]
    if( -not $h.ContainsKey( $_ ) ) { $h.Add( $_, $null ) }
  }
}

# 3) Using ContainsKey and Add on a single hashtable.
#     TotalSeconds: ~3
Measure-Command {
  $h = @{}
  $words | foreach { if( -not $h.ContainsKey( $_ ) ) { $h.Add( $_, $null ) } }
}

# 4) Using ContainsKey and Add on a hashtable constructed with capacity.
#     TotalSeconds: ~3
Measure-Command {
  $h = New-Object Collections.Hashtable( 21KB )
  $words | foreach { if( -not $h.ContainsKey( $_ ) ) { $h.Add( $_, $null ) } }
}

# 5) Using HashSet<string> and Add.
#     TotalSeconds: ~3
Measure-Command {
  $h = New-Object Collections.Generic.HashSet[string]
  $words | foreach { $null = $h.Add( $_ ) }
}
Run Code Online (Sandbox Code Playgroud)