สมมติว่าคุณมี method หรือ cmdlet ที่คืนค่าบางอย่าง แต่คุณไม่ต้องการใช้และไม่ต้องการส่งออก ฉันพบสองวิธีนี้:
Add-Item > $null
[void]Add-Item
Add-Item | Out-Null
คุณใช้อะไร? แนวทางใดที่ดีกว่า / สะอาดกว่า ทำไม?
สมมติว่าคุณมี method หรือ cmdlet ที่คืนค่าบางอย่าง แต่คุณไม่ต้องการใช้และไม่ต้องการส่งออก ฉันพบสองวิธีนี้:
Add-Item > $null
[void]Add-Item
Add-Item | Out-Null
คุณใช้อะไร? แนวทางใดที่ดีกว่า / สะอาดกว่า ทำไม?
คำตอบ:
ฉันเพิ่งทดสอบสี่ตัวเลือกที่ฉันรู้
Measure-Command {$(1..1000) | Out-Null}
TotalMilliseconds : 76.211
Measure-Command {[Void]$(1..1000)}
TotalMilliseconds : 0.217
Measure-Command {$(1..1000) > $null}
TotalMilliseconds : 0.2478
Measure-Command {$null = $(1..1000)}
TotalMilliseconds : 0.2122
## Control, times vary from 0.21 to 0.24
Measure-Command {$(1..1000)}
TotalMilliseconds : 0.2141
ดังนั้นฉันขอแนะนำให้คุณใช้อะไรก็ได้ แต่Out-Null
เนื่องจากค่าใช้จ่ายสูงเกินไป สิ่งที่สำคัญต่อไปสำหรับฉันคือความสามารถในการอ่าน ฉันชอบเปลี่ยนเส้นทาง$null
และตั้งค่าเท่ากับ$null
ตัวเอง ฉันชอบแคสต์[Void]
มากกว่า แต่อาจไม่เป็นที่เข้าใจเมื่อมองไปที่โค้ดหรือสำหรับผู้ใช้ใหม่
ฉันเดาว่าฉันชอบเปลี่ยนเส้นทางเอาต์พุตไปที่$null
ไฟล์.
Do-Something > $null
แก้ไข
หลังจากความคิดเห็นของ stej อีกครั้งฉันตัดสินใจที่จะทำการทดสอบเพิ่มเติมกับไปป์ไลน์เพื่อแยกค่าใช้จ่ายในการทิ้งขยะที่ดีขึ้น
ต่อไปนี้คือการทดสอบบางส่วนด้วยท่อออบเจ็กต์ 1,000 รายการ
## Control Pipeline
Measure-Command {$(1..1000) | ?{$_ -is [int]}}
TotalMilliseconds : 119.3823
## Out-Null
Measure-Command {$(1..1000) | ?{$_ -is [int]} | Out-Null}
TotalMilliseconds : 190.2193
## Redirect to $null
Measure-Command {$(1..1000) | ?{$_ -is [int]} > $null}
TotalMilliseconds : 119.7923
ในกรณีนี้Out-Null
มีค่าใช้จ่ายประมาณ 60% และ> $null
มีค่าโสหุ้ย 0.3%
ภาคผนวก 2017-10-16:เดิมทีฉันมองข้ามตัวเลือกอื่นด้วยOut-Null
การใช้-inputObject
พารามิเตอร์ การใช้สิ่งนี้ค่าใช้จ่ายดูเหมือนจะหายไป แต่ไวยากรณ์แตกต่างกัน:
Out-Null -inputObject ($(1..1000) | ?{$_ -is [int]})
และตอนนี้สำหรับการทดสอบบางอย่างด้วยท่อออบเจ็กต์ 100 รายการ
## Control Pipeline
Measure-Command {$(1..100) | ?{$_ -is [int]}}
TotalMilliseconds : 12.3566
## Out-Null
Measure-Command {$(1..100) | ?{$_ -is [int]} | Out-Null}
TotalMilliseconds : 19.7357
## Redirect to $null
Measure-Command {$(1..1000) | ?{$_ -is [int]} > $null}
TotalMilliseconds : 12.8527
ที่นี่Out-Null
มีค่าใช้จ่ายประมาณ 60% อีกครั้ง ในขณะที่> $null
มีค่าใช้จ่ายประมาณ 4% ตัวเลขที่นี่แตกต่างกันเล็กน้อยจากการทดสอบไปสู่การทดสอบ (ฉันวิ่งแต่ละครั้งประมาณ 5 ครั้งและเลือกพื้นกลาง) Out-Null
แต่ผมคิดว่ามันแสดงให้เห็นเหตุผลที่ชัดเจนที่จะไม่ใช้
Out-Null
อาจเป็นค่าใช้จ่าย แต่ .. ถ้าวางวัตถุชิ้นหนึ่งเป็นOut-Null
0.076 มิลลิวินาที imho ก็ยังใช้ได้ดีสำหรับภาษาสคริปต์ :)
ฉันรู้ว่านี่เป็นกระทู้เก่า แต่สำหรับผู้ที่รับคำตอบที่ได้รับการยอมรับของ @ JasonMArcher ข้างต้นในความเป็นจริงฉันแปลกใจที่พวกเราหลายคนไม่ได้รับการแก้ไขมานานหลายปีแล้วว่าจริง ๆ แล้ว PIPELINE เพิ่มความล่าช้าและไม่มีอะไรเกี่ยวข้องกับว่า มันเป็น Out-Null หรือไม่ ในความเป็นจริงถ้าคุณเรียกใช้การทดสอบด้านล่างคุณจะเห็นได้อย่างรวดเร็วว่าการร่าย "เร็วกว่า" เป็น [โมฆะ] และ $ void = เป็นเวลาหลายปีที่เราคิดว่ามันเร็วขึ้นนั้นเป็นเพียงแค่สโลว์และในความเป็นจริงช้ามากเมื่อ คุณเพิ่มการไปป์ไลน์ใด ๆ ก็ตาม กล่าวอีกนัยหนึ่งคือทันทีที่คุณไปยังสิ่งใดก็ตามกฎทั้งหมดของการไม่ใช้ค่าว่างเปล่าจะลงในถังขยะ
หลักฐานการทดสอบ 3 ครั้งล่าสุดในรายการด้านล่าง Out-null ที่น่าสยดสยองคือ 32339.3792 มิลลิวินาที แต่เดี๋ยวก่อน - แคสต์ไปยัง [โมฆะ] เร็วแค่ไหน? 34121.9251 มิลลิวินาที?!? WTF? นี่คือ # REAL ในระบบของฉันการแคสต์เป็น VOID นั้นช้าลงจริงๆ แล้ว = $ null ล่ะ? 34217.685ms ..... ยังคงเป็น friggin SLOWER! ดังที่การทดสอบอย่างง่ายสามครั้งล่าสุดแสดงให้เห็นว่า Out-Null นั้นเร็วกว่าในหลาย ๆ กรณีเมื่อมีการใช้งานไปป์ไลน์อยู่แล้ว
แล้วทำไมถึงเป็นเช่นนี้? เรียบง่าย มันเป็นภาพหลอน 100% เสมอที่การส่งไปยัง Out-Null ช้าลง อย่างไรก็ตามการ PIPING ไปยังสิ่งใด ๆ นั้นช้ากว่าและเราไม่รู้ด้วยเหตุผลพื้นฐานหรือไม่? เราอาจไม่รู้ว่าจะช้าลงแค่ไหน แต่การทดสอบเหล่านี้จะบอกเล่าเรื่องราวเกี่ยวกับค่าใช้จ่ายในการใช้ไปป์ไลน์หากคุณสามารถหลีกเลี่ยงได้ และเราไม่ได้ผิด 100% จริง ๆ เพราะมีสถานการณ์จริงจำนวนน้อยมากที่สิ่งที่ไม่เป็นโมฆะเป็นสิ่งชั่วร้าย เมื่อไหร่? เมื่อเพิ่ม Out-Null เป็นการเพิ่มกิจกรรมไปป์ไลน์เท่านั้น กล่าวอีกนัยหนึ่ง .... เหตุผลคำสั่งง่ายๆเช่น $ (1..1000) | Out-Null ตามที่แสดงด้านบนแสดงให้เห็นว่าเป็นจริง
หากคุณเพิ่มไปป์เพิ่มเติมใน Out-String ในทุกการทดสอบข้างต้น #s จะเปลี่ยนอย่างรุนแรง (หรือเพียงแค่วางรายการด้านล่าง) และอย่างที่คุณเห็นด้วยตัวคุณเอง Out-Null จะเร็วขึ้นในหลาย ๆ กรณี:
$GetProcess = Get-Process
# Batch 1 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Out-Null
}
}).TotalMilliseconds
# Batch 1 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess)
}
}).TotalMilliseconds
# Batch 1 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess
}
}).TotalMilliseconds
# Batch 2 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Select-Object -Property ProcessName | Out-Null
}
}).TotalMilliseconds
# Batch 2 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Select-Object -Property ProcessName )
}
}).TotalMilliseconds
# Batch 2 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Select-Object -Property ProcessName
}
}).TotalMilliseconds
# Batch 3 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name | Out-Null
}
}).TotalMilliseconds
# Batch 3 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name )
}
}).TotalMilliseconds
# Batch 3 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name
}
}).TotalMilliseconds
# Batch 4 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Out-String | Out-Null
}
}).TotalMilliseconds
# Batch 4 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Out-String )
}
}).TotalMilliseconds
# Batch 4 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Out-String
}
}).TotalMilliseconds
Out-Null
กับไปป์ไลน์เลยดังนั้นวิธีที่ดีที่สุดในการแสดงค่าใช้จ่ายของไปป์ไลน์คือการเรียกใช้Out-Null
และไม่มี ในระบบของฉันสำหรับการทำซ้ำ 10,000 ครั้งฉันจะได้รับ 0.576 วินาทีเป็นเวลาOut-Null -InputObject $GetProcess
เทียบกับ 5.656 วินาที (ช้ากว่าเกือบ 10 เท่า) สำหรับ$GetProcess | Out-Null
.
[void]
และ$null
ยังทำได้ดีกว่า| Out-Null
. ฉันเข้าใจว่านี่เป็นเพราะไปป์ไลน์และเดลต้าหดตัวตามแบทช์ในภายหลัง แต่บนเครื่องของฉันOut-Null
ไม่ทำงานเร็วกว่าในแบทช์ใด ๆ
[void]
และ$null
จะทำงานได้ดีกว่า| Out-Null
- เนื่องจากไฟล์|
. ลองOut-Null -InputObject (expression)
เปรียบเทียบ
นอกจากนี้ยังมีOut-Null
cmdlet Add-Item | Out-Null
ซึ่งคุณสามารถใช้ในท่อยกตัวอย่างเช่น
NAME
Out-Null
SYNOPSIS
Deletes output instead of sending it to the console.
SYNTAX
Out-Null [-inputObject <psobject>] [<CommonParameters>]
DETAILED DESCRIPTION
The Out-Null cmdlet sends output to NULL, in effect, deleting it.
RELATED LINKS
Out-Printer
Out-Host
Out-File
Out-String
Out-Default
REMARKS
For more information, type: "get-help Out-Null -detailed".
For technical information, type: "get-help Out-Null -full".
[void]
แม้ว่าโซลูชัน Out-Null จะดูเป็น "powershellish" มากกว่าก็ตาม
[void]
ดูชัดเจนมาก (ไม่ใช่ powershellish อย่างที่บอก) คุณจะเห็นที่จุดเริ่มต้นของบรรทัดว่าไม่มีผลลัพธ์ในบรรทัดนี้ นี่เป็นข้อดีอีกอย่างและถ้าคุณทำ Out-Null ในวงใหญ่ประสิทธิภาพอาจเป็นปัญหาได้)
ฉันจะพิจารณาใช้สิ่งต่างๆเช่น:
function GetList
{
. {
$a = new-object Collections.ArrayList
$a.Add(5)
$a.Add('next 5')
} | Out-Null
$a
}
$x = GetList
เอาต์พุตจาก$a.Add
จะไม่ถูกส่งกลับ - ซึ่งถือไว้สำหรับ$a.Add
การเรียกเมธอดทั้งหมด มิฉะนั้นคุณจะต้องใส่ไว้ข้าง[void]
หน้าก่อนการโทรทุกครั้ง
ในกรณีง่ายๆฉันจะไปด้วย[void]$a.Add
เพราะค่อนข้างชัดเจนว่าเอาต์พุตจะไม่ถูกใช้และถูกทิ้ง
ส่วนตัวผมใช้... | Out-Null
เพราะเป็นคนอื่น ๆ ได้เห็นรูปลักษณ์ที่เหมือนมากขึ้น "PowerShellish" วิธีการเมื่อเทียบกับและ ... > $null
กำลังใช้ประโยชน์จากตัวแปรอัตโนมัติที่เฉพาะเจาะจงและสามารถมองข้ามได้ง่ายในขณะที่วิธีการอื่นทำให้เห็นได้ชัดด้วยไวยากรณ์เพิ่มเติมที่คุณตั้งใจจะละทิ้งผลลัพธ์ของนิพจน์ เพราะและในตอนท้ายของการแสดงออกฉันคิดว่าพวกเขาสื่อสารได้อย่างมีประสิทธิภาพ "นำทุกสิ่งที่เราทำมาจนถึงจุดนี้และทิ้งมันไป" และคุณสามารถแสดงความคิดเห็นได้ง่ายขึ้นสำหรับวัตถุประสงค์ในการดีบัก (เช่น) เมื่อเทียบกับการวางหรือก่อนนิพจน์เพื่อกำหนดสิ่งที่เกิดขึ้นหลังจากดำเนินการ[void] ...
$null = ...
... | Out-Null
... > $null
... # | Out-Null
$null =
[void]
ลองดูเกณฑ์มาตรฐานที่แตกต่างกัน: ไม่ใช่ระยะเวลาที่ใช้ในการดำเนินการแต่ละตัวเลือก แต่เป็นระยะเวลาที่ใช้ในการพิจารณาว่าแต่ละตัวเลือกทำอะไร เมื่อทำงานในสภาพแวดล้อมร่วมกับเพื่อนร่วมงานที่ไม่มีประสบการณ์กับ PowerShell หรือแม้แต่การเขียนสคริปต์เลยฉันมักจะพยายามเขียนสคริปต์ของฉันในลักษณะที่มีคนมาหลายปีต่อมาซึ่งอาจไม่เข้าใจภาษาที่พวกเขากำลังดูอยู่ก็สามารถมี โอกาสในการต่อสู้เพื่อค้นหาว่ากำลังทำอะไรอยู่เนื่องจากพวกเขาอาจอยู่ในสถานะที่ต้องสนับสนุนหรือแทนที่ สิ่งนี้ไม่เคยเกิดขึ้นกับฉันเป็นเหตุผลที่จะใช้วิธีการเดียวกับวิธีอื่น ๆ จนถึงตอนนี้ แต่ลองนึกดูว่าคุณอยู่ในตำแหน่งนั้นและคุณใช้help
คำสั่งหรือเครื่องมือค้นหาที่คุณชื่นชอบเพื่อพยายามค้นหาว่าOut-Null
ทำ. คุณจะได้รับผลลัพธ์ที่เป็นประโยชน์ทันทีใช่ไหม? ตอนนี้พยายามที่จะทำเช่นเดียวกันกับและ[void]
$null =
ไม่ง่ายเลยใช่ไหม
จริงอยู่การระงับผลลัพธ์ของค่าเป็นรายละเอียดเล็กน้อยเมื่อเทียบกับการทำความเข้าใจตรรกะโดยรวมของสคริปต์และคุณทำได้แค่พยายาม "โง่" โค้ดของคุณให้มากก่อนที่คุณจะซื้อขายความสามารถในการเขียนโค้ดที่ดีสำหรับ a ความสามารถของมือใหม่ในการอ่าน ... โค้ดไม่ค่อยดี จุดของฉันคือเป็นไปได้ว่าบางคนที่มีความชำนาญใน PowerShell จะไม่ได้คุ้นเคยกับ[void]
, $null =
ฯลฯ และเพียงเพราะเหล่านั้นอาจดำเนินการได้เร็วขึ้นหรือใช้การกดแป้นพิมพ์น้อยประเภทไม่ได้หมายความว่าพวกเขากำลังวิธีที่ดีที่สุดที่จะทำ สิ่งที่คุณกำลังพยายามทำและเพียงเพราะภาษาให้ไวยากรณ์ที่เล่นโวหารไม่ได้หมายความว่าคุณควรใช้มันแทนสิ่งที่ชัดเจนและเป็นที่รู้จักกันดี *
*ฉันกำลังพลที่มีความชัดเจนและที่รู้จักกันดีซึ่งผมไม่ทราบว่าจะเป็นOut-Null
$true
ตัวเลือกใดที่คุณรู้สึกว่าชัดเจนที่สุดและสามารถเข้าถึงได้มากที่สุดสำหรับผู้อ่านและผู้แก้ไขโค้ดของคุณในอนาคต (รวมด้วยตัวคุณเอง) ไม่ว่าจะพิมพ์เวลาหรือเวลาในการดำเนินการก็ตามนั่นคือตัวเลือกที่ฉันแนะนำให้คุณใช้