4242MAX_BYTES = 8 * 1024 * 1024
4343MAX_COMMENT_CHARS = 60000
4444MAX_DIAGNOSTIC_ROWS = 20
45+ MAX_FINGERPRINT_TASKS = 4
4546MARKER = "<!-- mssql-python-profiler-ci -->"
4647THRESHOLD = 0.20
4748MIN_DELTA_MS = 1.0
@@ -376,75 +377,100 @@ def render(reports, head, build_id, issues=()):
376377 ]
377378 missing = len (LEGS ) - len (completed )
378379
379- if len (regressions ) == 1 :
380- leg , row = regressions [0 ]
381- opening = (
382- f"This PR consistently slows { TASK_NAMES [row ['name' ]].lower ()} on "
383- f"{ environment_name (leg )} by { row ['change_pct' ]:.1f} %."
384- )
385- elif regressions :
380+ highlighted = [
381+ (leg , row ) for leg , (_ , rows ) in completed .items () for row in rows if row ["status" ] != "ok"
382+ ]
383+ if regressions :
386384 tasks = len ({row ["name" ] for _ , row in regressions })
387385 environments = len ({leg for leg , _ in regressions })
388386 opening = (
389- f"This PR has { len ( regressions ) } consistent slowdown signals across "
390- f"{ tasks } database tasks and { environments } environments ."
387+ f"{ tasks } database task { 's' if tasks != 1 else '' } consistently slowed down across "
388+ f"{ environments } measured environment { 's' if environments != 1 else '' } ."
391389 )
390+ verdict = "⚠️ Performance regression detected"
392391 elif noisy :
393- if len (noisy ) == 1 :
394- leg , row = noisy [0 ]
395- opening = (
396- f"{ TASK_NAMES [row ['name' ]]} was slower on { environment_name (leg )} , "
397- "but the repeated comparisons were inconsistent."
398- )
399- else :
400- tasks = len ({row ["name" ] for _ , row in noisy })
401- environments = len ({leg for leg , _ in noisy })
402- opening = (
403- f"No consistent slowdowns detected. { len (noisy )} inconsistent comparisons "
404- f"need review across { tasks } database tasks and { environments } environments."
405- )
406- elif len (improvements ) == 1 :
407- leg , row = improvements [0 ]
392+ tasks = len ({row ["name" ] for _ , row in noisy })
393+ environments = len ({leg for leg , _ in noisy })
408394 opening = (
409- f"This PR consistently makes { TASK_NAMES [row ['name' ]].lower ()} faster on "
410- f"{ environment_name (leg )} by { abs (row ['change_pct' ]):.1f} %."
395+ f"{ tasks } database task{ 's' if tasks != 1 else '' } produced inconsistent slowdown "
396+ f"signals across { environments } measured environment"
397+ f"{ 's' if environments != 1 else '' } ."
411398 )
399+ verdict = "🔍 Performance needs review"
412400 elif improvements :
413401 tasks = len ({row ["name" ] for _ , row in improvements })
414402 environments = len ({leg for leg , _ in improvements })
415403 opening = (
416- f"This PR has { len (improvements )} consistent improvement signals across "
417- f"{ tasks } database tasks and { environments } environments."
404+ f"{ tasks } database task{ 's' if tasks != 1 else '' } consistently improved across "
405+ f"{ environments } measured environment{ 's' if environments != 1 else '' } . "
406+ "No consistent slowdowns were detected."
418407 )
408+ verdict = "✅ Performance improved"
419409 elif not completed :
420410 opening = (
421411 "Performance could not be assessed because no environment produced a complete result."
422412 )
413+ verdict = "⛔ Performance unavailable"
423414 elif not missing :
424415 opening = f"No consistent slowdowns detected across all { len (LEGS )} environments."
416+ verdict = "✅ No regression detected"
425417 else :
426418 completed_label = "environment" if len (completed ) == 1 else "environments"
427419 missing_label = "environment" if missing == 1 else "environments"
428420 opening = (
429421 f"No consistent slowdowns in the { len (completed )} completed { completed_label } . "
430422 f"No result is available for { missing } { missing_label } ."
431423 )
424+ verdict = "✅ No regression detected"
432425
433- lines = [MARKER , "## PR Performance Report" , "" , f"**{ opening } **" , "" ]
434- highlighted = regressions or noisy or improvements
435- if highlighted :
436- if not regressions and noisy :
437- lines += ["Inconsistent slowdowns to review:" , "" ]
426+ improvement_tasks = len ({row ["name" ] for _ , row in improvements })
427+ regression_tasks = len ({row ["name" ] for _ , row in regressions })
428+ lines = [
429+ MARKER ,
430+ "## PR Performance Report" ,
431+ "" ,
432+ f"### { verdict } " ,
433+ "" ,
434+ f"**{ opening } **" ,
435+ "" ,
436+ f"<kbd>{ improvement_tasks } IMPROVEMENT"
437+ f"{ 'S' if improvement_tasks != 1 else '' } </kbd> "
438+ f"<kbd>{ regression_tasks } SLOWDOWN"
439+ f"{ 'S' if regression_tasks != 1 else '' } </kbd> "
440+ f"<kbd>{ len (completed )} /{ len (LEGS )} ENVIRONMENTS</kbd>" ,
441+ "" ,
442+ ]
443+ if noisy :
444+ noisy_tasks = len ({row ["name" ] for _ , row in noisy })
438445 lines += [
439- "| Environment | Affected task | Before | After | Change | " ,
440- "|---|---|---:|---:|---:| " ,
446+ f"<kbd> { noisy_tasks } INCONSISTENT SLOWDOWN" f" { 'S' if noisy_tasks != 1 else '' } </kbd> " ,
447+ "" ,
441448 ]
442- for leg , row in highlighted :
443- lines .append (
444- f"| { environment_name (leg )} | { TASK_NAMES [row ['name' ]]} | "
445- f"{ row ['base_ms' ]:.3f} ms | { row ['candidate_ms' ]:.3f} ms | "
446- f"{ row ['change_pct' ]:+.1f} % |"
447- )
449+ affected_tasks = [name for name in CASES if any (row ["name" ] == name for _ , row in highlighted )]
450+ if highlighted and len (affected_tasks ) <= MAX_FINGERPRINT_TASKS :
451+ affected_legs = [leg for leg in LEGS if any (item_leg == leg for item_leg , _ in highlighted )]
452+ by_signal = {(leg , row ["name" ]): row for leg , row in highlighted }
453+ lines += [
454+ "### Signal fingerprint" ,
455+ "" ,
456+ "| Database task | "
457+ + " | " .join (environment_name (leg ) for leg in affected_legs )
458+ + " |" ,
459+ "|---|" + "|" .join ("---:" for _ in affected_legs ) + "|" ,
460+ ]
461+ for name in affected_tasks :
462+ cells = []
463+ for leg in affected_legs :
464+ row = by_signal .get ((leg , name ))
465+ if row is None :
466+ cells .append ("No signal" )
467+ elif row ["status" ] == "improvement" :
468+ cells .append (f"**{ abs (row ['change_pct' ]):.1f} % faster**" )
469+ elif row ["status" ] == "regression" :
470+ cells .append (f"**{ abs (row ['change_pct' ]):.1f} % slower**" )
471+ else :
472+ cells .append (f"**{ abs (row ['change_pct' ]):.1f} % inconsistent**" )
473+ lines .append (f"| { escape (TASK_NAMES [name ])} | " + " | " .join (cells ) + " |" )
448474 lines .append ("" )
449475 if regressions :
450476 lines .append (
@@ -461,24 +487,37 @@ def render(reports, head, build_id, issues=()):
461487 lines += [
462488 f"**Coverage:** { len (completed )} of { len (LEGS )} environments completed. "
463489 "Advisory result; does not block merging." ,
464- "" ,
465- "| Environment | Status |" ,
466- "|---|---|" ,
467490 ]
468- for leg in LEGS :
469- report = by_leg .get (leg )
470- status = (
471- "Completed"
472- if leg in completed
473- else f"No result available ({ escape (issue_reason (leg , issues ))} )"
474- )
475- lines .append (f"| { environment_name (leg )} | { status } |" )
491+ unavailable_legs = [
492+ f"{ environment_name (leg )} ({ escape (issue_reason (leg , issues ))} )"
493+ for leg in LEGS
494+ if leg not in completed
495+ ]
496+ if unavailable_legs :
497+ lines += ["" , "Unavailable: " + "; " .join (unavailable_legs ) + "." ]
498+
499+ if highlighted :
500+ lines += [
501+ "" ,
502+ "<details>" ,
503+ "<summary><b>Measured timings</b></summary>" ,
504+ "" ,
505+ "| Environment | Database task | Before | After | Change |" ,
506+ "|---|---|---:|---:|---:|" ,
507+ ]
508+ for leg , row in highlighted :
509+ lines .append (
510+ f"| { environment_name (leg )} | { TASK_NAMES [row ['name' ]]} | "
511+ f"{ row ['base_ms' ]:.3f} ms | { row ['candidate_ms' ]:.3f} ms | "
512+ f"**{ row ['change_pct' ]:+.1f} %** |"
513+ )
514+ lines += ["" , "</details>" ]
476515
477516 diagnostics_start = len (lines )
478517 lines += [
479518 "" ,
480519 "<details>" ,
481- "<summary>Affected phases and call counts </summary>" ,
520+ "<summary><b>Performance diagnostics</b> </summary>" ,
482521 "" ,
483522 "Phase times are inclusive diagnostics and must not be added together. "
484523 "They identify where measured time changed, not why it changed." ,
@@ -516,7 +555,7 @@ def render(reports, head, build_id, issues=()):
516555 lines += [
517556 "" ,
518557 "<details>" ,
519- "<summary>All database tasks and timings</summary>" ,
558+ "<summary><b> All database tasks and timings</b> </summary>" ,
520559 ]
521560
522561 for leg , (report , rows ) in completed .items ():
@@ -542,7 +581,7 @@ def render(reports, head, build_id, issues=()):
542581 "</details>" ,
543582 "" ,
544583 "<details>" ,
545- "<summary>Build, commits and measurement details</summary>" ,
584+ "<summary><b> Build and measurement details</b> </summary>" ,
546585 "" ,
547586 ]
548587 lines += [
@@ -591,7 +630,7 @@ def render(reports, head, build_id, issues=()):
591630 lines [diagnostics_start :diagnostics_end ] = [
592631 "" ,
593632 "<details>" ,
594- "<summary>Affected phases and call counts </summary>" ,
633+ "<summary><b>Performance diagnostics</b> </summary>" ,
595634 "" ,
596635 f"{ total_diagnostics } diagnostic rows are available in the raw ADO artifacts." ,
597636 "" ,
0 commit comments