Logo

dev-resources.site

for different kinds of informations.

Web エンジニアリング基礎 -- Part01 同期 or 非同期の処理のコールスタックとタスクキュー

Published at
12/31/2022
Categories
webdev
beginners
promise
japanese
Author
kaede_io
Categories
4 categories in total
webdev
open
beginners
open
promise
open
japanese
open
Author
8 person written this
kaede_io
open
Web エンジニアリング基礎 -- Part01 同期 or 非同期の処理のコールスタックとタスクキュー

why

http://www.02.246.ne.jp/~torutk/seway/dreyfus.html

自分がドレイファスモデルの初心者レベルであることを自覚した。

中級のこれらの項目が以下の理由で満たせていなかったからである。

1: 独力で仕事に当たれるが問題処理に手こずる

  • RDB の設計
  • ドキュメンテーション

そもそもこれらの項目の経験がほぼないため。

2: ほんの少しだけ決まったルールから離れられる

  • リカバリー、障害対応の点において、自分が普段開発していないプロジェクトで全然できなかった。
  • 実装や運用の点において、よく作るor使う処理はできるが「他と比べて〜だからこの処理にしている」と説明できたり、よりメンテナンス性の高い処理に自分から改善したりはできなかった。

そのため、RDB の設計の書籍を読んで実際に psql で作ってみるのと
Web の基礎を改めて一通り学習することにする。

基本情報よりも実務に近い記事があるので、それで学習する。

https://zenn.dev/rio_dev/articles/c0da74ae28bdcd


フロント

https://zenn.dev/rio_dev/articles/c0da74ae28bdcd#%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89

同期とコールスタック

普通の関数は順次に呼び出されて、コールスタックというところに追加されるらしい。コールスタックが実行できるところだと解釈する。

通常の関数だと

funcA()

funcB()

funcC()

とべた書きされていた場合

https://qiita.com/sho_U/items/f07a4f3e7760a9729f10#%E3%82%B3%E3%83%BC%E3%83%AB%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%AD%E3%83%A5%E3%83%BC%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%83%AB%E3%83%BC%E3%83%97

この記事のように

funcA がコールスタックに入る
funcA が実行されて処理が終わる
fucnA がコールスタックから出される
funcB が積まれる...

と進んでいく

Image description

一つ一つ、実行後の場所に送られて、その後コールスタックに新しい関数が積まれて... と進んでいくと解釈した。


依存性のある同期関数とコールスタック

funcA() {
  funcB() 
}
funcB() {
}
Enter fullscreen mode Exit fullscreen mode

このような別の関数を呼び出す依存性のある構成になっている場合は
まず funcA が先に積まれる。

Image description

しかし funcA が終わる前に funcB が呼び出される。

Image description

なので コールスタックに funcB も積まれる。

Image description

そして funcB が先に処理されて出される。

Image description

最後に funcA が出される。

このように、コールスタックに積んだ関数に依存性がある場合はスタックに順に積み重ねられていき、後から重ねられた関数から処理が終わって外に出されていく。

デバックモードでよく確認した動きだ。
関数Aの呼び出している関数Bに入って、終わってから呼び出し先の関数Aの関数Bを呼び出した行の次の処理に移って...と。

一見効率が悪く、非同期にしてしまえと思うが、


const userID = getUser()
const groupID = getUserGroup(userId)

return userTimeLine(groupId)
Enter fullscreen mode Exit fullscreen mode

このように、前の処理で取ってきた情報がないと、後ろの処理ができない場合には必要になる。

なので全部非同期にすることはできない。


非同期処理

https://qiita.com/sho_U/items/f07a4f3e7760a9729f10#%E3%82%B3%E3%83%BC%E3%83%AB%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%AD%E3%83%A5%E3%83%BC%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%83%AB%E3%83%BC%E3%83%97

この sho_U さんの記事を引き続き参考にする

function a() {
  console.log("a")
}
function b() {
  setTimeout(bc,0)
}
function bc() {
  console.log("bc")
}
function c() {
  console.log("c")
}

a();
b();
c();
Enter fullscreen mode Exit fullscreen mode

このように

同期関数の a
非同期関数の b
b に呼び出される bc
同期関数の c

とコードを書いて

https://www.jsv9000.app/

このサイトで実行する。

Image description

すると、bc は呼ばれたタイミングでタスクキューに入る。
コールスタックには入らない。

Image description

そして、キューに入った bc は放置されて

