Bagaimana untuk memahami bahawa Node.js bukanlah program satu benang sepenuhnya (analisis ringkas)

青灯夜游
Lepaskan: 2022-02-18 19:37:54
ke hadapan
1871 orang telah melayarinya

Mengapa anda katakan Node.js tidak berbenang tunggal sepenuhnya? Bagaimana untuk memahami? Artikel berikut akan membincangkannya dengan anda, saya harap ia akan membantu anda!

Bagaimana untuk memahami bahawa Node.js bukanlah program satu benang sepenuhnya (analisis ringkas)

Saya percaya semua orang tahu bahawa nod ialah program satu benang yang menggunakan Gelung Acara untuk mencapai berbilang mata wang. Malangnya ini tidak sepenuhnya betul.

Jadi mengapa Node.js bukan program satu benang sepenuhnya?

Node.js ialah program satu benang*

Semua Javsacript, V8 dan gelung peristiwa yang kami tulis sendiri dijalankan dalam urutan yang sama, yang merupakan utas utama .

Hei, bukankah ini bermakna nod itu berbenang tunggal?

Tetapi mungkin anda tidak tahu bahawa nod mempunyai banyak modul dengan kod C di belakangnya.

Walaupun nod tidak mendedahkan pengguna kepada kebenaran untuk mengawal benang, C boleh menggunakan berbilang benang.

Jadi bila nod akan menggunakan multi-threading?

  • Jika kaedah nod memanggil kaedah segerak C di belakang tabir, kaedah itu akan dijalankan dalam urutan utama.

  • Jika kaedah nod memanggil kaedah tak segerak C di belakang tabir, kadangkala kaedah itu tidak dijalankan dalam utas utama.

Cakap itu murah, tunjukkan kodnya.

Kaedah segerak, berjalan dalam utas utama

Di sinicrypto Banyak modul berkaitan ditulis dalam C. Program berikut ialah fungsi untuk mengira cincang, yang biasanya digunakan untuk menyimpan kata laluan.

import { pbkdf2Sync } from "crypto";
const startTime = Date.now();
let index = 0;
for (index = 0; index < 3; index++) {
    pbkdf2Sync("secret", "salt", 100000, 64, "sha512");
    const endTime = Date.now();
    console.log(`${index} time, ${endTime - startTime}`);
}
const endTime = Date.now();
console.log(`in the end`);
Salin selepas log masuk

Masa keluaran,

0 time, 44 
1 time, 90
2 time, 134
in the end
Salin selepas log masuk

Anda boleh melihat bahawa ia mengambil masa kira-kira 45ms setiap kali dan kod dilaksanakan secara berurutan pada urutan utama.

Beri perhatian kepada siapa keluaran akhir? Ambil perhatian bahawa cincang di sini mengambil masa ~45ms pada CPU saya.

Kaedah pbkdf2 tak segerak, tidak berjalan dalam utas utama

import { cpus } from "os";
import { pbkdf2 } from "crypto";
console.log(cpus().length);
let startTime = console.time("time-main-end");
for (let index = 0; index < 4; index++) {
    startTime = console.time(`time-${index}`);
    pbkdf2("secret", `salt${index}`, 100000, 64, "sha512", (err, derivedKey) => {
        if (err) throw err;
        console.timeEnd(`time-${index}`);
    });
}
console.timeEnd("time-main-end");
Salin selepas log masuk

Masa keluaran,

time-main-end: 0.31ms
time-2: 45.646ms
time-0: 46.055ms
time-3: 46.846ms
time-1: 47.159ms
Salin selepas log masuk

Lihat di sini , utas utama berakhir lebih awal, tetapi masa untuk setiap pengiraan ialah 45ms Anda mesti tahu bahawa masa yang diperlukan untuk CPU mengira cincang ialah 45ms. Nod di sini pasti menggunakan berbilang utas untuk pengiraan cincang.

Jika saya menukar bilangan panggilan di sini kepada 10, maka masanya adalah seperti berikut. Sekali lagi, terbukti bahawa nod pasti menggunakan berbilang benang untuk pengiraan cincang.

time-main-end: 0.451ms
time-1: 44.977ms
time-2: 46.069ms
time-3: 50.033ms
time-0: 51.381ms
time-5: 96.429ms // 注意这里,从第五次时间开始增加了
time-7: 101.61ms
time-4: 113.535ms
time-6: 121.429ms
time-9: 151.035ms
time-8: 152.585ms
Salin selepas log masuk

