Mengapa membuat proses baru lebih mahal di Windows daripada Linux?

101

Saya pernah mendengar bahwa membuat proses baru di kotak Windows lebih mahal daripada di Linux. Apakah ini benar? Adakah yang bisa menjelaskan alasan teknis mengapa lebih mahal dan memberikan alasan historis untuk keputusan desain di balik alasan tersebut?

Hanya baca
sumber

Jawaban:

68

mweerden: NT telah dirancang untuk multi-pengguna sejak hari pertama, jadi ini sebenarnya bukan alasan. Namun, Anda benar tentang pembuatan proses yang memainkan peran yang kurang penting di NT daripada di Unix karena NT, berbeda dengan Unix, lebih menyukai multithreading daripada multiprocessing.

Rob, memang benar bahwa fork relatif murah saat COW digunakan, tapi faktanya, fork lebih banyak diikuti oleh seorang exec. Dan seorang eksekutif harus memuat semua gambar juga. Oleh karena itu, membahas kinerja garpu hanyalah sebagian dari kebenaran.

Saat membahas kecepatan pembuatan proses, mungkin ada baiknya untuk membedakan antara NT dan Windows / Win32. Sejauh NT (yaitu kernel itu sendiri) berjalan, saya tidak berpikir pembuatan proses (NtCreateProcess) dan pembuatan utas (NtCreateThread) secara signifikan lebih lambat seperti pada Unix rata-rata. Mungkin ada sedikit lebih banyak hal yang terjadi, tetapi saya tidak melihat alasan utama perbedaan kinerja di sini.

Jika Anda melihat Win32, bagaimanapun, Anda akan melihat bahwa itu menambahkan sedikit overhead untuk proses pembuatan. Pertama, CSRSS harus diberi tahu tentang pembuatan proses, yang melibatkan LPC. Ini membutuhkan setidaknya kernel32 untuk dimuat tambahan, dan itu harus melakukan sejumlah item pekerjaan pembukuan tambahan yang harus dilakukan sebelum proses tersebut dianggap sebagai proses Win32 lengkap. Dan jangan lupa tentang semua overhead tambahan yang dikenakan oleh penguraian manifes, memeriksa apakah gambar memerlukan shim kompatibilitas, memeriksa apakah kebijakan pembatasan perangkat lunak berlaku, yada yada.

Yang mengatakan, saya melihat perlambatan keseluruhan dalam jumlah semua hal kecil yang harus dilakukan selain pembuatan mentah dari suatu proses, ruang VA, dan utas awal. Tetapi seperti yang dikatakan di awal - karena lebih menyukai multithreading daripada multitasking, satu-satunya perangkat lunak yang sangat terpengaruh oleh biaya tambahan ini adalah perangkat lunak Unix yang di-porting dengan buruk. Meskipun situasi ini berubah ketika perangkat lunak seperti Chrome dan IE8 tiba-tiba menemukan kembali manfaat multiprosesing dan mulai sering memulai dan membongkar proses ...

Johannes Passing
sumber
8
Fork tidak selalu diikuti oleh exec (), dan orang yang peduli dengan fork () saja. Apache 1.3 menggunakan fork () (tanpa exec) di Linux dan thread di Windows, meskipun dalam banyak kasus proses di-fork sebelum dibutuhkan dan disimpan dalam kumpulan.
Blaisorblade
5
Tentu saja tidak lupa, perintah 'vfork', yang dirancang untuk skenario 'just call exec' yang Anda gambarkan.
Chris Huang-Leaver
4
Jenis perangkat lunak lain yang sangat terpengaruh oleh hal ini adalah semua jenis skrip shell yang melibatkan koordinasi beberapa proses. Skrip Bash di dalam Cygwin, misalnya, sangat menderita karenanya. Pertimbangkan shell loop yang menghasilkan banyak sed, awk, dan grep di pipeline. Setiap perintah memunculkan proses dan setiap pipa memunculkan subkulit dan proses baru di subkulit tersebut. Unix dirancang dengan mempertimbangkan jenis penggunaan ini, itulah sebabnya pembuatan proses cepat tetap menjadi norma di sana.
Dan Moulding
5
-1. Klaim bahwa perangkat lunak 'porting buruk' karena tidak berjalan dengan baik pada sistem operasi yang dirancang dengan buruk penuh dengan kompatibilitas yang memperlambat pembuatan proses adalah konyol.
Miles Rout
6
@MilesRout tujuan porting adalah untuk memodifikasi perangkat lunak agar berjalan pada sistem target baru, dengan mempertimbangkan kekuatan dan kekurangan sistem tersebut. Perangkat lunak porting yang berkinerja buruk adalah perangkat lunak yang diporting dengan buruk, terlepas dari penghalang pandang yang disediakan oleh sistem operasi.
Dizzyspiral
28

