検索

ノードJS内部

Nov 19, 2024 am 08:15 AM

あなたがレストランに行って、「私は同時に何百人もの料理を作ることができます、そしてあなた方の誰もお腹を空かせることはありません」と約束する一人のシェフがいると仮定します。不可能に聞こえますよね?この 1 つのチェックを、複数の注文をすべて管理し、すべての顧客に料理を提供する Node JS と考えることができます。

誰かに「Node JS とは何ですか?」という質問をすると、必ず「Node JS はブラウザ環境の外で JavaScript を実行するために使用されるランタイムです」という答えが返ってきます。

しかし、ランタイムとは何を意味するのでしょうか?... ランタイム環境は、コードの実行が特定のプログラミング言語で記述されるソフトウェア インフラストラクチャです。コードの実行、エラーの処理、メモリの管理を行うためのすべてのツール、ライブラリ、機能が備わっており、基盤となるオペレーティング システムやハードウェアと対話できます。

Node JS にはこれらがすべて含まれています。

  • コードを実行するには Google V8 エンジン。

  • fs、crypto、http などのコア ライブラリと API。

  • 非同期およびノンブロッキング I/O 操作をサポートする Libuv やイベント ループなどのインフラストラクチャ。

これで、Node JS がランタイムと呼ばれる理由がわかりました。

このランタイムは、V8libuv という 2 つの独立した依存関係で構成されます。

V8 は Google Chrome でも使用されているエンジンで、Google が開発・管理しています。 Node JS では JavaScript コードを実行します。コマンド node Index.js を実行すると、Node JS はこのコードを V8 エンジンに渡します。 V8 はこのコードを処理して実行し、結果を提供します。たとえば、コードが「Hello, World!」をログに記録するとします。コンソールに対して、V8 はこれを実現する実際の実行を処理します。

libuv ライブラリには、ネットワーク、I/O 操作、または時間関連の操作などの機能が必要な場合にオペレーティング システムへのアクセスを可能にする C コードが含まれています。これは、Node JS とオペレーティング システムの間のブリッジとして機能します。

libuv は次の操作を処理します:

  • ファイル システム操作: ファイルの読み取りまたは書き込み (fs.readFile、fs.writeFile)。

  • ネットワーク: HTTP リクエスト、ソケットの処理、またはサーバーへの接続。

  • タイマー: setTimeout や setInterval などの関数を管理します。

ファイル読み取りなどのタスクは Libuv スレッド プールによって処理され、タイマーは Libuv のタイマー システムによって処理され、ネットワーク呼び出しは OS レベルの API によって処理されます。

Node JS はシングルスレッドですか?

次の例を見てください。

const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'file.txt');

const readFileWithTiming = (index) => {
  const start = Date.now();
  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
      console.error(`Error reading the file for task ${index}:`, err);
      return;
    }
    const end = Date.now();
    console.log(`Task ${index} completed in ${end - start}ms`);
  });
};

const startOverall = Date.now();
for (let i = 1; i  {
  const endOverall = Date.now();
  console.log(`Total execution time: ${endOverall - startOverall}ms`);
});

同じファイルを 4 回読み取り、それらのファイルを読み取る時間を記録しています。

このコードから次の出力が得られます。

Task 1 completed in 50ms
Task 2 completed in 51ms
Task 3 completed in 52ms
Task 4 completed in 53ms
Total execution time: 54ms

ほぼ 50 ミリ秒で 4 つのファイルすべての読み取りが完了したことがわかります。 Node JS がシングルスレッドの場合、これらすべてのファイルの読み取り操作はどのようにして同時に完了するのでしょうか?

この質問は、libuv ライブラリがスレッド プールを使用していると答えています。スレッド プールはスレッドの束です。デフォルトでは、スレッド プール サイズは 4 で、libuv によって一度に 4 つのリクエストを処理できることを意味します。

1 つのファイルを 4 回読み取る代わりに、このファイルを 6 回読み取る別のシナリオを考えてみましょう。

const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'file.txt');

const readFileWithTiming = (index) => {
  const start = Date.now();
  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
      console.error(`Error reading the file for task ${index}:`, err);
      return;
    }
    const end = Date.now();
    console.log(`Task ${index} completed in ${end - start}ms`);
  });
};

const startOverall = Date.now();
for (let i = 1; i  {
  const endOverall = Date.now();
  console.log(`Total execution time: ${endOverall - startOverall}ms`);
});

出力は次のようになります:

Task 1 completed in 50ms
Task 2 completed in 51ms
Task 3 completed in 52ms
Task 4 completed in 53ms
Total execution time: 54ms

Node JS Internals

読み取り操作 1 と 2 が完了し、スレッド 1 と 2 が解放されたとします。

Node JS Internals

最初の 4 回はファイルの読み取りにほぼ同じ時間がかかりますが、このファイルを 5 回目と 6 回目に読み取ると、読み取り操作を完了するまでに最初の 4 回の読み取り操作に比べてほぼ 2 倍の時間がかかることがわかります。 。

