Apa cara (pembersih) yang lebih baik untuk mengabaikan output di PowerShell? [Tutup]

134

Katakanlah Anda memiliki metode atau cmdlet yang mengembalikan sesuatu, tetapi Anda tidak ingin menggunakannya dan Anda tidak ingin menampilkannya. Saya menemukan dua cara ini:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

Apa yang kamu gunakan? Mana pendekatan yang lebih baik / bersih? Mengapa?

Hinek
sumber
1
seperti versi [void] ... belum untuk saya, tapi saya akan mencoba mengingatnya.
Massif

Jawaban:

181

Saya baru saja melakukan beberapa tes dari empat opsi yang saya ketahui.

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

Jadi saya menyarankan agar Anda menggunakan apa pun kecuali Out-Nullkarena overhead. Hal penting berikutnya, bagi saya, adalah keterbacaan. Saya agak suka mengalihkan ke $nulldan menetapkan sama dengan $nulldiri saya sendiri. Saya lebih suka casting[Void] , tapi itu mungkin tidak bisa dimengerti ketika melirik kode atau untuk pengguna baru.

Saya kira saya sedikit lebih suka mengarahkan ulang output ke $null.

Do-Something > $null

Edit

Setelah komentar stej lagi, saya memutuskan untuk melakukan beberapa tes lagi dengan saluran pipa untuk lebih mengisolasi overhead dari trashing output.

Berikut adalah beberapa tes dengan pipa objek 1000 sederhana.

## 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

Dalam hal ini, Out-Nullmemiliki sekitar 60% overhead dan > $nullsekitar 0,3% overhead.

Tambahan 2017-10-16: Saya awalnya mengabaikan opsi lain dengan Out-Null, penggunaan -inputObjectparameter. Menggunakan ini overhead tampaknya menghilang, namun sintaksnya berbeda:

Out-Null -inputObject ($(1..1000) | ?{$_ -is [int]})

Dan sekarang untuk beberapa tes dengan pipa objek 100 sederhana.

## 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

Di sini lagi Out-Nullmemiliki sekitar 60% overhead. Sementara > $nullmemiliki overhead sekitar 4%. Angka-angka di sini sedikit bervariasi dari tes ke tes (saya berlari masing-masing sekitar 5 kali dan mengambil jalan tengah). Tapi saya pikir itu menunjukkan alasan yang jelas untuk tidak menggunakan Out-Null.

JasonMArcher
sumber
1
saya biasanya menggunakan VOID untuk hal-hal yang merupakan bagian dari garis bahasa, dan keluar-nol jika sudah merupakan pipa panjang yang besar
klumsy
25
Out-Nullmungkin di atas kepala. Tapi .. jika pipa satu objek ke Out-Null0.076 milidetik, IMHO itu masih baik-baik saja untuk bahasa scripting :)
stej
1
Saya sedikit mengotak-atik ini, dan saya mendapatkan kinerja terbaik di atas [void] dan> $ null dengan menggunakan Out-Null -InputObject ($ (1..1000) |? {$ _ -Is [int]}).
tomohulk
1
Poin bagus, yang tampaknya tidak memiliki overhead yang terlihat.
JasonMArcher
5
Meskipun selalu baik untuk memiliki tolok ukur untuk membandingkan berbagai cara dalam mencapai sesuatu, jangan mengabaikan kesimpulan lain yang dapat ditarik di sini: kecuali Anda harus membuang nilai ratusan ribu kali perbedaan kinerja dapat diabaikan. Dan jika satu milidetik di sini atau di sana benar-benar penting bagi Anda, Anda mungkin seharusnya tidak menggunakan PowerShell. Tanpa membuat penilaian tentang bagaimana peringkat opsi dalam hal ini, itu tidak selalu buruk mengorbankan kecepatan untuk kualitas lain seperti keterbacaan dan mengekspresikan niat programmer.
BACON
22

Saya menyadari ini adalah utas lama, tetapi bagi mereka yang menerima jawaban yang diterima @ JasonMArcher di atas sebagai fakta, saya terkejut itu belum diperbaiki banyak dari kita yang tahu selama bertahun-tahun itu sebenarnya adalah PIPELINE yang menambahkan penundaan dan TIDAK ADA hubungannya dengan apakah itu Out-Null atau tidak. Faktanya, jika Anda menjalankan tes di bawah ini, Anda akan dengan cepat melihat bahwa casting "lebih cepat" yang sama ke [void] dan $ void = bahwa selama bertahun-tahun kita semua berpikir bahwa itu lebih cepat, sebenarnya HANYA SEPERTI LAMBAT dan pada kenyataannya SANGAT LAMBAT ketika Anda menambahkan pipelining APAPUN apa pun. Dengan kata lain, segera setelah Anda melakukan pipe ke apa pun, seluruh aturan untuk tidak menggunakan-null masuk ke tempat sampah.

