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. Однако не может быть проведено испытание, когда один тест будет работать лучше, чем другой тест. Мой код ниже:Тестирование производительности двух методов разделения целых чисел 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] [Math] :: этаж ($ _/$ делителя)> $ null' из второго цикла. –

+0

Они кажутся настолько близкими по производительности, что фоновые процессы вашей системы делают разницу несущественной.вы можете минимизировать фоновый шум, останавливая службы, закрывая окна и т. д., вы даже можете загрузиться в безопасном режиме Windows. (см. msconfig.exe). Должен сказать, я не понимаю, почему кастинг результата операции заставит операцию работать быстрее. –

+0

@ AndyArismendiquite правильно и исправлено. Вы могли бы отредактировать его самостоятельно и оставили комментарий для редактирования. –

ответ

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] перед параметрами метода пола, так как они уже типа 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, 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

Будьте осторожны @ Andy Arismendi, когда вы написали ([int] :: MaxValue + 1), это больше не целое число, это двойная попытка вашей командной строки ([int] :: MaxValue + 1) .gettype(), почему технология образец написан с литой. И для меня с математической точки зрения результат целочисленного деления на n бит поместится в n бит. – JPBlanc

+0

@JPBlanc Этот пример должен был вывести значение, не помещенное в Int32, чтобы показать, почему это не очень хорошая идея: '[int] [math] :: Floor ($ aNumberBiggerThanInt32MaxValue)' из-за исключения , Лучше, чтобы среда выполнения PowerShell позаботилась об этом. –

1

Что касается меня, это оптимизация производительности не очень важно. Сама PowerShell намного медленнее, чем скомпилированные langugages, поэтому, если вам действительно нужна производительность, используйте скомпилированные языки или скомпилируйте свой код с помощью 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