Topik temu duga representatif

Apakah Perbezaan Antara Proses dan Thread?

UmumSederhana
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Sebuah aplikasi mesti menjalankan 8 pemalam pihak ketiga CPU-bound yang mungkin mengalami ranap (crash) atau tergantung (hang) serta mengendalikan sehingga 2,000 permintaan I/O-bound serentak yang berkongsi cache besar yang sebahagian besarnya untuk bacaan (read-mostly). Adakah anda akan menggunakan proses, thread, atau model konkurensi lain untuk setiap beban kerja tersebut, dan mengapa?

Soalan dan bila patut menggunakannya

Sebuah aplikasi mesti menjalankan 8 pemalam pihak ketiga CPU-bound yang mungkin mengalami ranap atau tergantung dan mengendalikan sehingga 2,000 permintaan I/O-bound serentak yang berkongsi cache besar yang kebanyakannya untuk bacaan (read-mostly). Terangkan perbezaan antara proses dan thread, kemudian pilih model pelaksanaan untuk setiap beban kerja. Huraikan pemilikan sumber, penjadualan, komunikasi, penyegerakan, pengasingan kegagalan dan keselamatan, kitaran hayat, serta pengesahan.

Ini adalah soalan asas sistem pengoperasian untuk peranan perisian, backend, infrastruktur dan sistem. Angka 8 dan 2,000 hanyalah andaian temu duga, bukan peraturan saiz universal. Beban kerja pertama mengutamakan pengasingan dan keselarian (parallelism) CPU; beban kerja kedua mengutamakan konkurensi I/O yang tinggi serta akses yang cekap kepada data sepunya. Jawapan yang bernilai menerbitkan dua pilihan daripada kekangan tersebut dan bukannya mendakwa proses atau thread secara universalnya lebih pantas.

Perkara yang dinilai oleh penemu duga

Isyarat pertama ialah model pemilikan yang tepat. Proses ialah bekas sumber dan pengasingan yang mempunyai ruang alamat maya, kod boleh laksana, sumber sistem terbuka, konteks keselamatan, dan sekurang-kurangnya satu thread. Thread ialah konteks pelaksanaan yang boleh dijadualkan di dalam proses tersebut. Thread dalam satu proses berkongsi ruang alamat dan sumber peringkat prosesnya, manakala setiap thread mengekalkan keadaan pelaksanaan seperti daftar (registers), tindanan (stack), pengecam thread, dan storan setempat thread (thread-local storage).

Isyarat kedua ialah sama ada calon membezakan antara konkurensi dan keselarian. Pelbagai tugas boleh membuat kemajuan secara serentak pada satu teras melalui selang-seli (interleaving). Tugas-tugas ini dilaksanakan secara selari hanya apabila runtime dan sistem pengoperasian menjalankannya pada beberapa teras. Mencipta 2,000 thread tidak mencipta keselarian CPU 2,000 hala, dan lapan tugas CPU-bound tidak membayangkan bahawa lapan proses pekerja muat dalam belanjawan CPU dan memori mesin.

Isyarat ketiga ialah pertimbangan kejuruteraan. Memori kongsi menjadikan komunikasi thread secara langsung tetapi mewujudkan keadaan perlumbaan (race conditions), pertikaian kunci (lock contention), dan risiko kegagalan peringkat proses. Proses berasingan menyediakan sempadan kegagalan dan memori lalai yang lebih kukuh tetapi memerlukan IPC, penyeliaan, serta protokol pensirilan atau memori kongsi. Pengasingan proses sahaja bukanlah sandbox lengkap untuk kod yang tidak dipercayai; keistimewaan, panggilan sistem (system calls), fail, akses rangkaian, CPU dan memori juga memerlukan had.