Unix memiliki panggilan sistem 'garpu' yang 'membagi' proses saat ini menjadi dua, dan memberi Anda proses kedua yang identik dengan yang pertama (modulo kembalian dari panggilan garpu). Karena ruang alamat dari proses baru sudah aktif dan berjalan, ini seharusnya lebih murah daripada memanggil 'CreateProcess' di Windows dan memuat gambar exe, dll terkait, dll.

Dalam kasus fork, OS dapat menggunakan semantik 'salin-saat-tulis' untuk halaman memori yang terkait dengan kedua proses baru untuk memastikan bahwa masing-masing mendapatkan salinannya sendiri dari halaman yang kemudian mereka modifikasi.

Rob Walker
sumber
22
Argumen ini hanya berlaku saat Anda benar-benar bercabang. Jika Anda memulai proses baru, di Unix Anda masih harus bercabang dan eksekutif. Baik Windows dan Unix memiliki salinan saat menulis. Windows pasti akan menggunakan kembali EXE yang dimuat jika Anda menjalankan salinan kedua dari sebuah aplikasi. Saya tidak berpikir penjelasan Anda benar, maaf.
Joel Spolsky
1
Lebih lanjut tentang exec () dan fork () vipinkrsahu.blogspot.com/search/label/system%20programming
webkul
Saya menambahkan beberapa data kinerja dalam jawaban saya. stackoverflow.com/a/51396188/537980 Anda dapat melihat bahwa ini lebih cepat.
ctrl-alt-delor
25

Menambah apa yang dikatakan JP: sebagian besar overhead dimiliki oleh startup Win32 untuk proses tersebut.

Kernel Windows NT sebenarnya mendukung garpu COW. SFU (lingkungan UNIX Microsoft untuk Windows) menggunakannya. Namun, Win32 tidak mendukung garpu. Proses SFU bukanlah proses Win32. SFU ortogonal untuk Win32: keduanya adalah subsistem lingkungan yang dibangun di atas kernel yang sama.

Selain panggilan LPC di luar proses CSRSS, di XP dan yang lebih baru, ada panggilan di luar proses ke mesin kompatibilitas aplikasi untuk menemukan program dalam database kompatibilitas aplikasi. Langkah ini menyebabkan overhead yang cukup sehingga Microsoft menyediakan opsi kebijakan grup untuk menonaktifkan mesin kompatibilitas pada WS2003 karena alasan kinerja.

Pustaka runtime Win32 (kernel32.dll, dll.) Juga melakukan banyak pembacaan dan inisialisasi registri saat startup yang tidak berlaku untuk UNIX, SFU atau proses asli.

Proses asli (tanpa subsistem lingkungan) sangat cepat dibuat. SFU melakukan lebih sedikit daripada Win32 untuk pembuatan proses, sehingga prosesnya juga cepat dibuat.

PEMBARUAN UNTUK 2019: tambahkan LXSS: Subsistem Windows untuk Linux

