Skip to content

Commit 5cff578

Browse files
authored
Merge pull request BrentOzarULTD#3918 from BrentOzarULTD/copilot/add-warning-for-approaching-max-thread-time
sp_BlitzFirst: add Priority 1 “High Thread Time” warning near CPU thread-time saturation
2 parents 937e05a + 5aa4d5c commit 5cff578

2 files changed

Lines changed: 67 additions & 2 deletions

File tree

Documentation/sp_BlitzFirst_Checks_by_Priority.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ Before adding a new check, make sure to add a Github issue for it first, and hav
66

77
If you want to change anything about a check - the priority, finding, URL, or ID - open a Github issue first. The relevant scripts have to be updated too.
88

9-
CURRENT HIGH CHECKID: 53
10-
If you want to add a new check, start at 54.
9+
CURRENT HIGH CHECKID: 54
10+
If you want to add a new check, start at 55.
1111

1212
| Priority | FindingsGroup | Finding | URL | CheckID |
1313
|----------|---------------------------------|---------------------------------------|-------------------------------------------------|----------|
@@ -17,6 +17,7 @@ If you want to add a new check, start at 54.
1717
| 1 | Maintenance Tasks Running | Backup Running | https://www.brentozar.com/askbrent/backups | 1 |
1818
| 1 | Maintenance Tasks Running | DBCC CHECK* Running | https://www.brentozar.com/askbrent/dbcc | 2 |
1919
| 1 | Maintenance Tasks Running | Restore Running | https://www.brentozar.com/askbrent/backups | 3 |
20+
| 1 | Potential Upcoming Problems | High Thread Time | https://www.brentozar.com/go/threadtime | 54 |
2021
| 1 | Query Problems | Long-Running Query Blocking Others | https://www.brentozar.com/go/blocking | 5 |
2122
| 1 | Query Problems | Query Rolling Back | https://www.brentozar.com/go/rollback | 9 |
2223
| 1 | Query Problems | Sleeping Query with Open Transactions | https://www.brentozar.com/go/sleeping | 8 |

sp_BlitzFirst.sql

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3625,6 +3625,70 @@ If one of them is a lead blocker, consider killing that query.'' AS HowToStopit,
36253625
SELECT CAST((wd2.thread_time_ms - wd1.thread_time_ms) / 1000 AS INT) AS TotalThreadTimeSeconds
36263626
) AS c;
36273627

3628+
/* Potential Upcoming Problems - High Thread Time - CheckID 54 */
3629+
IF @Seconds > 0
3630+
BEGIN
3631+
IF (@Debug = 1)
3632+
BEGIN
3633+
RAISERROR('Running CheckID 54',10,1) WITH NOWAIT;
3634+
END
3635+
3636+
;WITH max_batch AS (
3637+
SELECT MAX(SampleTime) AS SampleTime
3638+
FROM #WaitStats
3639+
),
3640+
thread_time AS (
3641+
SELECT TOP 1
3642+
wd1.SampleTime AS StartSampleTime,
3643+
wd2.SampleTime AS EndSampleTime,
3644+
CAST((wd2.thread_time_ms - wd1.thread_time_ms) / 1000.0 AS DECIMAL(18,1)) AS TotalThreadTimeSeconds
3645+
FROM max_batch b
3646+
JOIN #WaitStats wd2 ON wd2.SampleTime = b.SampleTime
3647+
JOIN #WaitStats wd1 ON wd1.wait_type = wd2.wait_type AND wd2.SampleTime > wd1.SampleTime
3648+
ORDER BY wd2.SampleTime DESC, wd1.SampleTime ASC
3649+
),
3650+
non_idle_waits AS (
3651+
SELECT CAST(SUM((wNow.wait_time_ms - COALESCE(wBase.wait_time_ms, 0)) / 1000.0) AS DECIMAL(18,1)) AS NonIdleWaitSeconds
3652+
FROM #WaitStats wNow
3653+
LEFT OUTER JOIN #WaitStats wBase ON wNow.wait_type = wBase.wait_type AND wNow.SampleTime > wBase.SampleTime
3654+
LEFT OUTER JOIN ##WaitCategories wc ON wc.WaitType = wNow.wait_type
3655+
WHERE wNow.Pass = 2
3656+
AND (wc.WaitCategory IS NULL OR wc.WaitCategory <> 'Idle')
3657+
),
3658+
cores AS (
3659+
SELECT SUM(1) AS cpu_count
3660+
FROM sys.dm_os_schedulers
3661+
WHERE status = 'VISIBLE ONLINE'
3662+
AND is_online = 1
3663+
)
3664+
INSERT INTO #BlitzFirstResults (CheckID, Priority, FindingsGroup, Finding, URL, Details, DetailsInt)
3665+
SELECT
3666+
54 AS CheckID,
3667+
1 AS Priority,
3668+
'Potential Upcoming Problems' AS FindingsGroup,
3669+
'High Thread Time' AS Finding,
3670+
'https://www.brentozar.com/go/threadtime' AS URL,
3671+
CAST(CAST(c.CpuTimeUsedSeconds AS DECIMAL(18,1)) AS NVARCHAR(30))
3672+
+ ' CPU time used out of a theoretical max of '
3673+
+ CAST(CAST(t.TheoreticalMaxCpuSeconds AS DECIMAL(18,1)) AS NVARCHAR(30))
3674+
+ ' seconds. As CPU time used starts to approach 80-90%, the server can quickly become unresponsive. Be prepared to troubleshoot with the DAC.' AS Details,
3675+
CAST(c.CpuTimeUsedSeconds AS INT) AS DetailsInt
3676+
FROM thread_time tt
3677+
CROSS JOIN non_idle_waits niw
3678+
CROSS JOIN cores i
3679+
CROSS APPLY (
3680+
SELECT CAST(i.cpu_count * DATEDIFF(ss, tt.StartSampleTime, tt.EndSampleTime) AS DECIMAL(18,1)) AS TheoreticalMaxCpuSeconds
3681+
) t
3682+
CROSS APPLY (
3683+
SELECT CAST(CASE
3684+
WHEN tt.TotalThreadTimeSeconds - COALESCE(niw.NonIdleWaitSeconds, 0) < 0 THEN 0
3685+
ELSE tt.TotalThreadTimeSeconds - COALESCE(niw.NonIdleWaitSeconds, 0)
3686+
END AS DECIMAL(18,1)) AS CpuTimeUsedSeconds
3687+
) c
3688+
WHERE t.TheoreticalMaxCpuSeconds > 0
3689+
AND c.CpuTimeUsedSeconds >= (t.TheoreticalMaxCpuSeconds * 0.5);
3690+
END;
3691+
36283692
/* Server Info - Batch Requests per Sec - CheckID 19 */
36293693
IF (@Debug = 1)
36303694
BEGIN

0 commit comments

Comments
 (0)