Buktinya, 3 tes terakhir dalam daftar di bawah ini. Out-null yang mengerikan adalah 32339.3792 milidetik, tapi tunggu - seberapa cepatkah casting menjadi [batal]? 34121.9251 ms?!? WTF? Ini adalah # NYATA pada sistem saya, casting ke VOID sebenarnya lebih lambat. Bagaimana dengan = $ null? 34217.685ms ..... masih friggin SLOWER! Jadi, seperti yang ditunjukkan oleh tiga tes sederhana terakhir, Out-Null sebenarnya LEBIH CEPAT dalam banyak kasus ketika pipa sudah digunakan.

Jadi mengapa ini? Sederhana. 100% halusinasi membuat perpipaan ke Out-Null lebih lambat. Namun, PIPING TO ANYTHING lebih lambat, dan bukankah kita semacam sudah tahu itu melalui logika dasar? Kita mungkin saja tidak tahu BAGAIMANA JAUH lebih lambat, tetapi tes ini tentu saja menceritakan tentang biaya menggunakan pipa jika Anda bisa menghindarinya. Dan, kami tidak benar-benar 100% salah karena ada sejumlah skenario benar yang KECIL di mana nol adalah kejahatan. Kapan? Saat menambahkan Out-Null adalah menambahkan aktivitas pipa ONLY. Dengan kata lain .... alasan perintah sederhana seperti $ (1..1000) | Out-Null seperti yang ditunjukkan di atas menunjukkan true.

Jika Anda cukup menambahkan pipa tambahan ke Out-String untuk setiap tes di atas, #s ​​berubah secara radikal (atau cukup tempel yang di bawah) dan seperti yang Anda lihat sendiri, Out-Null sebenarnya menjadi LEBIH CEPAT dalam banyak kasus:

$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
Collin Chaffin
sumber
+1 untuk membuat poin penting ini. Bahkan, tidak ada yang memaksa siapa pun untuk menggunakan Out-Nullpipa sama sekali, jadi cara terbaik untuk menunjukkan overhead pipa adalah dengan memohon Out-Nulldengan dan tanpa itu. Di sistem saya, untuk 10.000 iterasi saya mendapatkan 0,576 detik untuk Out-Null -InputObject $GetProcessvs 5,656 detik (hampir 10x lebih lambat) untuk $GetProcess | Out-Null.
BACON
Hai Collin, terima kasih atas jawaban Anda. Saya menjalankan sampel Anda, tetapi dalam semua batch [void]dan $nullmasih melakukan yang lebih baik daripada | Out-Null. Saya mendapatkan bahwa ini adalah karena pipa dan delta menyusut dengan batch kemudian, tetapi pada mesin saya Out-Nulltidak berkinerja lebih cepat di salah satu batch.
Hinek
Tetapi tentu saja saya harus setuju dengan mereka, yang berpendapat, bahwa kinerja bukanlah segalanya dan keterbacaan harus menjadi faktor juga.
Hinek
@ Hinek Komentar Anda menunjukkan bahwa Anda melewatkan pokok pembicaraan Collin. Ya, [void]dan $nullakan tampil lebih baik daripada | Out-Null- karena itu |. Coba Out-Null -InputObject (expression)untuk perbandingan.
Jonathan Gilbert
19

Ada juga Out-Nullcmdlet, yang dapat Anda gunakan dalam pipa, misalnya Add-Item | Out-Null,.

Halaman manual untuk 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".
Ocaso Protal
sumber
Apa pendapat Anda tentang hasil tes tolok ukur kecil dalam jawaban Jason?
Hinek
Sangat menarik, terutama perbedaan yang sangat besar antara Out-Null dan metode lainnya. Saya pikir saya akan beralih ke [void]meskipun solusi Out-Null terlihat lebih "powershellish".
Ocaso Protal
Saya masih tidak yakin, apa cara yang saya sukai. Bahkan perbedaan besar ini tampaknya tidak terlalu signifikan karena stej sudah berkomentar.
Hinek
2
@ Hinek [void]terlihat sangat jelas (tho tidak powershellish seperti yang saya katakan), Anda akan melihat di awal baris bahwa tidak ada output di baris ini. Jadi ini adalah keuntungan lain, dan jika Anda melakukan Out-Null dalam lingkaran besar, kinerja bisa menjadi masalah;)
Ocaso Protal
11