Image description

コールスタックに入っている b が処理されてコールスタックから出され

Image description

まだタスクキューに入っている bc は放置されて
次に c がコールスタックに入り、処理されてコールスタックから出される。

Image description

最後に、コールスタックに入ろうとする関数がなくなったので
ようやく、bc がタスクキューからコールスタックに入り、

処理されてコールスタックから出される。

非同期まとめ

今回の bc のように、非同期で呼び出された関数は
優先順位の低いものとして「タスクキュー」に入り
優先順位の高い「コールスタック」に入る同期の関数が全てなくなった後に
「コールスタック」に最後に入り、処理される。


まとめ

1. 普通の関数、つまり同期関数で依存がない場合

関数 A が呼ばれてコールスタックに入って処理されて出る
次に関数 B が呼ばれてコールスタックに入って処理されて出る

と、順繰りにコールスタックに入れて終わって出してを繰り返す。

2. 同期関数で依存がある場合

funcA() {
  funcB() 
}
funcB() {
}
Enter fullscreen mode Exit fullscreen mode

関数 A が依存する 関数 B を呼び出し
コールスタックの A の上に B が積まれる。
B が処理されてコールスタックを出る。
B が処理されたことで A が処理されたことになり
A がコールスタックを出る

この流れになる。

3. 非同期関数の場合

function b() {
  setTimeout(bc,0)
}
function bc() {
  console.log("bc")
}
function c() {
  console.log("c")
}
Enter fullscreen mode Exit fullscreen mode

関数 b がコールスタックに詰まれる
bc を呼び出す。
bc がタスクキューに詰まれる
b が終わったものとしてコールスタックから出される。
c がコールスタックに詰まれる
c が処理され、コールスタックから出される
bc がコールスタックに詰まれる
bc が処理され、コールスタックか出される。

このように、非同期の関数が優先順位の低いタスクキューという場所に置かれる。そしてコールスタックに直接入れる同期の後に処理される形になる。

松屋の店員の休憩の時の賄いと同じですね。お客さんの食事が常に先に詰まれるので。

japanese Article's
30 articles in total
Favicon
re:Invent 2023に参加してから1年たってみて
Favicon
re:Invent 2023 day1
Favicon
IIS環境でのパス制御を考える
Favicon
ホストベースルーティングを活用してALBを集約した際のデメリットを検討する
Favicon
AWS Summit Japan 2024体験記
Favicon
AWS Step Functionsに入門する
Favicon
AWS Community Buildersになって変わったこと
Favicon
GenAI Use Cases JPを試してみた
Favicon
RDS for MySQLでスロークエリログの出力を有効化する
Favicon
AWS Fargateを利用した時刻固定したシステムテストの方法について
Favicon
ランブックを活用したWindows Serverインプレースアップグレードのススメ
Favicon
DocumentDBでマルチバイト検索を実現する場合の留意事項について
Favicon
JAWS DAYS 2024参加体験記
Favicon
OCR + SwiftUI + Japanese. Quite a training project! 😅
Favicon
Lambdaで.NET 7のカスタムランタイムを実行する
Favicon
$0.005 per In-use public IPv4 address per hour の明細が高額になる場合の対応を考える
Favicon
Ryuu - a Japanese dragon
Favicon
事務局長を2年やってみて感じたこと
Favicon
Mechanically Detecting Accessibility Violations
Favicon
Hello back! Sharing some projects
Favicon
Making Font Loading More Efficient with React Content Font
Favicon
How to Avoid Japanese Characters in Your Code!
Favicon
AI 基礎 Part 00 -- stable-diffusion / ChilloutMix を使って日本人美女の画像を作る
Favicon
Next 基礎 Part 02 -- axios で API を叩けるようにする。No 'Access-Control-Allow-Origin' エラーの解決。
Favicon
Next 基礎 Part 01 -- プロジェクト作成
Favicon
AWS 基礎 Part 0 -- EC2 などの AWS サービスと用途の整理
Favicon
Android 基礎 -- Part 00 Android Studio のインストールと Hello World
Favicon
Web エンジニアリング基礎 -- Part02 TS のメリットとブラウザのレンダリング詳細
Favicon
Web エンジニアリング基礎 -- Part01 同期 or 非同期の処理のコールスタックとタスクキュー
Favicon
Ubuntu Settings -- US キーで Mac のように ctrl space の英かな切り替えと ctrl h などでの削除ができるようにする。

Featured ones: