SOS_WORK_DISPATCHER については、What is the SOS_WORK_DISPATCHER Wait Type? で解説が行われていますが、SOS_WORKER との比較を把握しておきたかったのでメモとして。
SOS_WORKER とはどのような待機事象が該当するのか
待機事象を確認するための方法としては sys.dm_os_wait_stats という DMV があります。この情報を拡張イベントから確認する場合は、wait_info というイベントから確認を行います。
DMV で確認できる待機場としては、 [SOS_WORKER] は存在していません。そして、拡張イベントから待機事象を確認する場合は、[THREADPOOL] は存在していません。
拡張イベントで確認できる SOS_WORKER という待機事象は DMV で確認できるどのような待機事象となるのでしょうか?
拡張イベントの wait_type と DMV の wait_type が異なるものはいくつかあるのですが、それについては、Mapping wait types in dm_os_wait_stats to Extended Events で解説が行われています。
拡張イベントの [SOS_WORKER] は、DMV 上は [THREADPOOL] の待機事象が該当していることが上記の記事で記載されています。
そのたm、え拡張イベントで SOS_WORKER が発生している場合は、DMV を使用した調査の THREADPOOL が発生していると考える必要があります。
拡張イベントで SOS_WORKER の情報が確認できた = DMV の THREADPOOL が発生しており、ワーカースレッドの新規生成の問題解決のアプローチと同様の対応が必要になると判断ができるのではないでしょうか。
コールスタックの比較
それでは、SOS_WORK_DISPATCHER と SOS_WORKER のコールスタックを比較してみます。SOS_WORKER は Begin が取れなかったため End のみ記載しています。
拡張イベントからコールスタックを取得しているので、先頭の publish は本来の待機情報としては発生しないもの (publish は拡張イベントで取得するように設定したため追加されている呼び出し) となりますが、どこまでが拡張イベントで取得できている情報なのかを判断できるようにするため、記載しています。
opccode | SOS_WORK_DISPATCHER | SOS_WORKER |
Begin |
sqldk.dll!XeSosPkg::wait_info::Publish+0x1b2 |
|
End |
sqldk.dll!XeSosPkg::wait_info::Publish+0x1b2 |
sqldk.dll!XeSosPkg::wait_info::Publish+0x1b2 |
コールスタックとしては似たような内容となっており、「sqldk.dll!WorkDispatcher::DequeueTask」が呼び出されています
[sqldk.dll!WorkDispatcher::DequeueTask] 内のオフセットが異なっているので、タスクを実行するためにワーカーをデキューする際の処理には違いがあるようです。
新規ワーカーの割り当てか既存ワーカーの再利用の違い等があるのかもしれませんね。
待機事象が発生するタイミングの比較
次に、SOS_WORK_DISPATCHER と、SOS_WORKER が発生タイミングを比較してみます。
SOS_WORKER については、上述のとおり、End の情報しか取得できていないのですが、取得できた情報では各イベントは次のような順序で実行が行われていました。
冒頭に記載した記事では [SOS_WORK_DISPATCHER] は、ワーカーを使用するタスクが存在しない場合に発生し、ワーカーにタスクが割り当てられた場合に、待機が解除されるという解説が行われている理解でいます。
次の処理のなっていることは手元の環境でも確認ができました。
- task_started
- task_completed
- SOS_WORK_DISPATCHER: Start
- task_enqueued
- このタスクのキューへの入力は今まで実行されていたタスクとは別の Activity ID としてトラッキングされている
- SOS_WORK_DISPATCHER: end
[SOS_WORKER] については、次の順序となっていました。
- task_started
- task_completed
- SOS_WORKER: END
この場合は、Task Enqueued / Wait: End となっていないようです。すべてのイベントを取得することができていないので、いくつかのイベントをとり逃している可能性はありますが、新規に作成したワーカーを使用するか既存のワーカーを使用するかで処理の違いがあるのかもしれませんね。
task_enqueued のコールスタック
今回は深く確認していませんが、task_enqueued については次のようなスタックとなっているようです。
sqldk.dll!XeSosPkg::task_enqueued::Publish+0x1b2 |
Task Enqueued は、TDSSNIClient (SNI:SQL Network Interface or Server Name Indication) からの要求をトリガーとして実行されているようですね。