Soalan untuk dijelaskan sebelum menjawab

  • Apakah yang dimaksudkan dengan "pihak ketiga"? Kod yang dipercayai tetapi mempunyai pepijat kebanyakannya memerlukan pengasingan ranap dan tergantung. Kod bermusuhan (adversarial) juga memerlukan sandbox sebenar, keistimewaan paling sedikit (least privilege), dan kawalan sumber.
  • Adakah pemalam mesti berkongsi model atau cache yang besar? Memori bebas lebih memihak kepada proses. Set data baca sahaja yang sangat besar mungkin memerlukan pemetaan baca sahaja yang dikongsi untuk mengelakkan satu salinan fizikal bagi setiap pekerja.
  • Adakah runtime bahasa membenarkan thread CPU-bound berjalan secara selari? Thread natif boleh menggunakan beberapa teras, tetapi kunci runtime atau penjadual mungkin mensirikan kod aplikasi dan mengubah pilihan tersebut.
  • Adakah pengendali permintaan menggunakan pustaka menghalang (blocking) atau tidak menghalang (nonblocking)? Kebergantungan menghalang sesuai dengan kolam thread terikat (bounded thread pool). Tindanan yang sepenuhnya tidak menghalang boleh mengendalikan banyak sambungan yang menunggu dengan gelung peristiwa (event loop) dan thread sistem pengoperasian yang lebih sedikit.
  • Bolehkah cache dijadikan tidak boleh diubah (immutable) atau diversi? Snapshot tidak boleh ubah dengan penggantian atomik lebih mudah dikongsi secara selamat berbanding graf objek boleh ubah yang memerlukan kunci berbutir halus (fine-grained locks).
  • Apakah objektif kegagalan dan kependaman (latency)? Had masa pemalam, belanjawan mula semula, p99 permintaan, kontrak pembatalan, had memori dan dasar beban lebih menentukan saiz kolam dan had giliran.

Kerangka jawapan 30 saat

"Satu proses memiliki ruang alamat maya terasing dan sumber peringkat proses; ia mengandungi satu atau lebih thread. Thread ialah konteks pelaksanaan boleh dijadualkan yang berkongsi keadaan proses tersebut tetapi mengekalkan tindanan, daftar, pengecam dan keadaan setempat thread sendiri. Saya akan menjalankan pemalam CPU yang mudah ranap dalam proses yang diselia dan dihadkan sumbernya supaya kegagalan atau keadaan tergantung boleh ditamatkan dan diganti tanpa berkongsi heap hos; bilangan pekerja mengikut belanjawan CPU dan memori, bukannya nombor lapan secara automatik. Bagi 2,000 permintaan yang kebanyakannya menunggu, saya akan menggunakan async event loop jika keseluruhan laluan kebergantungan adalah tidak menghalang, atau bounded thread pool jika pustaka adalah menghalang. Thread boleh berkongsi cache sebahagian besarnya baca, sebaik-baiknya sebagai snapshot tidak boleh diubah. Saya akan menanda aras daya pemprosesan (throughput), p99, memori, pertukaran konteks, masa menunggu IPC atau kunci, serta menyuntik ranap, tergantung dan keadaan perlumbaan sebelum membuat keputusan."

Penyelesaian langkah demi langkah

Langkah 1: Bina model pemilikan

Model mental yang mudah difahami ialah proses sebagai sempadan sumber dan thread sebagai aliran pelaksanaan di dalamnya. Pelaksanaan kernel yang tepat berbeza mengikut platform, jadi elakkan daripada membentangkan model objek dalaman satu sistem pengoperasian sebagai universal.

Keadaan atau sumberHubungan prosesHubungan thread
Ruang alamat maya, kod, heapBerasingan secara lalai antara prosesDikongsi oleh thread dalam satu proses
Fail terbuka dan sumber proses lainDimiliki atau dirujuk oleh proses; pewarisan dan perkongsian eksplisit adalah mungkinBiasanya dikongsi oleh thread dalam proses
Tindanan, daftar, pembilang program (program counter)Proses mengandungi ini melalui thread-threadnyaBerbeza bagi setiap thread
Storan setempat thread dan ID threadBukan satu nilai untuk keseluruhan prosesBerbeza bagi setiap thread
Had keselamatan dan sumberTempat semula jadi untuk dasar pengasinganKebanyakannya peringkat proses; sesetengah platform menyokong butiran per-thread seperti penyamaran (impersonation)

"Berasingan secara lalai" adalah penting. Proses boleh berkongsi memori, fail dan pemegang (handles) secara sengaja; thread boleh berkomunikasi melalui giliran dan bukannya mutasi kongsi sewenang-wenangnya. Pilihan ini mengawal sempadan kegagalan dan pemilikan lalai, bukannya satu-satunya API komunikasi yang mungkin.

