SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

SOS_WORK_DISPATCHER と SOS_WORKER の比較についてのメモ

leave a comment

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
sqldk.dll!SOS_Task::PreWait+0x14b
sqldk.dll!WaitableBase::Wait+0x160
sqldk.dll!WorkDispatcher::DequeueTask+0x502
sqldk.dll!SOS_Scheduler::ProcessTasks+0x233
sqldk.dll!SchedulerManager::WorkerEntryPoint+0x2a1
sqldk.dll!SystemThreadDispatcher::ProcessWorker+0x42a
sqldk.dll!SchedulerManager::ThreadEntryPoint+0x406
KERNEL32.DLL!BaseThreadInitThunk+0x10
ntdll.dll!RtlUserThreadStart+0x2b

 
End

sqldk.dll!XeSosPkg::wait_info::Publish+0x1b2
sqldk.dll!SOS_Scheduler::UpdateWaitTimeStats+0x2f0
sqldk.dll!SOS_Task::PostWait+0x6f
sqldk.dll!WaitableBase::Wait+0x178
sqldk.dll!WorkDispatcher::DequeueTask+0x502
sqldk.dll!SOS_Scheduler::ProcessTasks+0x233
sqldk.dll!SchedulerManager::WorkerEntryPoint+0x2a1
sqldk.dll!SystemThreadDispatcher::ProcessWorker+0x42a
sqldk.dll!SchedulerManager::ThreadEntryPoint+0x406
KERNEL32.DLL!BaseThreadInitThunk+0x10
ntdll.dll!RtlUserThreadStart+0x2b

sqldk.dll!XeSosPkg::wait_info::Publish+0x1b2
sqldk.dll!SOS_Scheduler::UpdateWaitTimeStats+0x2f0


sqldk.dll!WorkDispatcher::DequeueTask+0x33d
sqldk.dll!SOS_Scheduler::ProcessTasks+0x233
sqldk.dll!SchedulerManager::WorkerEntryPoint+0x2a1
sqldk.dll!SystemThreadDispatcher::ProcessWorker+0x42a
sqldk.dll!SchedulerManager::ThreadEntryPoint+0x406
KERNEL32.DLL!BaseThreadInitThunk+0x10
ntdll.dll!RtlUserThreadStart+0x2b

 

コールスタックとしては似たような内容となっており、「sqldk.dll!WorkDispatcher::DequeueTask」が呼び出されています

[sqldk.dll!WorkDispatcher::DequeueTask] 内のオフセットが異なっているので、タスクを実行するためにワーカーをデキューする際の処理には違いがあるようです。

新規ワーカーの割り当てか既存ワーカーの再利用の違い等があるのかもしれませんね。

 

待機事象が発生するタイミングの比較

次に、SOS_WORK_DISPATCHER と、SOS_WORKER が発生タイミングを比較してみます。

SOS_WORKER については、上述のとおり、End の情報しか取得できていないのですが、取得できた情報では各イベントは次のような順序で実行が行われていました。

image

冒頭に記載した記事では [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
sqldk.dll!WorkDispatcher::EnqueueTask+0x22d
sqldk.dll!WorkDispatcher::CreateAndEnqueueTask+0x1e9
sqldk.dll!SOS_Node::EnqueueTaskDirectInternal+0x26a
sqllang.dll!CNetConnection::EnqueuePacket+0x2e5
sqllang.dll!TDSSNIClient::ReadHandler+0x482
sqllang.dll!SNIReadDone+0x138
sqldk.dll!SOS_Node::ListenOnIOCompletionPort+0x2cc
sqldk.dll!SOS_Task::Param::Execute+0x232
sqldk.dll!SOS_Scheduler::RunTask+0xbf
sqldk.dll!SOS_Scheduler::ProcessTasks+0x39d
sqldk.dll!SchedulerManager::WorkerEntryPoint+0x2a1
sqldk.dll!SystemThreadDispatcher::ProcessWorker+0x42a
sqldk.dll!SchedulerManager::ThreadEntryPoint+0x406
KERNEL32.DLL!BaseThreadInitThunk+0x10
ntdll.dll!RtlUserThreadStart+0x2b

 

Task Enqueued は、TDSSNIClient (SNI:SQL Network Interface or Server Name Indication) からの要求をトリガーとして実行されているようですね。

Share

Written by Masayuki.Ozawa

12月 15th, 2022 at 10:13 am

Posted in SQL Server

Tagged with

Leave a Reply