Mengganti SFU untuk Windows 10 adalah subsistem lingkungan LXSS. Ini adalah mode kernel 100% dan tidak memerlukan IPC apa pun yang terus dimiliki Win32. Syscall untuk proses ini diarahkan langsung ke lxss.sys / lxcore.sys, sehingga fork () atau proses lain yang membuat panggilan hanya memerlukan biaya 1 panggilan sistem untuk pembuat, total. [Area data yang disebut instance] melacak semua proses LX, utas, dan status runtime.

Proses LXSS didasarkan pada proses asli, bukan proses Win32. Semua hal spesifik Win32 seperti mesin kompatibilitas tidak terlibat sama sekali.

Chris Smith
sumber
16

Selain jawaban dari Rob Walker: Saat ini Anda memiliki hal-hal seperti Native POSIX Thread Library - jika Anda mau. Tapi untuk waktu yang lama satu-satunya cara untuk "mendelegasikan" pekerjaan di dunia unix adalah dengan menggunakan fork () (dan ini masih lebih disukai di banyak, banyak keadaan). misalnya beberapa jenis server soket

socket_accept ()
garpu()
jika (anak)
    handleRequest ()
lain
    goOnBeingParent ()
Oleh karena itu, implementasi fork harus cepat dan banyak pengoptimalan telah diterapkan dari waktu ke waktu. Microsoft mendukung CreateThread atau bahkan serat alih-alih membuat proses baru dan penggunaan komunikasi antarproses. Saya pikir itu tidak "adil" untuk membandingkan CreateProcess ke garpu karena mereka tidak dapat dipertukarkan. Mungkin lebih tepat untuk membandingkan fork / exec dengan CreateProcess.

VolkerK
sumber
2
Tentang poin terakhir Anda: fork () tidak dapat ditukar dengan CreateProcess (), tetapi orang juga dapat mengatakan bahwa Windows harus mengimplementasikan fork () kemudian, karena itu memberikan lebih banyak fleksibilitas.
Blaisorblade
Ah, kata kerja To Bee.
acib708
Tapi fork + exec di Linux, lebih cepat dari CreateThread di MS-Windows. Dan Linux dapat melakukan fork sendiri menjadi lebih cepat. Bagaimanapun Anda membandingkannya, MS lebih lambat.
ctrl-alt-delor
13

Kunci dari masalah ini adalah penggunaan historis dari kedua sistem, saya kira. Windows (dan DOS sebelumnya) awalnya adalah sistem pengguna tunggal untuk komputer pribadi . Dengan demikian, sistem ini biasanya tidak harus membuat banyak proses sepanjang waktu; (sangat) sederhananya, sebuah proses hanya dibuat ketika pengguna yang kesepian ini memintanya (dan kita manusia tidak beroperasi sangat cepat, secara relatif).

Sistem berbasis Unix awalnya adalah sistem dan server multi-pengguna. Khusus untuk yang terakhir, tidak jarang ada proses (mis. Mail atau http daemon) yang memisahkan proses untuk menangani pekerjaan tertentu (mis. Menangani satu koneksi masuk). Faktor penting dalam melakukan ini adalah forkmetode murah (yang, seperti disebutkan oleh Rob Walker ( 47865 ), awalnya menggunakan memori yang sama untuk proses yang baru dibuat) yang sangat berguna karena proses baru segera memiliki semua informasi yang dibutuhkan.

Jelas bahwa setidaknya secara historis kebutuhan sistem berbasis Unix untuk memiliki proses pembuatan yang cepat jauh lebih besar daripada untuk sistem Windows. Saya pikir ini masih terjadi karena sistem berbasis Unix masih sangat berorientasi pada proses, sedangkan Windows, karena sejarahnya, mungkin lebih berorientasi pada utas (utas berguna untuk membuat aplikasi responsif).

Penafian: Saya sama sekali bukan ahli dalam masalah ini, jadi maafkan saya jika saya salah.

mweerden
sumber
9