Langkah 2: Asingkan konkurensi, keselarian dan kos

Konkurensi bermaksud beberapa unit kerja kekal dalam proses kemajuan. Keselarian bermaksud kerja dilaksanakan pada masa yang sama pada sumber pemprosesan yang berbeza. Satu thread boleh memultiplekskan banyak operasi I/O tak segerak; pelbagai thread atau proses yang boleh dijalankan boleh menggunakan pelbagai teras. Keselarian CPU sebenar dihadkan oleh teras yang tersedia, kuota kontena, dan tingkah laku runtime.

Thread biasanya lebih murah untuk dicipta dan bertukar konteks kerana ia menggunakan semula satu ruang alamat, manakala proses biasanya membawa lebih banyak memori dan keadaan kitaran hayat. Itu adalah kecenderungan, bukan jaminan prestasi. Penciptaan proses copy-on-write, peruntukan tindanan thread, terlepas cache (cache misses), perubahan ruang alamat, penjadualan runtime, muatan IPC, dan pertikaian kunci boleh menterbalikkan kos penting untuk sesuatu beban kerja tertentu. Jangan letakkan angka mikrosaat atau memori yang universal; ukur runtime dan platform sasaran.

Langkah 3: Bandingkan kos komunikasi dan ketepatan

Thread boleh menghantar penunjuk (pointer) ke data kongsi, tetapi setiap objek boleh ubah memerlukan peraturan pemilikan atau penyegerakan. Dua thread yang melakukan baca-ubah-tulis (read-modify-write) pada satu entri cache boleh kehilangan kemas kini walaupun setiap baris kod sumber kelihatan mudah. Kunci, atomics, data tidak boleh ubah, penghantaran mesej, atau pemilikan terbahagi menyelesaikan corak akses yang berbeza. Kunci yang mengekalkan ketepatan masih boleh menghasilkan giliran panjang dan kependaman p99 yang tinggi di bawah pertikaian.

Proses biasanya bertukar mesej melalui paip (pipes), soket, giliran, atau RPC. Ini mewujudkan protokol yang jelas dan menjadikan pemilikan lebih mudah diaudit, dengan kos pensirilan, penyalinan, tekanan balik (backpressure), dan pengendalian kegagalan separa. Memori kongsi boleh menghapuskan penyalinan, tetapi kemudian proses sekali lagi memerlukan protokol versi dan penyegerakan. IPC tidak menghapuskan pepijat konkurensi; ia memindahkannya ke sempadan identiti mesej, susunan, percubaan semula, masa tamat dan kitaran hayat.

Langkah 4: Pilih proses diselia untuk beban kerja pemalam

Bagi 8 tugas pihak ketiga CPU-bound, gunakan kolam proses pekerja terikat yang diselia oleh hos. Berikan setiap tugas satu pengecam, kontrak input, had masa, kontrak output, dan tingkah laku pembatalan. Pekerja yang keluar, melebihi had masa, atau melanggar had sumber akan ditamatkan dan diganti; penyelia memutuskan sama ada tugas itu selamat untuk dicuba semula. Jauhkan keadaan pemalam daripada heap hos dan hantar input serta output yang jelas.

Saiz kolam ditentukan oleh kuota CPU, memori pemalam dan ruang simpanan perkhidmatan (headroom). Pada kuota empat teras, memulakan lapan pekerja yang sentiasa boleh dijalankan boleh meningkatkan pertukaran konteks tanpa mengurangkan jumlah kerja CPU. Jika pemalam memerlukan set data baca sahaja sepunya yang besar, petakan snapshot baca sahaja yang disahkan ke dalam pekerja atau jalankan perkhidmatan data khusus; jangan tinggalkan pengasingan kerosakan semata-mata untuk mengelakkan andaian kos penyalinan.

Proses berasingan hanyalah satu lapisan keselamatan. Pemalam yang berpotensi bermusuhan memerlukan identiti terhad, sempadan sandbox atau kontena, dasar panggilan sistem yang dibenarkan jika ada, sekatan sistem fail dan rangkaian, kuota CPU dan memori, serta pengesah output. Asingkan juga penyelia daripada kebanjiran log pekerja, fail ranap, dan percubaan mula semula.

