2012-01-15 2 views
1

Microsoft technet suggests [Math]::Floor([int]$a/[int]$b) for integer division. 나는보다 적은 캐스팅 작업으로 인해 [int][Math]::Floor($a/$b)이 더 읽기 쉽고 성능이 뛰어나다 고 생각합니다. I have proven both methods equivalent. 그러나 일관된 결과를 얻을 수 없습니다. 내 방법론은 두 방법론을 모두 10,000 번 반복하고 Measure-Command cmdlet을 사용하여 결과를 측정하는 것입니다. 그러나 한 테스트가 다른 테스트보다 반복적으로 수행되는 테스트를 수행 할 수는 없습니다. 내 코드는 다음과 같습니다.성능 테스트 PowerShell 정수 나누기의 두 가지 방법

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)" 

한 가지 방법이 다른 것보다 낫다는 일관된 결과를 얻으려면 어떻게 코드를 수정해야합니까?

+0

있습니다 나는'[INT] [수학] :: 층 ($ _/$ 제수)> $ null' 누락 생각 두 번째 루프에서. –

+0

이들은 시스템의 백그라운드 프로세스가 차이를 무시할만큼 성능면에서 매우 비슷합니다.서비스를 중지하고 창을 닫으면 백그라운드 노이즈를 최소화 할 수 있습니다. Windows 안전 모드로 부팅 할 수도 있습니다. (msconfig.exe 참조). 작동의 결과를 캐스팅하면 왜 작동 자체가 더 빨라지는지 나는 모르겠다. –

+0

@AndyArismendiquite가 올바르게 수정되었습니다. 직접 편집하고 편집 주석을 남길 수 있습니다. –

답변

0

숫자가 이미 System.Int32이므로 TechNet의 예는 다소 바보입니다.

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 

을 그래서 그들은 이미 유형 System.Int32의 때문에 바닥 메서드 매개 변수 앞에 [int]을 넣어 완전히 불필요 :이 예에서 살펴 보자.

또한 반환 값이 Int32보다 클 수 있으므로 반환되는 System.DoubleInt32으로 캐스팅하지 않으실 것입니다. 예 :

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, decimals 등을 너무 걱정할 필요가 없도록 설계되었습니다. 숫자가 맞습니까? ;-) 예 :

[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 
+0

당신이 [int] :: MaxValue + 1을 썼을 때 @Andy Arismendi가 더 이상 정수가 아니므로 명령 줄 ([int] :: MaxValue + 1) .gettype()에서 두 번 시도해보십시오. 샘플은 캐스트로 작성됩니다. 그리고 수학적 관점에서 n 비트의 정수 나누기 결과가 n 비트에 들어 맞습니다. – JPBlanc

+0

@JPBlanc이 예제는 예외 때문에 Int32에 적합하지 않은 값을 출력하여 '[int] [math] :: Floor ($ aNumberBiggerThanInt32MaxValue)'를 수행하는 것이 좋지 않은 이유를 보여주었습니다. . PowerShell 런타임에서 처리하는 것이 좋습니다. –

1

,이 성능 최적화가 정말 중요하지 않습니다 :

여기에 내 컴퓨터의 성능 결과입니다. PowerShell 자체는 컴파일 된 언어보다 훨씬 느립니다. 따라서 실제로 성능이 필요한 경우 컴파일 된 언어를 사용하거나 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