Saya akan mempertimbangkan menggunakan sesuatu seperti:

function GetList
{
  . {
     $a = new-object Collections.ArrayList
     $a.Add(5)
     $a.Add('next 5')
  } | Out-Null
  $a
}
$x = GetList

Output dari $a.Addtidak dikembalikan - yang berlaku untuk semua $a.Addpanggilan metode. Kalau tidak, Anda perlu menambahkan [void]sebelum setiap panggilan.

Dalam kasus sederhana saya akan pergi [void]$a.Addkarena sudah cukup jelas bahwa output tidak akan digunakan dan dibuang.

stej
sumber
2

Secara pribadi, saya menggunakan ... | Out-Nullkarena, seperti yang telah dikomentari orang lain, sepertinya lebih banyak pendekatan "PowerShellish" dibandingkan dengan ... > $nulldan [void] .... $null = ...mengeksploitasi variabel otomatis tertentu dan dapat dengan mudah diabaikan, sedangkan metode lain membuatnya jelas dengan sintaks tambahan bahwa Anda bermaksud untuk membuang output dari ekspresi. Karena ... | Out-Nulldan ... > $nullmuncul di akhir kalimat, saya pikir mereka berkomunikasi secara efektif "ambil semua yang telah kami lakukan hingga saat ini dan buanglah", ditambah Anda dapat berkomentar lebih mudah untuk tujuan debugging (misalnya ... # | Out-Null), dibandingkan dengan menempatkan $null =atau [void] sebelum ekspresi untuk menentukan apa yang terjadi setelah menjalankannya.

Mari kita lihat tolok ukur yang berbeda: bukan jumlah waktu yang dibutuhkan untuk mengeksekusi setiap opsi, tetapi jumlah waktu yang dibutuhkan untuk mengetahui apa yang dilakukan setiap opsi . Setelah bekerja di lingkungan dengan kolega yang tidak berpengalaman dengan PowerShell atau bahkan menulis skrip sama sekali, saya cenderung mencoba menulis skrip saya sedemikian rupa sehingga seseorang yang datang bertahun-tahun kemudian yang mungkin bahkan tidak mengerti bahasa yang mereka lihat dapat memiliki berjuang peluang mencari tahu apa yang dilakukannya karena mereka mungkin harus mendukung atau menggantinya. Ini tidak pernah terpikir oleh saya sebagai alasan untuk menggunakan satu metode di atas yang lain sampai sekarang, tetapi bayangkan Anda berada di posisi itu dan Anda menggunakan helpperintah atau mesin pencari favorit Anda untuk mencoba mencari tahu apaOut-Nulltidak. Anda mendapatkan hasil yang bermanfaat segera, bukan? Sekarang coba lakukan hal yang sama dengan [void]dan $null =. Tidak mudah, bukan?

Memang, menekan output dari nilai adalah detail yang cukup kecil dibandingkan dengan memahami logika keseluruhan skrip, dan Anda hanya dapat mencoba "membodohi" kode Anda sebelum Anda memperdagangkan kemampuan Anda untuk menulis kode yang baik untuk kemampuan pemula untuk membaca ... kode yang tidak terlalu baik. Maksud saya adalah, ada kemungkinan bahwa beberapa yang fasih di PowerShell bahkan tidak terbiasa dengan [void],, $null =dll., Dan hanya karena mereka dapat mengeksekusi lebih cepat atau mengambil penekanan tombol yang lebih sedikit, tidak berarti mereka adalah cara terbaik untuk melakukan apa yang Anda coba lakukan, dan hanya karena sebuah bahasa memberi Anda sintaks yang aneh tidak berarti Anda harus menggunakannya alih-alih sesuatu yang lebih jelas dan lebih dikenal. *

* Saya kira itu Out-Nulljelas dan terkenal, yang saya tidak tahu $true. Opsi apa pun yang Anda rasa paling jelas dan paling mudah diakses oleh pembaca dan editor kode Anda yang akan datang (termasuk Anda sendiri), terlepas dari tipe waktu atau waktu yang dijalankan, itulah opsi yang saya sarankan Anda gunakan.

DAGING BABI ASAP
sumber