Uh, sepertinya ada banyak pembenaran "lebih baik begini" terjadi.

Saya pikir orang bisa mendapatkan keuntungan dari membaca "Showstopper"; buku tentang pengembangan Windows NT.

Seluruh alasan layanan dijalankan sebagai DLL dalam satu proses di Windows NT adalah karena mereka terlalu lambat sebagai proses terpisah.

Jika Anda turun dan kotor, Anda akan menemukan bahwa strategi pemuatan perpustakaan adalah masalahnya.

Pada Unices (secara umum) segmen kode Shared libraries (DLL) sebenarnya dibagikan.

Windows NT memuat salinan DLL per proses, karena itu memanipulasi segmen kode perpustakaan (dan segmen kode yang dapat dieksekusi) setelah memuat. (Memberitahu di mana data Anda?)

Ini menghasilkan segmen kode di pustaka yang tidak dapat digunakan kembali.

Jadi, proses pembuatan NT sebenarnya cukup mahal. Dan di sisi bawah, itu membuat DLL tidak menghemat memori, tetapi peluang untuk masalah ketergantungan antar aplikasi.

Kadang-kadang membayar dalam teknik untuk mundur dan berkata, "sekarang, jika kita akan merancang ini untuk benar-benar payah, akan terlihat seperti apa?"

Saya bekerja dengan sistem tertanam yang dulu cukup temperamental, dan suatu hari melihatnya dan menyadari itu adalah rongga magnetron, dengan elektronik di rongga gelombang mikro. Kami membuatnya jauh lebih stabil (dan tidak seperti microwave) setelah itu.

Tim Williscroft
sumber
3
Segmen kode dapat digunakan kembali selama DLL dimuat di alamat dasar pilihannya. Secara tradisional, Anda harus memastikan bahwa Anda menetapkan alamat dasar yang tidak berkonflik untuk semua DLL yang akan dimuat ke dalam proses Anda, tetapi itu tidak berfungsi dengan ASLR.
Mike Dimmick
Ada beberapa alat untuk me-rebase semua DLL, bukan? Tidak yakin apa fungsinya dengan ASLR.
Zan Lynx
3
Berbagi bagian kode juga berfungsi pada sistem yang mendukung ASLR.
Johannes Passing
@MikeDimmick jadi semua orang, membuat DLL harus bekerja sama, untuk memastikan bahwa tidak ada konflik, atau apakah Anda menambal semuanya pada tingkat sistem, sebelum memuat?
ctrl-alt-delor
9

Jawaban singkatnya adalah "lapisan dan komponen perangkat lunak".

Arsitektur Windows SW memiliki beberapa lapisan dan komponen tambahan yang tidak ada di Unix atau disederhanakan dan ditangani di dalam kernel di Unix.

Di Unix, fork dan exec adalah panggilan langsung ke kernel.

Di Windows, kernel API tidak digunakan secara langsung, ada win32 dan komponen tertentu lainnya di atasnya, jadi pembuatan proses harus melalui lapisan ekstra dan kemudian proses baru harus dimulai atau terhubung ke lapisan dan komponen tersebut.

Untuk beberapa waktu, para peneliti dan perusahaan telah mencoba untuk memecah Unix dengan cara yang agak mirip, biasanya mendasarkan eksperimen mereka pada kernel Mach ; contoh yang terkenal adalah OS X .. Setiap kali mereka mencoba, bagaimanapun, itu menjadi sangat lambat mereka akhirnya setidaknya menggabungkan sebagian potongan kembali ke kernel baik secara permanen atau untuk pengiriman produksi.

DigitalRoss
sumber
Lapisan tidak serta merta memperlambat segalanya: Saya menulis driver perangkat, dengan banyak lapisan, dalam C. Kode bersih, pemrograman terpelajar, mudah dibaca. Itu lebih cepat (sedikit), daripada versi yang ditulis dalam assembler yang sangat dioptimalkan, tanpa lapisan.
ctrl-alt-delor
Ironisnya, NT adalah kernel yang sangat besar (bukan kernel mikro)
ctrl-alt-delor
2

