【问题标题】:Switch vs If-Else PerformanceSwitch 与 If-Else 性能对比
【发布时间】:2016-08-07 14:20:07
【问题描述】:

我正在重写的登录脚本中有以下If 块:

If ($distinguishedname -match 'Joe Bloggs') {
    Map-Drive 'X' "\\path\to\drive"
}
If ($distinguishedname -match 'Steve Bloggs') {
    Map-Drive 'X' "\\path\to\drive"
}
If ($distinguishedname -match 'Joe Jobs') {
    Map-Drive 'X' "\\path\to\drive"
}

这显然需要重写为If/Else 语句(因为每个用户只有一个名字!)但是,我更喜欢以下switch -Regex 方法的外观:

switch -Regex ($distinguishedname) {
    'Joe Bloggs' {Map-Drive 'X' "\\path\to\drive"; break}
    'Steve Bloggs' {Map-Drive 'X' "\\path\to\drive"; break}
    'Joe Jobs' {Map-Drive 'X' "\\path\to\drive"; break}
}

我的问题是 - 以这种方式使用开关是否会影响此功能的性能?它必须比上述(if/if/if)更好,因为不是每次都评估所有可能性,但switch 会比ifelse/ifelse/else 快吗?

【问题讨论】:

  • 您可能希望使用组而不是逐个测试用户,但这不适用于您的情况
  • @sodawillow 感谢您的评论 - 我正在脚本中的其他地方测试组,但这里执行的设置对于这些用户来说是独一无二的,所以这似乎是我的最佳方式

标签: performance powershell if-statement switch-statement


【解决方案1】:

我编写了这个测试来检查我是否可以找出使用Measure-Command 的方式更好:

function switchtest {
    param($name)

    switch -Regex ($name) {
        $optionsarray[0] {
            Write-host $name
            break
        }
        $optionsarray[1] {
            Write-host $name
            break
        }
        $optionsarray[2] {
            Write-host $name
            break
        }
        $optionsarray[3] {
            Write-host $name
            break
        }
        $optionsarray[4] {
            Write-host $name
            break
        }
        default { }
    }
}
function iftest {
    param($name)

    If ($name -match $optionsarray[0]) {Write-host $name}
    ElseIf ($name -match $optionsarray[1]) {Write-host $name}
    ElseIf($name -match $optionsarray[2]) {Write-host $name}
    ElseIf($name -match $optionsarray[3]) {Write-host $name}
    ElseIf($name -match $optionsarray[4]) {Write-host $name}
}

$optionsarray = @('Joe Bloggs', 'Blog Joggs', 'Steve Bloggs', 'Joe Jobs', 'Steve Joggs')
for ($i=0; $i -lt 10000; $i++) {
    $iftime = 0
    $switchtime = 0

    $rand = Get-Random -Minimum 0 -Maximum 4
    $name = $optionsarray[$rand]

    $iftime = (Measure-Command {iftest $name}).Ticks
    $switchtime = (Measure-Command {switchtest $name}).Ticks

    Add-Content -Path C:\path\to\outfile\timetest.txt -Value "$switchtime`t$iftime"
}

结果

平均而言,这是每个函数在 10,000 次测试中的表现:

开关 - 11592.8566

IfElse - 15740.3281

结果不是最一致的(有时switch 更快,有时ifelse 更快)但由于switch 整体更快(平均而言)我将使用它而不是ifelse

如果对此决定和我的测试有任何反馈,我们将不胜感激。

【讨论】:

    【解决方案2】:

    通常,switch 语句通过在汇编代码中构建一个跳转表并使用它来确定适当的路由而不是使用 if/else 之类的比较器来工作。这就是 switch 语句更快的原因。我相信对于字符串,编译器会生成字符串的哈希码并使用它来实现跳转表,以便 switch 语句仍然更快。所以 switch 语句应该比你上面写的 if/if/if 更快,但它可能不是因为 switch 语句通常依赖于均匀间隔的选项(例如 1 2 3 或 5 10 15).

    话虽如此,为什么不使用 if/else-if/else-if 而不是 if/if/if?这肯定会更快,因为并非每次都评估每个选项。

    【讨论】:

    • 您确定这同样适用于像 PowerShell 这样的动态/解释型语言吗?您如何为支持正则表达式模式匹配的开关实现基于散列的跳转表?
    • @Ryan 感谢您的回答。根据一些测试,我决定选择switch(请参阅我自己的答案)。您认为这些测试是确定哪个语句更快的有效方法吗?
    猜你喜欢
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多