0

Microsoft technetは、整数除算を提案[Math]::Floor([int]$a / [int]$b)しています。[int][Math]::Floor($a / $b)キャスト操作が1つ少ないため、読みやすく、パフォーマンスも向上すると思います。私は両方の方法が同等であることを証明しました。しかし、一貫した結果を得ることができません。私の方法論では、両方の方法論を10,000回繰り返し、Measure-Commandコマンドレットを使用して結果を測定します。ただし、あるテストが別のテストよりも繰り返しパフォーマンスが優れているテストを構成することはできません。私のコードは以下の通りです:

Write-Host
$loopLength = 10000

$runtime = Measure-Command {
    1..$loopLength | ForEach-Object {
        Foreach ($divisor in 2,3,5,7) {
            [Math]::Floor([int]$_ / [int]$divisor) > $null
        }
    }
}

"Double Cast: $($runtime.TotalMilliSeconds)"

$runtime = Measure-Command {
    1..$loopLength | ForEach-Object {
        Foreach ($divisor in 2,3,5,7) {
            [int][Math]::Floor($_ / $divisor) > $null           
        }
    }
}
"Single Cast: $($runtime.TotalMilliSeconds)"

ある方法が別の方法よりも優れていることを証明する一貫した結果が得られるように、コードを変更するにはどうすればよいですか。

4

3 に答える 3

1

私にとっては、このパフォーマンスの最適化はそれほど重要ではありません。PowerShell 自体はコンパイル済み言語よりもはるかに遅いため、パフォーマンスが本当に必要な場合は、コンパイル済み言語を使用するか、コードを .xml でコンパイルしますAdd-Type

それに加えて、パフォーマンスをテストする場合、結果を変える可能性のある最小限の他のコードが必要です。Foreach-Objectそれ自体が複雑さを追加します。foreachそのため、代わりにステートメントを使用することをお勧めします。

驚いたことに、私のマシンの結果は時々反対です..

[76]: $loopLength = 100000
[77]:
[77]: $runtime = Measure-Command {
>>     foreach($i in 1..$loopLength) {
>>         Foreach ($divisor in 2,3,5,7) {
>>             [Math]::Floor([int]$i / [int]$divisor) > $null
>>         }
>>     }
>> }
>>
[78]: "Double Cast: $($runtime.TotalMilliSeconds)"
Double Cast: 16294.3328
[79]:
[79]: $runtime = Measure-Command {
>>     foreach($i in 1..$loopLength) {
>>         Foreach ($divisor in 2,3,5,7) {
>>             [int][Math]::Floor($i / $divisor) > $null
>>         }
>>     }
>> }
>> "Single Cast: $($runtime.TotalMilliSeconds)"
>>
Single Cast: 15924.3836
于 2012-01-16T07:38:09.137 に答える
0

TechNet の例はちょっとばかげています。なぜなら、数値は既に 型になっているからSystem.Int32です。次の例を見てください。

PS C:\Users\andy> [math]::floor( 100 / 26 ).GetType().Fullname
System.Double
PS C:\Users\andy> (100).GetType().FullName
System.Int32
PS C:\Users\andy> [int].FullName
System.Int32

[int]したがって、Floor メソッドのパラメーターの前に配置する必要はまったくありません。これらは既に type になっているためSystem.Int32です。

System.Doubleまた、戻り値が保持できる値よりも大きくなる可能性があるため、戻り値をInt32とにかくにキャストしたくないでしょうInt32。例えば:

PS C:\Users\andy> [int][math]::floor( ([int]::MaxValue + 1) / 1 )
Cannot convert value "2147483648" to type "System.Int32". Error: "Value was either too large or too small for an Int32."

パフォーマンスに関しては、速度の違いはごくわずかです。PowerShell エンジンは、必要に応じて舞台裏で多くの型の適応と強制を実行します...このように設計されているため、システム管理者は int、double、小数などについてあまり心配する必要がありません...数は数ですよね?;-) 例えば:

[Math]::Floor("123")
# This outputs 123 as System.Double.

これは C# でもコンパイルできません。PowerShell ランタイムは、Floor メソッド シグネチャを満たすために必要なキャストを実行します。

もう一つの例:

"2" / "1"
# This outputs 2 as System.Int32.

文字列を除算することはできませんが、PowerShell エンジンはバックグラウンドで変換を行い、これを機能させます。

私のマシンのパフォーマンス結果は次のとおりです。

function Get-SingleCastTime {
    $runtime = Measure-Command {
        1..10000 | ForEach-Object {
            Foreach ($divisor in 2,3,5,7) {
                [int][Math]::Floor($_ / $divisor) > $null          
            }
        }
    }
    "Single Cast: $($runtime.TotalMilliSeconds)"
}

function Get-DoubleCastTime {
    $runtime = Measure-Command {
        1..10000 | ForEach-Object {
            Foreach ($divisor in 2,3,5,7) {
                [Math]::Floor([int]$_ / [int]$divisor) > $null
            }
        }
    }

    "Double Cast: $($runtime.TotalMilliSeconds)"
}

Get-SingleCastTime
#Single Cast: 614.6537

Get-DoubleCastTime
#Double Cast: 545.2668

Get-DoubleCastTime
#Double Cast: 514.2103

Get-SingleCastTime
#Single Cast: 526.9188
于 2012-01-15T04:31:41.633 に答える