Karena tampaknya ada beberapa pembenaran MS-Windows di beberapa jawaban misalnya

  • “Kernel NT dan Win32, bukanlah hal yang sama. Jika Anda memprogram ke kernel NT maka itu tidak terlalu buruk. ”- Benar, tetapi kecuali Anda menulis subsistem Posix, lalu siapa yang peduli. Anda akan menulis untuk win32.
  • “Tidak adil membandingkan fork, dengan ProcessCreate, karena mereka melakukan hal yang berbeda, dan Windows tidak memiliki fork.“ - Benar, Jadi saya akan membandingkan like dengan like. Namun saya juga akan membandingkan garpu, karena memiliki banyak kasus penggunaan, seperti isolasi proses (misalnya, setiap tab browser web berjalan dalam proses yang berbeda).

Sekarang mari kita lihat faktanya, apa bedanya performanya?

Data diambil dari http://www.bitsnbites.eu/benchmarking-os-primitives/ .
Karena bias tidak bisa dihindari, ketika meringkas, saya melakukannya demi MS-Windows
Hardware untuk sebagian besar tes i7 8 core 3.2GHz. Kecuali Raspberry-Pi yang menjalankan Gnu / Linux

Perbandingan berbagai operasi dasar, di Gnu / Linux, Apple-Mac, dan Microsoft Windows (lebih kecil lebih baik)

Perbandingan proses pembuatan MS-Windows vs Linux

Catatan: Di linux, forklebih cepat dari metode yang disukai MS-Window CreateThread.

Angka untuk operasi jenis pembuatan proses (karena sulit untuk melihat nilai Linux di bagan).

Dalam urutan kecepatan, tercepat hingga paling lambat (angka adalah waktu, kecil lebih baik).

  • Linux CreateThread 12
  • Mac CreateThread 15
  • Linux Fork 19
  • Windows CreateThread 25
  • Linux CreateProcess (fork + exec) 45
  • Mac Fork 105
  • Mac CreateProcess (fork + exec) 453
  • Proses Pembuatan Raspberry-Pi (garpu + exec) 501
  • Windows CreateProcess 787
  • Windows CreateProcess Dengan pemindai virus 2850
  • Windows Fork (disimulasikan dengan CreateProcess + fixup) lebih besar dari 2850

Angka untuk pengukuran lainnya

  • Membuat file.
    • Linux 13
    • Mac 113
    • Windows 225
    • Raspberry-Pi (dengan kartu SD lambat) 241
    • Windows dengan pembela dan pemindai virus dll 12950
  • Mengalokasikan memori
    • Linux 79
    • Windows 93
    • Mac 152
ctrl-alt-delor
sumber
1

Semua itu plus ada fakta bahwa pada mesin Win kemungkinan besar perangkat lunak antivirus akan bekerja selama CreateProcess ... Itu biasanya pelambatan terbesar.

gabr
sumber
1
Ya, ini adalah yang terbesar, tetapi bukan satu-satunya perlambatan yang signifikan.
ctrl-alt-delor
1

Perlu juga dicatat bahwa model keamanan di Windows jauh lebih rumit daripada di OS berbasis unix, yang menambahkan banyak overhead selama pembuatan proses. Namun alasan lain mengapa multithreading lebih disukai daripada multiproses di Windows.

hacksoncode
sumber
1
Saya mengharapkan model keamanan yang lebih rumit menjadi lebih aman; tetapi fakta menunjukkan sebaliknya.
Lie Ryan
4
SELinux juga merupakan model keamanan yang sangat kompleks, dan tidak membebankan biaya tambahan yang signifikan padafork()
Spudd86
6
@LieRyan, Dalam desain perangkat lunak (menurut pengalaman saya), lebih rumit sangat jarang berarti lebih aman.
Woodrow Douglass