Langkah 5: Pilih async I/O atau bounded thread pool untuk permintaan

Bagi sehingga 2,000 permintaan serentak yang menghabiskan sebahagian besar masanya menunggu, jangan petakan "satu permintaan" secara terus kepada "satu proses baharu." Jika rangkaian, pangkalan data dan pustaka klien adalah tidak menghalang dari hujung ke hujung, gelung peristiwa boleh mengekalkan banyak permintaan berjalan pada bilangan thread yang kecil. Kerja berat CPU mesti dialihkan daripada gelung peristiwa, dan setiap giliran memerlukan had supaya beban berlebihan bertukar menjadi penolakan atau tekanan balik dan bukannya pertumbuhan memori tanpa had.

Jika pustaka yang diperlukan menghalang, gunakan bounded thread pool yang disesuaikan saiznya dan diukur terhadap kebergantungan tersebut. Had ini melindungi memori, sambungan terbuka, dan kapasiti hiliran. Thread boleh mengakses cache sebahagian besarnya baca tanpa IPC; terbitkan snapshot tidak boleh ubah dan diversi melalui rujukan atomik apabila boleh. Jika mutasi tidak dapat dielakkan, tentukan skop kunci dan ukur pertikaian. Menggabungkan gelung peristiwa untuk soket dengan kolam kerja menghalang yang terikat selalunya lebih tepat daripada hanya memilih "thread" atau "async."

Langkah 6: Sahkan keputusan dengan pengukuran dan kerosakan (faults)

Tanda aras kedua-dua calon pada mesin atau kuota yang sama dengan muatan dan nisbah menunggu yang menyerupai pengeluaran. Rekodkan daya pemprosesan, kependaman p50 dan p99, penggunaan CPU, memori pemastautin dan berkadar, masa giliran, pertukaran konteks, bait IPC dan masa pensirilan untuk proses, serta masa menunggu kunci ditambah kelengahan gelung peristiwa untuk reka bentuk ber-thread atau async. Masa pemanasan (warm-up), pengedaran input, bilangan pekerja, dan had giliran mestilah sama apabila membandingkan keputusan.

Uji sempadan seagresif menguji laluan lancar (happy path):

  1. Ranapkan pemalam dan sahkan bahawa hos dan pekerja lain kekal tersedia, penamatan dikesan, dan dasar mula semula adalah terikat.
  2. Gantungkan pemalam dan sahkan had masa, penamatan, pembersihan, dan keputusan percubaan semula.
  3. Paksa pertumbuhan memori dan log pemalam dan sahkan kuota melindungi hos.
  4. Berikan tekanan pada bacaan dan penyegaran cache serentak; gunakan pengesan perlumbaan (race detector) jika runtime menyediakannya dan sahkan pembaca melihat snapshot lama atau baharu yang lengkap.
  5. Tepukan pengendalian permintaan dan sahkan giliran terikat, pembatalan, had hiliran, dan respons beban berlebihan.
  6. Mulakan semula perkhidmatan dan sahkan pemilikan dalam proses sama ada dipulihkan atau digagalkan mengikut kontrak.

Peraturan keputusan yang boleh diguna semula ialah: pilih sempadan proses apabila pengasingan, kitaran hayat bebas, atau keselarian CPU runtime mendominasi; pilih thread kongsi apabila akses kos rendah kepada keadaan dalam proses sepunya mendominasi dan penyegerakan kekal boleh diurus; pilih tugas async apabila konkurensi menunggu mendominasi dan rantaian kebergantungan menyokong pembatalan tidak menghalang. Sahkan sempadan yang boleh gagal, bukan hanya daya pemprosesan puncak.

Contoh jawapan yang mantap

"Saya akan mulakan dengan pemilikan. Sesuatu proses mempunyai ruang alamat maya dan sumber peringkat prosesnya sendiri serta mengandungi sekurang-kurangnya satu thread. Thread dalam proses tersebut berkongsi heap dan sumber terbukanya, manakala setiap thread mempunyai tindanan, daftar, pengecam dan keadaan setempat thread sendiri. Ini menjadikan thread mudah untuk data kongsi, tetapi penulisan yang buruk atau kegagalan maut boleh menjejaskan keseluruhan proses. Proses menjadikan komunikasi lebih eksplisit dan menyediakan sempadan kegagalan lalai yang lebih kukuh, walaupun memori kongsi dan sumber yang diwarisi bermakna sempadan itu boleh dikonfigurasi.