Walaupun terbukti di sini, nod pastinya mendayakan pelbagai benang. Tapi masalah sikit? CPU komputer saya ialah AMD R5-5600U, yang mempunyai 6 teras dan 12 benang. Tetapi mengapa masa meningkat dari kali kelima tidak menggunakan CPU saya sepenuhnya?

Apa sebabnya?

Nod menggunakan kumpulan benang yang dipratentukan Saiz lalai kumpulan benang ini ialah 4.

eksport UV_THREADPOOL_SIZE=6

Mari kita lihat An. contoh,

Permintaan HTTP

import { request } from "https";
const options = {
  hostname: "www.baidu.com",
  port: 443,
  path: "/img/PC_7ac6a6d319ba4ae29b38e5e4280e9122.png",
  method: "GET",
};

let startTime = console.time(`main`);

for (let index = 0; index < 15; index++) {
  startTime = console.time(`time-${index}`);
  const req = request(options, (res) => {
    console.log(`statusCode: ${res.statusCode}`);
    console.timeEnd(`time-${index}`);
    res.on("data", (d) => {
      // process.stdout.write(d);
    });
  });

  req.on("error", (error) => {
    console.error(error);
  });

  req.end();
}

console.timeEnd("main");
Salin selepas log masuk
main: 13.927ms
time-2: 83.247ms
time-4: 89.641ms
time-3: 91.497ms
time-12: 91.661ms
time-5: 94.677ms
.....
time-8: 134.026ms
time-1: 143.906ms
time-13: 140.914ms
time-10: 144.088ms
Salin selepas log masuk

Atur cara utama di sini juga tamat awal Di sini saya mulakan permintaan http untuk memuat turun imej sebanyak 15 kali, dan mereka dibelanjakan Masa tidak meningkat secara eksponen dan nampaknya tidak dihadkan oleh kumpulan benang/cpu.

Kenapa? ? Adakah Node menggunakan kolam benang?

Jika kaedah C asynchronous di belakang Node akan cuba melihat jika terdapat sokongan tak segerak kernel, sebagai contoh, sila gunakan epoll (Linux) untuk rangkaian di sini Jika kernel tidak menyediakan kaedah tak segerak, Node akan menggunakan kumpulan benangnya sendiri. .

Jadi, walaupun permintaan http tidak segerak, ia dilaksanakan oleh kernel Selepas kernel selesai, C akan dimaklumkan, dan C akan memberitahu utas utama untuk mengendalikan panggilan balik.

Jadi kaedah tak segerak yang manakah dalam Node menggunakan kumpulan benang? Mana yang tidak?

  • Async Kernal Asli

    • Pelanggan pelayan TCP/UDP
    • Soket Domain Unix (IPC)
    • paip
    • dns.resolveXXX
    • input tty(stdin dll)
    • Isyarat Unix
    • Proses kanak-kanak
  • Kolam benang

    • fs.*
    • dns.lookup
    • paip (kes tepi)

ini Ia juga merupakan titik masuk untuk kebanyakan pengoptimuman Nod.

Tetapi bagaimana ini digabungkan dengan Gelung Acara yang paling penting?

Gelung Acara

Saya percaya semua orang sudah biasa dengan gelung Acara. Gelung acara adalah seperti pengedar

  • Jika ia menemui program javascript biasa atau panggilan balik, ia diserahkan kepada V8 untuk diproses.

  • Jika kaedah penyegerakan ditulis dalam C, serahkan kepada C dan jalankannya pada utas utama.

  • Jika anda menemui kaedah tak segerak, bahagian belakang ditulis dalam C. Jika terdapat sokongan tak segerak kernel, ia akan diserahkan dari utas utama kepada kernel untuk pemprosesan.

  • Jika ia tak segerak bahagian belakang kaedah ditulis dalam C. Jika tiada sokongan tak segerak kernel, ia diserahkan dari utas utama kepada kolam benang.

  • Kumpulan benang dan kernel akan mengembalikan hasil ke gelung acara Jika terdapat panggilan balik javascript didaftarkan, ia akan diserahkan kepada V8 untuk diproses.

Kemudian kitaran diteruskan sehingga tiada apa-apa lagi untuk diproses.

Jadi Node bukanlah program berbenang tunggal.

Untuk lebih banyak pengetahuan berkaitan nod, sila lawati: tutorial nodejs!

Atas ialah kandungan terperinci Bagaimana untuk memahami bahawa Node.js bukanlah program satu benang sepenuhnya (analisis ringkas). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan