Bộ lọc chênh lệch hiệu năng PowerShell so với chức năng


11

Tôi hiện đang đọc cuốn sách Windows PowerShell 3.0 Từng bước để hiểu thêm về PowerShell.

Trên trang 201, tác giả chứng minh rằng bộ lọc nhanh hơn chức năng có cùng chức năng.

Kịch bản này mất 2,6 giây trên máy tính của anh ấy:

MeasureAddOneFilter.ps1
Filter AddOne
{ 
 "add one filter"
  $_ + 1
}

Measure-Command { 1..50000 | addOne }

và cái này 4,6 giây

MeasureAddOneFunction.ps1
Function AddOne
{  
  "Add One Function"
  While ($input.moveNext())
   {
     $input.current + 1
   }
}

Measure-Command { 1..50000 | addOne }

Nếu tôi chạy mã này thì ngược lại với kết quả của anh ta:

.\MeasureAddOneFilter.ps1
Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 226
Ticks             : 2266171
TotalDays         : 2,62288310185185E-06
TotalHours        : 6,29491944444444E-05
TotalMinutes      : 0,00377695166666667
TotalSeconds      : 0,2266171
TotalMilliseconds : 226,6171

.\MeasureAddOneFunction.ps1

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 93
Ticks             : 933649
TotalDays         : 1,08061226851852E-06
TotalHours        : 2,59346944444444E-05
TotalMinutes      : 0,00155608166666667
TotalSeconds      : 0,0933649
TotalMilliseconds : 93,3649

Ai đó có thể giải thích điều này với tôi?

Câu trả lời:


13

Trừ khi tác giả đưa ra nhiều bằng chứng hỗ trợ, có thể anh ta chỉ tràn đầy không khí nóng. Bạn đã chạy thử nghiệm và nhận được kết quả và chứng minh anh ta sai.

Chỉnh sửa: Từ blog của Jeffrey Snover:

Bộ lọc là một chức năng chỉ có một kịch bản lệnh

Điều đó thôi không đủ để thuyết phục tôi rằng bộ lọc sẽ có lợi thế về tốc độ so với chức năng, do cả hai đều có các khối quy trình giống hệt nhau.

Ngoài ra, loại thiết bị nào của năm 1950 mà anh chàng đó mất tới 4,6 giây để thêm một thiết bị vào một số?

PS C:\Users\Ryan> Measure-Command { Filter AddOne { $_ + 1 }; AddOne 1 }

TotalMilliseconds : 7.7266


PS C:\Users\Ryan> Measure-Command { Function AddOne { $_ + 1 }; AddOne 1 }    

TotalMilliseconds : 0.4108

4,6 giây là whack. Có lẽ tác giả đã sử dụng một số loại phiên bản CTP của Powershell trước khi các nhị phân được ngen'ed. : P

Cuối cùng, hãy thử bài kiểm tra của bạn trong phiên Powershell mới, nhưng theo thứ tự ngược lại. Hãy thử Chức năng trước và Bộ lọc thứ hai hoặc ngược lại:

PS C:\Users\Ryan> Measure-Command { Function AddOne { $_ + 1 }; AddOne 1 }    

TotalMilliseconds : 6.597    


PS C:\Users\Ryan> Measure-Command { Filter AddOne { $_ + 1 }; AddOne 1 }

TotalMilliseconds : 0.4055

Xem? Cái đầu tiên bạn chạy sẽ luôn chậm hơn. Nó chỉ là về phần bên trong của .NET đã tải nội dung vào bộ nhớ giúp thao tác thứ hai nhanh hơn, bất kể đó là chức năng hay bộ lọc.

Tôi sẽ thừa nhận mặc dù Chức năng dường như vẫn nhanh hơn Bộ lọc, bất kể nó chạy bao nhiêu lần.

Measure-Command { Function AddOne($Num) { Return $Num += 1 }; 1..50000 | AddOne $_ }

TotalMilliseconds : 13.9813

Measure-Command { Filter AddOne($Num) { Return $Num += 1 }; 1..50000 | AddOne $_ }

TotalMilliseconds : 69.5301

Vì vậy, tác giả đã sai ... và bây giờ tôi không cảm thấy tệ vì chưa bao giờ sử dụng Bộ lọc thay vì Chức năng trước đây.


4

Trên thực tế, sự khác biệt nhỏ hơn nhiều nếu bạn sử dụng cùng $ _ trong cả hai bài kiểm tra. Tôi đã không điều tra nguyên nhân, nhưng tôi cho rằng đó là vì tác giả không sử dụng cùng một phương pháp trong cả hai thử nghiệm. Ngoài ra, đầu ra giao diện điều khiển có thể can thiệp vào kết quả. Nếu bạn cắt những phần này, những con số rất giống nhau. Xem:

Function AddOneFunction
{  
    process {
        $_ + 1
    }
}

Filter AddOneFilter
{ 
    $_ + 1
}

write-host "First"
Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds
Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds
Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds
Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds
Measure-Command { 1..50000 | AddOneFilter } | select totalMilliseconds

write-host "Second"
Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds
Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds
Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds
Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds
Measure-Command { 1..50000 | AddOneFunction } | select totalMilliseconds

Kết quả sẽ rất gần, ngay cả khi bạn thay đổi thứ tự của các lệnh.

First

TotalMilliseconds
-----------------
        84.6742
        84.7646
        89.8603
        82.3399
        83.8195
Second
        86.8978
        87.4064
        89.304
        94.4334
        87.0135

Tài liệu cũng nói rằng Bộ lọc về cơ bản là các phím tắt đến các chức năng chỉ với khối quy trình. Các hàm, trừ khi được chỉ định với khối quy trình (hoặc một số kỹ thuật khác như sử dụng biến tự động như $ input), chạy một lần, không sử dụng đầu vào và không chuyển sang lệnh tiếp theo trong đường ống.

Thông tin thêm tại https://technet.microsoft.com/en-us/l Library / hh847829.aspxhttps://technet.microsoft.com/en-us/l Library / hh847781.aspx

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.