Bagi lapan pemalam CPU-bound, saya akan menggunakan proses pekerja yang diselia. Penyelia menghantar tugas dengan ID dan had masa, mengesahkan hasilnya, memerhati penamatan proses, dan menggantikan pekerja yang gagal dengan belanjawan mula semula. Bilangan pekerja mengikut kuota CPU dan ukuran memori; lapan tugas tidak bermakna lapan pekerja secara automatik. Jika pemalam tidak dipercayai, proses berasingan adalah perlu tetapi tidak mencukupi, jadi saya juga akan mengehadkan keistimewaan, panggilan sistem, fail, rangkaian, CPU dan memori.

Bagi 2,000 permintaan yang kebanyakannya menunggu I/O, saya akan memeriksa pustakanya. Dengan laluan tidak menghalang, saya akan menggunakan gelung peristiwa dan memindahkan kerja CPU ke kolam terikat. Dengan kebergantungan menghalang, saya akan menggunakan bounded thread pool. Cache sebahagian besarnya baca akan menjadi snapshot tidak boleh ubah diversi yang diterbitkan secara atomik, mengelakkan kunci pada setiap bacaan. Setiap giliran dan panggilan hiliran mempunyai had masa dan had kapasiti.

Saya akan membandingkan daya pemprosesan dan p99 bersama-sama dengan CPU, memori, masa giliran, pertukaran konteks, masa menunggu IPC atau kunci, dan kelengahan gelung peristiwa. Kemudian saya akan menguji ranap, tergantung dan tekanan memori pada pemalam serta menguji keadaan perlumbaan pada penyegaran cache. Reka bentuk ini menang hanya jika tuntutan pengasingan dan ketepatannya bertahan daripada kerosakan tersebut, bukan kerana thread atau proses secara umumnya dianggap lebih ringan."

Kesilapan lazim

  • Mengatakan proses ialah program dan thread ialah fungsi → Ini mengabaikan pemilikan sumber dan keadaan yang boleh dijadualkan → Huraikan sempadan ruang alamat proses serta keadaan pelaksanaan thread yang dikongsi dan peribadi.
  • Mendakwa thread berkongsi segala-galanya → Setiap thread mempunyai tindanan, daftar, pengecam dan keadaan setempat thread sendiri → Senaraikan keadaan peringkat proses dan per-thread secara berasingan.
  • Mendakwa proses tidak boleh berkongsi memori → Pemetaan kongsi eksplisit adalah mungkin → Nyatakan bahawa proses diasingkan secara lalai dan terangkan protokol yang diperlukan untuk berkongsi secara selamat.
  • Memanggil konkurensi dan keselarian sebagai sinonim → Kerja boleh diselang-seli pada satu teras tanpa dilaksanakan secara serentak → Kaitkan keselarian dengan teras, kuota, dan tingkah laku runtime.
  • Memilih lapan pekerja hanya kerana terdapat lapan tugas → Pekerja yang boleh dijalankan bersaing untuk CPU dan memori yang terhad → Tentukan saiz kolam daripada kuota, ukuran dan ruang simpanan perkhidmatan.
  • Menggunakan proses sebagai sandbox lengkap untuk kod yang tidak dipercayai → Proses masih boleh mengakses fail, rangkaian dan antara muka kernel yang dibenarkan atau menghabiskan sumber → Tambah keistimewaan paling sedikit, dasar sandbox, kuota, dan pengesahan output.
  • Mencipta satu thread bagi setiap permintaan yang menunggu tanpa had → Memori tindanan, penjadualan dan panggilan hiliran boleh menghabiskan sumber perkhidmatan → Gunakan async I/O atau kolam terikat yang diukur dengan tekanan balik.
  • Berkongsi cache boleh ubah tanpa peraturan pemilikan → Perlumbaan data dan pertikaian kunci boleh merosakkan ketepatan atau kependaman ekor (tail latency) → Utamakan snapshot tidak boleh ubah atau tentukan dan uji penyegerakan.
  • Membandingkan hanya daya pemprosesan purata → Sesuatu reka bentuk boleh menyembunyikan giliran p99, pertumbuhan memori, atau pengasingan yang lemah → Ukur taburan kependaman dan suntik ranap, tergantung, ketepuan, dan keadaan perlumbaan.
  • Menganggap thread sentiasa lebih pantas → Kos runtime, IPC, cache, kunci dan beban kerja adalah berbeza-beza → Anggap overhed yang lebih rendah sebagai hipotesis dan tanda aras pelaksanaan sebenar.