これは、スレッド プール サイズがデフォルトで 4 であるため、4 つの読み取り操作が同時に処理されますが、ファイルの読み取りが 2 回 (5 回目と 6 回目) 行われるため、すべてのスレッドが何らかの作業を行っているため、libuv が待機するために発生します。 4 つのスレッドのうち 1 つが実行を完了すると、5 回目の読み取り操作がそのスレッドに対して処理され、6 回目の読み取り操作も同様に実行されます。それがより時間がかかる理由です。

つまり、Node JS はシングルスレッドではありません。

しかし、なぜ一部の人はそれをシングルスレッドと呼ぶのでしょうか?

これは、メイン イベント ループがシングルスレッドであるためです。このスレッドは、非同期コールバックの処理やタスクの調整など、Node JS コードの実行を担当します。ファイル I/O などのブロック操作は直接処理しません。

コード実行の流れはこんな感じです。

  • 同期コード (V8):

Node.js は、V8 JavaScript エンジンを使用して、すべての同期 (ブロッキング) コードを 1 行ずつ実行します。

  • 委任された非同期タスク:

fs.readFile、setTimeout、http リクエストなどの非同期操作は、Libuv ライブラリまたは他のサブシステム (OS など) に送信されます。

  • タスクの実行:

ファイル読み取りなどのタスクは Libuv スレッド プールによって処理され、タイマーは Libuv のタイマー システムによって処理され、ネットワーク呼び出しは OS レベルの API によって処理されます。

  • キューに入れられたコールバック:

非同期タスクが完了すると、それに関連付けられたコールバックがイベント ループのキューに送信されます。

  • イベント ループはコールバックを実行します:

イベント ループはキューからコールバックを取得して 1 つずつ実行し、ノンブロッキングな実行を保証します。

スレッド プールのサイズは、process.env.UV_THREADPOOL_SIZE = 8 を使用して変更できます。

今、スレッド数を高く設定すれば、大量のリクエストにも対応できるのではないかと考えています。皆さんも私と同じように考えていただければ幸いです。

しかし、それは私たちが考えていたこととは逆です。

スレッド数を特定の制限を超えて増やすと、コードの実行が遅くなります。

次の例を見てください。

const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'file.txt');

const readFileWithTiming = (index) => {
  const start = Date.now();
  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
      console.error(`Error reading the file for task ${index}:`, err);
      return;
    }
    const end = Date.now();
    console.log(`Task ${index} completed in ${end - start}ms`);
  });
};

const startOverall = Date.now();
for (let i = 1; i  {
  const endOverall = Date.now();
  console.log(`Total execution time: ${endOverall - startOverall}ms`);
});

出力:

高スレッド プール サイズ (100 スレッド)

Task 1 completed in 50ms
Task 2 completed in 51ms
Task 3 completed in 52ms
Task 4 completed in 53ms
Total execution time: 54ms

次に、スレッド プール サイズを 4 (デフォルト サイズ) に設定した場合の出力を示します。

デフォルトのスレッド プール サイズ (4 スレッド)

const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'file.txt');

const readFileWithTiming = (index) => {
  const start = Date.now();
  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
      console.error(`Error reading the file for task ${index}:`, err);
      return;
    }
    const end = Date.now();
    console.log(`Task ${index} completed in ${end - start}ms`);
  });
};

const startOverall = Date.now();
for (let i = 1; i  {
  const endOverall = Date.now();
  console.log(`Total execution time: ${endOverall - startOverall}ms`);
});

合計実行時間には 100ms の差があることがわかります。合計実行時間 (スレッド プール サイズ 4) は 600 ミリ秒、合計実行時間 (スレッド プール サイズ 100) は 700 ミリ秒です。したがって、スレッド プール サイズが 4 の場合、所要時間は短くなります。

スレッドの数が多い != より多くのタスクを同時に処理できるのはなぜですか?

最初の理由は、各スレッドに独自のスタックとリソース要件があることです。スレッドの数を増やすと、最終的にはメモリ不足または CPU リソースの状態が発生します。

2 番目の理由は、オペレーティング システムがスレッドをスケジュールする必要があることです。スレッドが多すぎると、OS はスレッド間の切り替え (コンテキスト切り替え) に多くの時間を費やし、オーバーヘッドが追加され、パフォーマンスが向上するどころかパフォーマンスが低下します。

スケーラビリティと高いパフォーマンスを実現するためにスレッド プール サイズを増やすことではなく、クラスタリングなどの適切なアーキテクチャを使用し、タスクの性質 (I/O 対 CPU バウンド) を理解することが重要であると言えます。 ) と Node.js のイベント駆動モデルがどのように機能するか。

お読みいただきありがとうございます。

以上がノードJS内部の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
JavaScriptとWeb:コア機能とユースケースJavaScriptとWeb:コア機能とユースケースApr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンの理解:実装の詳細JavaScriptエンジンの理解:実装の詳細Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Python vs. JavaScript:学習曲線と使いやすさPython vs. JavaScript:学習曲線と使いやすさApr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Python vs. JavaScript:コミュニティ、ライブラリ、リソースPython vs. JavaScript:コミュニティ、ライブラリ、リソースApr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、