将来を見据えたウェブ・アプリケーションの構築:The Codestのエキスパート・チームによる洞察
The Codestが、最先端技術を駆使してスケーラブルでインタラクティブなウェブアプリケーションを作成し、あらゆるプラットフォームでシームレスなユーザー体験を提供することにどのように秀でているかをご覧ください。The Codestの専門知識がどのようにデジタルトランスフォーメーションとビジネス...
JavaScriptはシングルスレッド言語であると同時に、ノンブロッキング、非同期、並行処理も可能です。この記事では、その仕組みを説明する。
JavaScript はコンパイル言語ではなくインタプリタ言語である。つまり、JSを変換するインタプリタが必要なのだ。 コード をマシンコードに変換する。インタープリター(エンジンとして知られている)にはいくつかの種類がある。最もポピュラーなブラウザ・エンジンは、V8(Chrome)、Quantum(Firefox)、WebKit(Safari)だ。ちなみに、V8は一般的なブラウザ以外のランタイムにも使われている、 Node.js.
各エンジンには、メモリー・ヒープ、コール・スタック、イベント・ループ、コールバック・キュー、HTTPリクエスト、タイマー、イベントなどのWebAPIが含まれ、JSコードをより速く安全に解釈するために、すべてが独自の方法で実装されている。
基本的なJSランタイム・アーキテクチャ著者アレックス・ズラトコフ
シングルスレッド言語とは、単一のコールスタックと単一のメモリヒープを持つ言語のことである。つまり、一度にひとつのことだけを実行する。
A スタック
はメモリの連続領域で、実行される関数ごとにローカルコンテキストが割り当てられる。
A ヒープ
はもっと大きな領域で、動的に割り当てられたものすべてを格納する。
A コールスタック
はデータ構造で、基本的にプログラムのどこにいるかを記録する。
簡単なコードを書いて、コールスタック上で何が起こっているかを追跡してみよう。
見ての通り、関数はスタックに追加され、実行され、後で削除される。いわゆるLIFO方式(Last In, First Out)である。コールスタックの各エントリーは スタックフレーム
.
コールスタックの知識は、エラー・スタック・トレースを読むのに便利である。一般的に、エラーの正確な原因は最初の行の一番上にあるが、コードの実行順序は下から上になる。
で通知される一般的なエラーに対処できることもある。 コールスタックの最大サイズを超えた
.再帰を使ってこれを得るのは簡単だ:
関数 foo() {
foo()
}
foo()
ブラウザや端末がフリーズしてしまうのだ。各ブラウザは、そのバージョンが異なっていても、コールスタックサイズの上限が異なっている。大半の場合、それらは十分なものであり、問題は別の場所を探すべきである。
JSスレッドをブロックする例を挙げよう。を読んでみよう。 フー
ファイルと バー
を使用している。 ノード.js同期関数 リードファイル同期
.
これはループGIFである。ご覧のように、JSエンジンは リードファイル同期
が完成する。しかし、それは実現しない。 フー
ファイルでは、2番目の関数は決して呼び出されない。
しかし、JSはノンブロッキングでマルチスレッドのように振る舞うこともできる。つまり、APIコールのレスポンスやI/Oイベントなどを待たずに、コードの実行を続けることができる。これが可能なのは、C++(Chrome)やRust(Firefox)のような本物のマルチスレッド言語を(アンダー・ザ・フードで)使用するJSエンジンのおかげだ。これらのエンジンは、ブラウザのフードの下にあるWeb APIや、例えばNode.jsの下にあるI/O APIを提供してくれる。Node.jsのI/O API。
上のGIFでは、最初の関数がコールスタックにプッシュされているのがわかる。 こんにちは
は即座にコンソールで実行される。
そして セットタイムアウト
関数を呼び出します。コールスタックに移動し、非同期コールバックの フー
関数はWebApiのキューに送られ、そこで3秒後に起こるように設定された呼び出しを待ちます。
その間、プログラムはコードを続け、次のようになる。 こんにちは。
コンソールで。
呼び出された後、WebAPIキュー内の各関数は コールバックキュー
.コールスタックが空になるまで関数が待機する場所である。空になると、関数は1つずつそこに移される。
というわけで セットタイムアウト
タイマーがカウントダウンを終了すると フー
関数はコールバックキューに行き、コールスタックが利用可能になるまで待ち、そこで実行され、次のようになる。 非同期コールバックからこんにちは
コンソールで。
問題は、コールスタックが空であることをランタイムはどうやって知るのか、そしてコールバック・キューのイベントはどうやって呼び出されるのか、ということだ。イベント・ループがある。これはJSエンジンの一部である。このプロセスは、コールスタックが空かどうかを常にチェックし、空であれば、コールバック・キューに呼び出し待ちのイベントがあるかどうかを監視する。
それが舞台裏のマジックなんだ!
コンカレンシー
とは、複数のタスクを同時に実行することを意味するが、同時ではない。例えば、2つのタスクが重複した時間帯に実行される。
パラレリズム
とは、2つ以上のタスクを同時に実行すること、例えば複数の計算を同時に実行することを意味する。
スレッド
は、互いに独立して実行可能なコード実行のシーケンスである。
プロセス
は実行中のプログラムのインスタンスである。プログラムは複数のプロセスを持つことができる。
で 同期
プログラミングでは、タスクは次々に実行される。各タスクは前のタスクが完了するのを待ち、そのとき初めて実行される。
で 非同期
プログラミングでは、あるタスクが実行されると、前のタスクの完了を待たずに別のタスクに切り替えることができる。
シングルスレッドとの同期
:タスクは次々に実行される。各タスクは前のタスクが実行されるのを待つ。
複数スレッドによる同期
:タスクは異なるスレッドで実行されるが、他のスレッドで実行中のタスクを待つ。
単一スレッドによる非同期
:タスクは、他のタスクの終了を待たずに実行を開始する。一度に実行できるタスクは1つだけ。
複数スレッドによる非同期
:タスクは他のタスクの完了を待つことなく異なるスレッドで実行され、独立して実行を終了する。
JSエンジンがフードの下でどのように動作するかを考えると、JSは非同期でシングルスレッドのインタプリタ型言語に分類できる。インタプリタ型」という言葉が非常に重要なのは、この言語が常にランタイムに依存し、マルチスレッドを内蔵したコンパイル言語ほど高速ではないということを意味しているからだ。
特筆すべきは、Node.jsは、各スレッドを個別のプロセスとして起動させれば、本当のマルチスレッドを実現できることだ。そのためのライブラリもありますが、Node.jsには ワーカースレッド.
すべてのイベントループGIFは ルーペ フィリップ・ロバーツが作成したアプリケーションで、非同期シナリオをテストすることができる。
続きを読む