Soalan susulan dan jawapan

Soalan susulan 1: Bolehkah proses masih berkongsi model baca sahaja 20 GB?

Boleh. Petakan fail tidak boleh diubah yang disahkan atau kawasan memori kongsi sebagai baca sahaja ke dalam setiap pekerja supaya halaman fizikal boleh dikongsi jika sistem pengoperasian menyokongnya. Versikan pemetaan tersebut dan tukar pekerja kepada snapshot baharu dan bukannya mengubahnya secara langsung di tempat asal. Ukur kelakuan kegagalan halaman (page-fault) dan pemastautin, serta kekalkan keadaan boleh ubah setiap permintaan di luar kawasan kongsi.

Soalan susulan 2: Apakah yang berubah jika runtime bahasa mensirikan thread CPU-bound?

Sahkan runtime dan beban kerja yang tepat; kunci mungkin hanya meliputi pelaksanaan bahasa terurus manakala pustaka natif melepaskannya. Jika kerja CPU disirikan, gunakan proses pekerja atau kemudahan runtime yang menyediakan pelaksanaan selari sebenar. Kekalkan giliran terikat dan pembatalan, kerana menukar primitif pekerja tidak menyelesaikan masalah beban berlebihan.

Soalan susulan 3: Adakah satu thread yang tersekat (blocked) menghentikan keseluruhan proses?

Biasanya, thread lain yang boleh dijalankan boleh meneruskan kerja. Proses masih boleh terhenti jika thread yang tersekat itu memegang kunci, memiliki gelung peristiwa yang diperlukan, menghabiskan kolam kongsi, atau menunggu di dalam laluan permulaan peringkat proses. Diagnosis graf kebergantungan dan pemilikan dan bukannya menyamakan satu thread yang tersekat dengan satu proses yang tersekat.

Soalan susulan 4: Bilakah kolam thread lebih baik daripada gelung peristiwa?

Kolam thread sesuai untuk pustaka menghalang, konkurensi sederhana, dan kod yang kesederhanaannya melebihi kos thread yang diukur. Gelung peristiwa sesuai untuk konkurensi menunggu yang besar apabila setiap kebergantungan penting menyokong operasi tidak menghalang dan pembatalan. Model hibrid menggunakan gelung peristiwa untuk soket dan kolam terikat untuk kerja menghalang yang tidak dapat dielakkan; giliran dan had masanya adalah sebahagian daripada reka bentuk.

Soalan susulan 5: Bagaimanakah anda menghalang satu ranap pekerja daripada menyebabkan ribut mula semula (restart storm)?

Kelaskan punca penamatan, hadkan mula semula dalam satu tempoh masa, tambah backoff, kuarantin versi pemalam yang berulang kali gagal, dan tutup kemasukan (admission) apabila kapasiti tidak selamat. Kekalkan keadaan tugas yang mencukupi untuk memutuskan sama ada tugas yang terganggu boleh dicuba semula. Berikan amaran pada gelung ranap tanpa menghantar log atau artifak ranap tanpa had melalui penyelia.

Soalan susulan 6: Bilakah perkhidmatan berasingan patut menggantikan proses tempatan?

Gunakan sempadan perkhidmatan apabila pekerja memerlukan pelaksanaan (deployment), penskalaan, pemilikan, runtime bahasa, atau dasar keselamatan peringkat hos yang bebas. Kosnya melibatkan RPC rangkaian, kontrak diversi, penemuan perkhidmatan, penjejakan teragih, dan kegagalan separa. Proses tempatan kekal lebih mudah apabila satu penyelia peringkat hos dan IPC tempatan memenuhi keperluan pengasingan dan penskalaan.

Sumber awam

Soalan berkaitan