sparkforensics-server 0.5.2 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +16 -7
- package/package.json +1 -1
- package/public/assets/AutoscalingChurn-DenWKTv-.js +1 -0
- package/public/assets/CacheUtilization-DLz7NdjV.js +1 -0
- package/public/assets/CachingOpportunity-zpQIqhzm.js +1 -0
- package/public/assets/ChartTheme-DAiARbLP.js +8 -0
- package/public/assets/ColdStart-C-9HjxWl.js +1 -0
- package/public/assets/ConfigAudit-D0V9tcrJ.js +1 -0
- package/public/assets/CoreUsageArea-yeerrljd.js +1 -0
- package/public/assets/Dashboard-DkUPrHKV.js +1 -0
- package/public/assets/DisclosureContext-DK1_iz6J.js +1 -0
- package/public/assets/DuplicatePlanSubtree-xDNDbCd3.js +1 -0
- package/public/assets/DurationHistogram-B6jsE0Ov.js +1 -0
- package/public/assets/EmptyState-C1uL40VU.js +1 -0
- package/public/assets/ExecutorUtilization-DXDZKmSc.js +1 -0
- package/public/assets/GcPressure-MRf7I4IG.js +1 -0
- package/public/assets/ImpactEstimate-Dm3xWbzV.js +1 -0
- package/public/assets/IncompleteRun-CaLOhMtf.js +1 -0
- package/public/assets/JobFailures-CzmzlvhO.js +1 -0
- package/public/assets/MemoryUtilization-AWUMUjCH.js +1 -0
- package/public/assets/NestedLoopJoin-C9sNr6Ss.js +1 -0
- package/public/assets/OverBroadcast-BOmRE6ca.js +1 -0
- package/public/assets/PartitionHint-BL2EmJfE.js +1 -0
- package/public/assets/PartitionSizing-BzBySvUq.js +1 -0
- package/public/assets/PlanExplorer-DdiQRcJU.js +1 -0
- package/public/assets/PlanGraphRoute-CIH9gBuR.js +1 -0
- package/public/assets/PlanView-B1hxzFRs.js +2 -0
- package/public/assets/PythonUdf-DvgCCueD.js +1 -0
- package/public/assets/RetryWaste-uXXu_CyM.js +1 -0
- package/public/assets/RowPagination-C-LzWkI5.js +1 -0
- package/public/assets/RowStatusCluster-Dbtmte7l.js +1 -0
- package/public/assets/ShuffleIO-nALwzC1_.js +1 -0
- package/public/assets/Skew-CHMEKgvk.js +1 -0
- package/public/assets/SlowHost-yyvjpHk6.js +1 -0
- package/public/assets/SmallFiles-y6odJ97n.js +1 -0
- package/public/assets/SpeculationWaste-C-SD2LOt.js +1 -0
- package/public/assets/Spill-DHTMmOup.js +1 -0
- package/public/assets/StageFailed-CQ3DxC9R.js +1 -0
- package/public/assets/StageFindingGroup-BgYLyj5q.js +1 -0
- package/public/assets/StageHeader-CIETkjVZ.js +1 -0
- package/public/assets/StagePill--P7PDd3s.js +1 -0
- package/public/assets/StageShape-BIv8vx_o.js +1 -0
- package/public/assets/StageSlowness-MMqzERxN.js +1 -0
- package/public/assets/Straggler-BgrY7AyW.js +1 -0
- package/public/assets/TaskFailures-BHHyKYTs.js +1 -0
- package/public/assets/TinyTask-DDScNhCl.js +1 -0
- package/public/assets/UnderBroadcast-CGIC04TI.js +1 -0
- package/public/assets/WidgetLeadSummary-CXFZP00C.js +1 -0
- package/public/assets/button-DbpTz2yk.js +1 -0
- package/public/assets/charts-vendor-CtTxwTeu.js +59 -0
- package/public/assets/composite-C9Nu2EI9.js +1 -0
- package/public/assets/d3-vendor-DNlD2-cz.js +1 -0
- package/public/assets/detector-registry-Bp8hrLua.js +2 -0
- package/public/assets/downsample-WmNM1qc9.js +1 -0
- package/public/assets/finding-anchor-Dr40LkS9.js +1 -0
- package/public/assets/findings-of-type-BL2u3RGZ.js +1 -0
- package/public/assets/impact-sort-mC5ISgX8.js +1 -0
- package/public/assets/inbox-KPU1Gppm.js +1 -0
- package/public/assets/index-CaRVPvAT.css +2 -0
- package/public/assets/index-fDiwfuoO.js +14 -0
- package/public/assets/inertValue-L9VxV0VE.js +1 -0
- package/public/assets/instrument-sans-latin-ext-wdth-normal-C5E2Gvlv.woff2 +0 -0
- package/public/assets/instrument-sans-latin-wdth-normal-BVScPF0l.woff2 +0 -0
- package/public/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/public/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/public/assets/layout.worker-CLcBHxVp.js +3 -0
- package/public/assets/{parser-worker-CA5RxqKc.js → parser-worker-CRIOPMOW.js} +8 -8
- package/public/assets/plan-graph-vendor-Ce6d4HU6.js +7 -0
- package/public/assets/react-vendor-C6KcUD36.js +9 -0
- package/public/assets/select-BHqOqun5.js +1 -0
- package/public/assets/toggle-DPeN6aNa.js +1 -0
- package/public/assets/toggle-group-Kl3uyHSr.js +1 -0
- package/public/assets/usePagedRows-BafD6bEN.js +1 -0
- package/public/assets/useRecentFiles-DzJZAoOT.js +3 -0
- package/public/assets/useRegisterFieldControl-pQv-ZDoU.js +1 -0
- package/public/assets/useScrollLock-BCxn_dMp.js +1 -0
- package/public/assets/useSortMode-DjrAN-z4.js +1 -0
- package/public/docs/404.html +3 -7
- package/public/docs/assets/{app.eYTPqTeq.js → app.1gvzd5Zb.js} +1 -1
- package/public/docs/assets/chunks/@localSearchIndexroot.DS2TQP5_.js +1 -0
- package/public/docs/assets/chunks/{VPLocalSearchBox.DsZrQKQR.js → VPLocalSearchBox.CNxT3s0I.js} +1 -1
- package/public/docs/assets/chunks/{theme.DsTNE2pE.js → theme.C5lLqUv7.js} +2 -2
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.CqKM_jEG.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.CqKM_jEG.lean.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_board-widgets_caching-and-memory.md.8bH1HnZp.js → contributor-guide_architecture_board-widgets_caching-and-memory.md.BYDo3ClR.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets_plan-advisor.md.ajUAVdbc.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.WqY74T0T.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.WqY74T0T.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.CHHgywoP.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_detector-contract.md.wj6Et6UD.lean.js → contributor-guide_architecture_detector-contract.md.CHHgywoP.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.DIz3_oz9.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.DIz3_oz9.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract_threshold-tables.md.WH4tRHPL.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_detector-contract_threshold-tables.md.CKjWG56Y.lean.js → contributor-guide_architecture_detector-contract_threshold-tables.md.WH4tRHPL.lean.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_drill-down.md.CqZPrdo9.js → contributor-guide_architecture_drill-down.md.yB-Hz2XT.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_drill-down.md.CqZPrdo9.lean.js → contributor-guide_architecture_drill-down.md.yB-Hz2XT.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_drill-down_plan-graph.md.BQZE04sw.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_drill-down_plan-graph.md.DwOozIEs.lean.js → contributor-guide_architecture_drill-down_plan-graph.md.BQZE04sw.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.K71YB-Rr.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_impact-estimation.md.CZv_ZGOp.lean.js → contributor-guide_architecture_impact-estimation.md.K71YB-Rr.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.DLCAffwn.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.BUucRc0A.lean.js → contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.DLCAffwn.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.JFrzDMwo.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.JFrzDMwo.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_overview.md.nxkpOhgf.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_state-and-history_run-comparison-internals.md.U-9KMDFK.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_state-and-history_run-comparison-internals.md.CZA0JLtV.lean.js → contributor-guide_architecture_state-and-history_run-comparison-internals.md.U-9KMDFK.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.BrSz8Ezh.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.B7rjSF_h.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.B7rjSF_h.lean.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_widget-rendering_list-sort-mode.md.BuHKgH0C.js → contributor-guide_architecture_widget-rendering_list-sort-mode.md.37hcZJ7q.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_widget-rendering_row-expand-contract.md.ZT89u9f1.js → contributor-guide_architecture_widget-rendering_row-expand-contract.md.mK_VmAWk.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_worker-protocol.md.BAnhi2-d.js → contributor-guide_architecture_worker-protocol.md.Br6OE7RW.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.Br6OE7RW.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_cli-and-mcp.md.IVyaXrGe.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_worker-protocol_cli-and-mcp.md.DC1YqXBp.lean.js → contributor-guide_architecture_worker-protocol_cli-and-mcp.md.IVyaXrGe.lean.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DSVFPpWb.js → contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DVSXn-bb.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_worker-protocol_evidence-availability.md.CjimIDBY.js → contributor-guide_architecture_worker-protocol_evidence-availability.md.D3S5cyOW.js} +2 -2
- package/public/docs/assets/{contributor-guide_architecture_worker-protocol_evidence-availability.md.CjimIDBY.lean.js → contributor-guide_architecture_worker-protocol_evidence-availability.md.D3S5cyOW.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_evidence-report.md.CtmCU57I.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_worker-protocol_evidence-report.md.DVGZOWvW.lean.js → contributor-guide_architecture_worker-protocol_evidence-report.md.CtmCU57I.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_contributing.md.DBW4drtZ.js +1 -0
- package/public/docs/assets/{contributor-guide_development-setup.md.D9bu4j_c.js → contributor-guide_development-setup.md.B21ZTDhn.js} +3 -3
- package/public/docs/assets/contributor-guide_development-setup.md.B21ZTDhn.lean.js +1 -0
- package/public/docs/assets/contributor-guide_testing.md.DpkozNoG.js +4 -0
- package/public/docs/assets/{contributor-guide_testing.md.By6XGR9a.lean.js → contributor-guide_testing.md.DpkozNoG.lean.js} +1 -1
- package/public/docs/assets/{index.md.CHJVslga.js → index.md.lMm7SUMz.js} +1 -1
- package/public/docs/assets/{index.md.CHJVslga.lean.js → index.md.lMm7SUMz.lean.js} +1 -1
- package/public/docs/assets/instrument-sans-latin-ext-wdth-normal.C5E2Gvlv.woff2 +0 -0
- package/public/docs/assets/instrument-sans-latin-wdth-normal.BVScPF0l.woff2 +0 -0
- package/public/docs/assets/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2 +0 -0
- package/public/docs/assets/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2 +0 -0
- package/public/docs/assets/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2 +0 -0
- package/public/docs/assets/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2 +0 -0
- package/public/docs/assets/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2 +0 -0
- package/public/docs/assets/style.Cfxqlj0y.css +1 -0
- package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.C0pcQoNc.js +29 -0
- package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.C0pcQoNc.lean.js +1 -0
- package/public/docs/assets/user-guide_getting-started_reading-the-dashboard.md.CGaxPX_1.js +1 -0
- package/public/docs/assets/{user-guide_getting-started_tuning-thresholds.md.B_MyjyZm.js → user-guide_getting-started_tuning-thresholds.md.BGVE-wrc.js} +2 -2
- package/public/docs/assets/{user-guide_getting-started_tuning-thresholds.md.B_MyjyZm.lean.js → user-guide_getting-started_tuning-thresholds.md.BGVE-wrc.lean.js} +1 -1
- package/public/docs/assets/{user-guide_mcp-tools.md.C65SjWUL.js → user-guide_mcp-tools.md.49r3L2YE.js} +1 -1
- package/public/docs/assets/{user-guide_mcp-tools_compare-runs.md.Cc_gLoix.js → user-guide_mcp-tools_compare-runs.md.BQ_kIptC.js} +11 -6
- package/public/docs/assets/user-guide_mcp-tools_compare-runs.md.BQ_kIptC.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_diagnose-run.md.azCZXkH8.js +44 -0
- package/public/docs/assets/{user-guide_mcp-tools_diagnose-run.md.BP1vnHA5.lean.js → user-guide_mcp-tools_diagnose-run.md.azCZXkH8.lean.js} +1 -1
- package/public/docs/assets/{user-guide_mcp-tools_evaluate-budgets.md.BB0nDY3Z.js → user-guide_mcp-tools_evaluate-budgets.md.dpQpRQ7z.js} +2 -2
- package/public/docs/assets/{user-guide_mcp-tools_evaluate-budgets.md.BB0nDY3Z.lean.js → user-guide_mcp-tools_evaluate-budgets.md.dpQpRQ7z.lean.js} +1 -1
- package/public/docs/assets/{user-guide_mcp-tools_get-finding-evidence.md.rKyu4wts.js → user-guide_mcp-tools_get-finding-evidence.md.CH6FkNLX.js} +2 -1
- package/public/docs/assets/{user-guide_mcp-tools_get-finding-evidence.md.rKyu4wts.lean.js → user-guide_mcp-tools_get-finding-evidence.md.CH6FkNLX.lean.js} +1 -1
- package/public/docs/assets/{user-guide_mcp-tools_get-run-summary.md.DpxZ4ZNp.js → user-guide_mcp-tools_get-run-summary.md.EhaIsele.js} +1 -1
- package/public/docs/assets/user-guide_run-comparison.md.B_LOkdBf.js +1 -0
- package/public/docs/assets/user-guide_run-comparison.md.B_LOkdBf.lean.js +1 -0
- package/public/docs/assets/user-guide_understanding-findings.md.C4riKCKl.js +1 -0
- package/public/docs/assets/user-guide_understanding-findings.md.C4riKCKl.lean.js +1 -0
- package/public/docs/contributor-guide/architecture/board-widgets/caching-and-memory.html +6 -10
- package/public/docs/contributor-guide/architecture/board-widgets/plan-advisor.html +6 -10
- package/public/docs/contributor-guide/architecture/board-widgets/visual-system-and-templating.html +6 -10
- package/public/docs/contributor-guide/architecture/board-widgets.html +6 -10
- package/public/docs/contributor-guide/architecture/detector-contract/plan-attribution.html +6 -10
- package/public/docs/contributor-guide/architecture/detector-contract/threshold-tables.html +6 -10
- package/public/docs/contributor-guide/architecture/detector-contract.html +6 -10
- package/public/docs/contributor-guide/architecture/drill-down/plan-graph.html +6 -10
- package/public/docs/contributor-guide/architecture/drill-down.html +6 -10
- package/public/docs/contributor-guide/architecture/impact-estimation/caveats-tuning-and-coverage.html +6 -10
- package/public/docs/contributor-guide/architecture/impact-estimation/stage-union-rollup.html +6 -10
- package/public/docs/contributor-guide/architecture/impact-estimation.html +6 -10
- package/public/docs/contributor-guide/architecture/index.html +5 -9
- package/public/docs/contributor-guide/architecture/overview.html +6 -10
- package/public/docs/contributor-guide/architecture/state-and-history/history-server-intake.html +5 -9
- package/public/docs/contributor-guide/architecture/state-and-history/run-comparison-internals.html +6 -10
- package/public/docs/contributor-guide/architecture/state-and-history.html +5 -9
- package/public/docs/contributor-guide/architecture/widget-rendering/findings-tab.html +6 -10
- package/public/docs/contributor-guide/architecture/widget-rendering/investigation-routing.html +5 -9
- package/public/docs/contributor-guide/architecture/widget-rendering/list-sort-mode.html +6 -10
- package/public/docs/contributor-guide/architecture/widget-rendering/reference-section.html +5 -9
- package/public/docs/contributor-guide/architecture/widget-rendering/row-expand-contract.html +6 -10
- package/public/docs/contributor-guide/architecture/widget-rendering.html +6 -10
- package/public/docs/contributor-guide/architecture/worker-protocol/cli-and-mcp.html +6 -10
- package/public/docs/contributor-guide/architecture/worker-protocol/core-and-event-validation.html +6 -10
- package/public/docs/contributor-guide/architecture/worker-protocol/evidence-availability.html +7 -11
- package/public/docs/contributor-guide/architecture/worker-protocol/evidence-report.html +6 -10
- package/public/docs/contributor-guide/architecture/worker-protocol.html +6 -10
- package/public/docs/contributor-guide/contributing.html +6 -10
- package/public/docs/contributor-guide/development-setup.html +8 -12
- package/public/docs/contributor-guide/testing.html +9 -10
- package/public/docs/favicon.svg +2 -2
- package/public/docs/hashmap.json +1 -1
- package/public/docs/index.html +6 -10
- package/public/docs/logo-dark.svg +1 -0
- package/public/docs/logo-light.svg +1 -0
- package/public/docs/tuning-reference/anti-patterns.html +5 -9
- package/public/docs/tuning-reference/aqe.html +5 -9
- package/public/docs/tuning-reference/bottleneck-broadcast-sizing.html +5 -9
- package/public/docs/tuning-reference/bottleneck-cold-start.html +5 -9
- package/public/docs/tuning-reference/bottleneck-duplicate-plan-subtree.html +5 -9
- package/public/docs/tuning-reference/bottleneck-failures.html +5 -9
- package/public/docs/tuning-reference/bottleneck-gc.html +5 -9
- package/public/docs/tuning-reference/bottleneck-job-failure-rate.html +5 -9
- package/public/docs/tuning-reference/bottleneck-memory-utilization.html +5 -9
- package/public/docs/tuning-reference/bottleneck-retry-waste.html +5 -9
- package/public/docs/tuning-reference/bottleneck-shuffle.html +5 -9
- package/public/docs/tuning-reference/bottleneck-skew.html +5 -9
- package/public/docs/tuning-reference/bottleneck-slow-host.html +5 -9
- package/public/docs/tuning-reference/bottleneck-small-files.html +5 -9
- package/public/docs/tuning-reference/bottleneck-spill.html +5 -9
- package/public/docs/tuning-reference/bottleneck-straggler.html +5 -9
- package/public/docs/tuning-reference/bottleneck-tiny-tasks.html +5 -9
- package/public/docs/tuning-reference/bottleneck-utilization.html +5 -9
- package/public/docs/tuning-reference/caching.html +5 -9
- package/public/docs/tuning-reference/cluster-config.html +5 -9
- package/public/docs/tuning-reference/config.html +5 -9
- package/public/docs/tuning-reference/data-formats.html +5 -9
- package/public/docs/tuning-reference/index.html +5 -9
- package/public/docs/tuning-reference/intro.html +5 -9
- package/public/docs/tuning-reference/joins.html +5 -9
- package/public/docs/tuning-reference/memory-model.html +5 -9
- package/public/docs/tuning-reference/metrics.html +5 -9
- package/public/docs/tuning-reference/partitioning.html +5 -9
- package/public/docs/tuning-reference/pyspark.html +5 -9
- package/public/docs/tuning-reference/shuffle.html +5 -9
- package/public/docs/tuning-reference/spark-architecture.html +5 -9
- package/public/docs/tuning-reference/table-formats.html +5 -9
- package/public/docs/user-guide/alternative-log-retrieval/managed-platforms.html +5 -9
- package/public/docs/user-guide/alternative-log-retrieval/ssh-bastion.html +5 -9
- package/public/docs/user-guide/alternative-log-retrieval.html +5 -9
- package/public/docs/user-guide/getting-started/ci-and-automation.html +17 -15
- package/public/docs/user-guide/getting-started/reading-the-dashboard.html +6 -10
- package/public/docs/user-guide/getting-started/regression-metric-keys.html +5 -9
- package/public/docs/user-guide/getting-started/tuning-thresholds.html +7 -11
- package/public/docs/user-guide/getting-started.html +5 -9
- package/public/docs/user-guide/mcp-tools/compare-runs.html +16 -15
- package/public/docs/user-guide/mcp-tools/diagnose-run.html +28 -11
- package/public/docs/user-guide/mcp-tools/evaluate-budgets.html +6 -10
- package/public/docs/user-guide/mcp-tools/get-finding-documentation.html +5 -9
- package/public/docs/user-guide/mcp-tools/get-finding-evidence.html +7 -10
- package/public/docs/user-guide/mcp-tools/get-reference-doc.html +5 -9
- package/public/docs/user-guide/mcp-tools/get-run-summary.html +6 -10
- package/public/docs/user-guide/mcp-tools/list-runs.html +5 -9
- package/public/docs/user-guide/mcp-tools.html +6 -10
- package/public/docs/user-guide/run-comparison/how-stages-are-matched.html +5 -9
- package/public/docs/user-guide/run-comparison.html +6 -10
- package/public/docs/user-guide/understanding-findings.html +6 -10
- package/public/export-template.html +46 -46
- package/public/favicon.svg +2 -2
- package/public/index.html +8 -10
- package/public/sample-runs/sample-run.ndjson.gz +0 -0
- package/vendor-core/allocation.js +126 -39
- package/vendor-core/analyzer.js +85 -58
- package/vendor-core/api-merge-writes.js +3 -0
- package/vendor-core/aqe-skew.js +347 -0
- package/vendor-core/cli/budgets.js +6 -4
- package/vendor-core/cli/collect-run-pair.js +89 -0
- package/vendor-core/cli/collect-run-worker.js +16 -0
- package/vendor-core/cli/collect-run.js +1 -2
- package/vendor-core/cli/native-zstd.js +12 -16
- package/vendor-core/comparability.js +234 -0
- package/vendor-core/comparison-output.js +15 -7
- package/vendor-core/comparison-verdict.js +105 -25
- package/vendor-core/core-source-hash.txt +1 -1
- package/vendor-core/core-time-series.js +0 -1
- package/vendor-core/core-usage-locality.js +1 -1
- package/vendor-core/delta-log-paths.js +10 -1
- package/vendor-core/detectors.js +1078 -416
- package/vendor-core/docs-config.js +0 -4
- package/vendor-core/docs-content/detection/cache.md +2 -1
- package/vendor-core/docs-content/detection/cfg.md +19 -11
- package/vendor-core/docs-content/detection/cold.md +2 -1
- package/vendor-core/docs-content/detection/gc.md +7 -3
- package/vendor-core/docs-content/detection/host.md +11 -1
- package/vendor-core/docs-content/detection/mem.md +17 -6
- package/vendor-core/docs-content/detection/part.md +3 -1
- package/vendor-core/docs-content/detection/plan.md +55 -13
- package/vendor-core/docs-content/detection/shfl.md +11 -5
- package/vendor-core/docs-content/detection/skew.md +48 -1
- package/vendor-core/docs-content/detection/slow.md +4 -2
- package/vendor-core/docs-content/detection/spec.md +6 -1
- package/vendor-core/docs-content/detection/spill.md +6 -3
- package/vendor-core/docs-content/detection/strag.md +19 -6
- package/vendor-core/docs-content/detection/tiny.md +9 -3
- package/vendor-core/docs-content/detection/util.md +6 -2
- package/vendor-core/effective-conf.js +7 -10
- package/vendor-core/efficiency-model.js +24 -16
- package/vendor-core/etl-phases.js +1 -2
- package/vendor-core/event-handlers.js +175 -57
- package/vendor-core/event-schemas.js +21 -16
- package/vendor-core/evidence-availability.js +9 -2
- package/vendor-core/evidence-report.js +118 -35
- package/vendor-core/executor-peaks.js +41 -0
- package/vendor-core/export-data.js +5 -5
- package/vendor-core/finding-identity.js +78 -0
- package/vendor-core/finding-presentation.js +129 -39
- package/vendor-core/finding-types.js +108 -30
- package/vendor-core/format-utils.js +14 -15
- package/vendor-core/html-export.js +1 -1
- package/vendor-core/impact-band.js +2 -2
- package/vendor-core/impact-format.js +47 -19
- package/vendor-core/impact-model.js +28 -17
- package/vendor-core/job-groups.js +4 -4
- package/vendor-core/mcp-server-factory.js +48 -12
- package/vendor-core/mcp-tools.js +179 -24
- package/vendor-core/median.js +2 -2
- package/vendor-core/nested-loop-join.js +73 -0
- package/vendor-core/occupancy.js +1 -2
- package/vendor-core/parser-worker.js +1 -1
- package/vendor-core/plan-graph-model.js +14 -22
- package/vendor-core/plan-node-detail.js +2 -3
- package/vendor-core/plan-summary.js +24 -19
- package/vendor-core/plan-tree-walk.js +6 -8
- package/vendor-core/python-stage.js +12 -1
- package/vendor-core/recommendation-rollup.js +13 -12
- package/vendor-core/redact.js +52 -46
- package/vendor-core/remediation.js +10 -5
- package/vendor-core/run-aggregates.js +6 -8
- package/vendor-core/run-comparison.js +226 -66
- package/vendor-core/run-identity.js +12 -0
- package/vendor-core/run-interpretation.js +21 -0
- package/vendor-core/run-metrics.js +2 -2
- package/vendor-core/run-output.js +44 -11
- package/vendor-core/run-totals.js +12 -0
- package/vendor-core/run-verdict.js +76 -3
- package/vendor-core/scaling-sim.js +3 -4
- package/vendor-core/snappy-block.js +2 -2
- package/vendor-core/spark-conf.js +168 -0
- package/vendor-core/sql-stages.js +2 -2
- package/vendor-core/stage-alignment.js +2 -12
- package/vendor-core/stage-identity.js +58 -3
- package/vendor-core/stage-label.js +14 -0
- package/vendor-core/stage-plan-nodes.js +17 -3
- package/vendor-core/stage-quantiles.js +141 -9
- package/vendor-core/stage-structure.js +17 -3
- package/vendor-core/threshold-overrides.js +9 -3
- package/vendor-core/types.js +70 -23
- package/vendor-core/wall-clock.js +8 -0
- package/vendor-core/wasted-core-hours.js +12 -12
- package/vendor-core/write-targets.js +146 -14
- package/vendor-core/zstd-worker-client.js +1 -1
- package/vendor-core/zstd-worker.js +1 -1
- package/public/assets/AutoscalingChurn-8t3U3isq.js +0 -1
- package/public/assets/CacheUtilization-CJs9tTum.js +0 -1
- package/public/assets/CachingOpportunity-D1NcHs0V.js +0 -1
- package/public/assets/ColdStart-CdRJ9gD8.js +0 -1
- package/public/assets/ConfigAudit-B5Gbe5js.js +0 -1
- package/public/assets/CoreUsageArea-a--NTRGY.js +0 -1
- package/public/assets/Dashboard-C1hNeX49.js +0 -2
- package/public/assets/DisclosureContext-ZpE6CkHx.js +0 -1
- package/public/assets/DuplicatePlanSubtree-dobXdz7E.js +0 -1
- package/public/assets/ExecutorUtilization-D9grwi7t.js +0 -1
- package/public/assets/GcPressure-8-G2ri10.js +0 -1
- package/public/assets/IncompleteRun-B91lky7a.js +0 -1
- package/public/assets/JobFailures-BsWvBMyJ.js +0 -1
- package/public/assets/MemoryUtilization-BM5schZI.js +0 -1
- package/public/assets/OverBroadcast-DdN8JIJH.js +0 -1
- package/public/assets/PartitionHint-CUvbnnxy.js +0 -1
- package/public/assets/PartitionSizing-CY5HDYtp.js +0 -1
- package/public/assets/PlanExplorer-DgHCDBD_.js +0 -1
- package/public/assets/PlanGraphRoute-DH3KJb8j.js +0 -1
- package/public/assets/RetryWaste-DOnE9vGF.js +0 -1
- package/public/assets/ShuffleIO-MMnDESkF.js +0 -1
- package/public/assets/Skew-BmZZJ5ms.js +0 -1
- package/public/assets/SlowHost-CsJzfEqo.js +0 -1
- package/public/assets/SmallFiles-BoK3R1Ex.js +0 -1
- package/public/assets/SpeculationWaste-CnVxB5AJ.js +0 -1
- package/public/assets/Spill-BhNicyBy.js +0 -1
- package/public/assets/StageFailed-mAhHU4l_.js +0 -1
- package/public/assets/StageFindingGroup-BEtPWcT0.js +0 -1
- package/public/assets/StageHeader-DJkYkrsU.js +0 -1
- package/public/assets/StageShape-BDxRknLp.js +0 -1
- package/public/assets/StageSlowness-BPRw-otN.js +0 -1
- package/public/assets/Straggler-CZCbnOWP.js +0 -1
- package/public/assets/TaskFailures-C57YcLFQ.js +0 -1
- package/public/assets/TinyTask-Bi84qU7n.js +0 -1
- package/public/assets/UnderBroadcast-DdQV7htE.js +0 -1
- package/public/assets/charts-vendor-0VMaLVLN.js +0 -59
- package/public/assets/finding-anchor-Cl6_5hfV.js +0 -1
- package/public/assets/impact-sort-CssZ6MT2.js +0 -1
- package/public/assets/index-2h_TgUAb.css +0 -2
- package/public/assets/index-B-03mG7K.js +0 -14
- package/public/assets/plan-graph-vendor-BYl-AzN5.js +0 -7
- package/public/assets/react-vendor-DEdfrRTJ.js +0 -9
- package/public/assets/select-CQjNhprm.js +0 -1
- package/public/assets/usePagedRows-Dyl6T8Ok.js +0 -1
- package/public/assets/useRecentFiles-XZEnLlal.js +0 -11
- package/public/assets/useSortMode-Dhvit8dt.js +0 -1
- package/public/docs/assets/chunks/@localSearchIndexroot.u_e5bQz4.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.YQcj5EI4.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.YQcj5EI4.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets_plan-advisor.md.RlzvUmNm.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.DYgUpIJB.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.DYgUpIJB.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.wj6Et6UD.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.yNex4bys.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.yNex4bys.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract_threshold-tables.md.CKjWG56Y.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_drill-down_plan-graph.md.DwOozIEs.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.CZv_ZGOp.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.BUucRc0A.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.DdCGtAGu.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.DdCGtAGu.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_overview.md.C1sSvm9i.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_state-and-history_run-comparison-internals.md.CZA0JLtV.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.BOZ1azXG.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.BQXycK6G.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.BQXycK6G.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.BAnhi2-d.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_cli-and-mcp.md.DC1YqXBp.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_evidence-report.md.DVGZOWvW.js +0 -1
- package/public/docs/assets/contributor-guide_contributing.md.CQMvGwFt.js +0 -1
- package/public/docs/assets/contributor-guide_development-setup.md.D9bu4j_c.lean.js +0 -1
- package/public/docs/assets/contributor-guide_testing.md.By6XGR9a.js +0 -1
- package/public/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
- package/public/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
- package/public/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
- package/public/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
- package/public/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
- package/public/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
- package/public/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
- package/public/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
- package/public/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
- package/public/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
- package/public/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
- package/public/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
- package/public/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
- package/public/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
- package/public/docs/assets/style.tmDhD3c8.css +0 -1
- package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.OUQqw3mI.js +0 -23
- package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.OUQqw3mI.lean.js +0 -1
- package/public/docs/assets/user-guide_getting-started_reading-the-dashboard.md.Obf3W3__.js +0 -1
- package/public/docs/assets/user-guide_mcp-tools_compare-runs.md.Cc_gLoix.lean.js +0 -1
- package/public/docs/assets/user-guide_mcp-tools_diagnose-run.md.BP1vnHA5.js +0 -23
- package/public/docs/assets/user-guide_run-comparison.md.BUALkohi.js +0 -1
- package/public/docs/assets/user-guide_run-comparison.md.BUALkohi.lean.js +0 -1
- package/public/docs/assets/user-guide_understanding-findings.md.C9YRruMT.js +0 -1
- package/public/docs/assets/user-guide_understanding-findings.md.C9YRruMT.lean.js +0 -1
- /package/public/docs/assets/{contributor-guide_architecture_board-widgets_caching-and-memory.md.8bH1HnZp.lean.js → contributor-guide_architecture_board-widgets_caching-and-memory.md.BYDo3ClR.lean.js} +0 -0
- /package/public/docs/assets/{contributor-guide_architecture_board-widgets_plan-advisor.md.RlzvUmNm.lean.js → contributor-guide_architecture_board-widgets_plan-advisor.md.ajUAVdbc.lean.js} +0 -0
- /package/public/docs/assets/{contributor-guide_architecture_overview.md.C1sSvm9i.lean.js → contributor-guide_architecture_overview.md.nxkpOhgf.lean.js} +0 -0
- /package/public/docs/assets/{contributor-guide_architecture_widget-rendering.md.BOZ1azXG.lean.js → contributor-guide_architecture_widget-rendering.md.BrSz8Ezh.lean.js} +0 -0
- /package/public/docs/assets/{contributor-guide_architecture_widget-rendering_list-sort-mode.md.BuHKgH0C.lean.js → contributor-guide_architecture_widget-rendering_list-sort-mode.md.37hcZJ7q.lean.js} +0 -0
- /package/public/docs/assets/{contributor-guide_architecture_widget-rendering_row-expand-contract.md.ZT89u9f1.lean.js → contributor-guide_architecture_widget-rendering_row-expand-contract.md.mK_VmAWk.lean.js} +0 -0
- /package/public/docs/assets/{contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DSVFPpWb.lean.js → contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DVSXn-bb.lean.js} +0 -0
- /package/public/docs/assets/{contributor-guide_contributing.md.CQMvGwFt.lean.js → contributor-guide_contributing.md.DBW4drtZ.lean.js} +0 -0
- /package/public/docs/assets/{user-guide_getting-started_reading-the-dashboard.md.Obf3W3__.lean.js → user-guide_getting-started_reading-the-dashboard.md.CGaxPX_1.lean.js} +0 -0
- /package/public/docs/assets/{user-guide_mcp-tools.md.C65SjWUL.lean.js → user-guide_mcp-tools.md.49r3L2YE.lean.js} +0 -0
- /package/public/docs/assets/{user-guide_mcp-tools_get-run-summary.md.DpxZ4ZNp.lean.js → user-guide_mcp-tools_get-run-summary.md.EhaIsele.lean.js} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { medianOfSorted } from './median.js';
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
|
|
5
6
|
// Single source of truth for the packed per-task numeric array: FIELDS (offset
|
|
6
7
|
// constants), TASK_FIELD_NAMES (display labels), and the finalizeStage hot-loop
|
|
@@ -43,9 +44,8 @@ export const TASK_FIELD_NAMES = TASK_FIELD_DESCRIPTORS.map((d) => d.na
|
|
|
43
44
|
const TASK_FIELD_PROPS = TASK_FIELD_DESCRIPTORS.map((d) => d.prop);
|
|
44
45
|
|
|
45
46
|
// Numeric accumulator fields on `stage` that this function reads/increments.
|
|
46
|
-
// `stage`'s public parameter type stays the loose Record shape
|
|
47
|
-
//
|
|
48
|
-
// below, never a restatement of the object's real shape.
|
|
47
|
+
// `stage`'s public parameter type stays the loose Record shape; this narrow view is only for the
|
|
48
|
+
// arithmetic below, never a restatement of the object's real shape.
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
|
|
@@ -82,7 +82,8 @@ export function finalizeStage(
|
|
|
82
82
|
const localityStats = new Map();
|
|
83
83
|
let peakExecutionMemoryMax = 0;
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
const attempts = stage.taskAttempts;
|
|
86
|
+
for (const t of attempts.values()) {
|
|
86
87
|
taskCount++;
|
|
87
88
|
if (t.failed) {
|
|
88
89
|
failedTasks++;
|
|
@@ -105,7 +106,15 @@ export function finalizeStage(
|
|
|
105
106
|
}
|
|
106
107
|
if (t.executorId) {
|
|
107
108
|
let es = executorStats.get(t.executorId);
|
|
108
|
-
if (!es) { es = { taskCount: 0, totalDuration: 0, inputBytes: 0, shuffleReadBytes: 0, shuffleWriteBytes: 0 }; executorStats.set(t.executorId, es); }
|
|
109
|
+
if (!es) { es = { taskCount: 0, totalDuration: 0, logDurationSum: 0, logDurationM2: 0, inputBytes: 0, shuffleReadBytes: 0, shuffleWriteBytes: 0 }; executorStats.set(t.executorId, es); }
|
|
110
|
+
// Task durations scatter multiplicatively, so the spread slowHost tests an executor against is
|
|
111
|
+
// kept on the log scale: a running sum and Welford's M2 of ln(1 + duration). A non-finite
|
|
112
|
+
// duration makes both NaN, which the detector reads as "no spread known".
|
|
113
|
+
const logDuration = Math.log1p(t.duration);
|
|
114
|
+
const logMeanBefore = es.taskCount > 0 ? es.logDurationSum / es.taskCount : 0;
|
|
115
|
+
const logMeanAfter = (es.logDurationSum + logDuration) / (es.taskCount + 1);
|
|
116
|
+
es.logDurationM2 += (logDuration - logMeanBefore) * (logDuration - logMeanAfter);
|
|
117
|
+
es.logDurationSum += logDuration;
|
|
109
118
|
es.taskCount++;
|
|
110
119
|
es.totalDuration += t.duration;
|
|
111
120
|
es.inputBytes += t.inputBytes;
|
|
@@ -145,9 +154,9 @@ export function finalizeStage(
|
|
|
145
154
|
const { p50: spillMemP50, p95: spillMemP95, max: spillMemMax } = computeFieldQuantiles(arr, FIELDS.MEM_SPILLED);
|
|
146
155
|
const { p50: spillDiskP50, p95: spillDiskP95, max: spillDiskMax } = computeFieldQuantiles(arr, FIELDS.DISK_SPILLED);
|
|
147
156
|
|
|
148
|
-
// Straggler count: tasks with duration >
|
|
149
|
-
// task that isn't one.
|
|
150
|
-
const stragglerThreshold =
|
|
157
|
+
// Straggler count: tasks with duration > STRAGGLER_FACTOR * P50, their summed excess over P50, and
|
|
158
|
+
// the longest task that isn't one.
|
|
159
|
+
const stragglerThreshold = STRAGGLER_FACTOR * p50;
|
|
151
160
|
let stragglerCount = 0;
|
|
152
161
|
let stragglerExcessMs = 0;
|
|
153
162
|
let longestNonStragglerMs = 0;
|
|
@@ -160,6 +169,7 @@ export function finalizeStage(
|
|
|
160
169
|
}
|
|
161
170
|
}
|
|
162
171
|
|
|
172
|
+
const tailAttribution = p50 > 0 ? attributeTail(attempts.values() , p50) : null;
|
|
163
173
|
const peakConcurrentTasks = computePeakConcurrentTasks(arr);
|
|
164
174
|
const tailReplayRecoveryMs = stragglerCount > 0
|
|
165
175
|
? computeTailReplayRecoveryMs(arr, p50, peakConcurrentTasks)
|
|
@@ -169,7 +179,7 @@ export function finalizeStage(
|
|
|
169
179
|
([host, s]) => ({ host, taskCount: s.taskCount, totalDuration: s.totalDuration })
|
|
170
180
|
);
|
|
171
181
|
const executorStatsArr = [...executorStats.entries()].map(
|
|
172
|
-
([executorId, s]) => ({ executorId, taskCount: s.taskCount, totalDuration: s.totalDuration, inputBytes: s.inputBytes, shuffleReadBytes: s.shuffleReadBytes, shuffleWriteBytes: s.shuffleWriteBytes })
|
|
182
|
+
([executorId, s]) => ({ executorId, taskCount: s.taskCount, totalDuration: s.totalDuration, logDurationSum: s.logDurationSum, logDurationM2: s.logDurationM2, inputBytes: s.inputBytes, shuffleReadBytes: s.shuffleReadBytes, shuffleWriteBytes: s.shuffleWriteBytes })
|
|
173
183
|
);
|
|
174
184
|
const failureReasonsArr = [...failureReasons.entries()].map(
|
|
175
185
|
([reason, count]) => ({ reason, count })
|
|
@@ -191,6 +201,7 @@ export function finalizeStage(
|
|
|
191
201
|
peakExecutionMemoryMax,
|
|
192
202
|
taskActiveMs: computeTaskActiveMs(arr),
|
|
193
203
|
peakConcurrentTasks,
|
|
204
|
+
...(tailAttribution ? { tailAttribution } : {}),
|
|
194
205
|
taskDurationP50: p50,
|
|
195
206
|
taskDurationP95: p95,
|
|
196
207
|
taskDurationMax: max,
|
|
@@ -210,6 +221,127 @@ export function finalizeStage(
|
|
|
210
221
|
return { type: 'stage', data };
|
|
211
222
|
}
|
|
212
223
|
|
|
224
|
+
// A task is in the tail when it runs over this many times the stage's median task: skew's own
|
|
225
|
+
// P95/median ratio threshold, so every stage either detector flags on duration has a tail here.
|
|
226
|
+
export const TAIL_FACTOR = 3;
|
|
227
|
+
|
|
228
|
+
// A task is a straggler when it runs over this many times the stage's median task.
|
|
229
|
+
export const STRAGGLER_FACTOR = 4;
|
|
230
|
+
|
|
231
|
+
// The per-task fields attributeTail reads; a TaskRecord in event-handlers.ts has all of them.
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
// A hosts-concentration reading needs this many tail tasks on the host, at least this share of the
|
|
247
|
+
// tail, and at least this multiple of the host's share of all tasks, before the host explains the
|
|
248
|
+
// excess the other causes leave. One slow task on a host that ran a tenth of the stage is chance.
|
|
249
|
+
const TAIL_HOST_MIN_TASKS = 3;
|
|
250
|
+
const TAIL_HOST_MIN_TAIL_SHARE = 0.5;
|
|
251
|
+
const TAIL_HOST_MIN_OVERREPRESENTATION = 2;
|
|
252
|
+
|
|
253
|
+
// A median task that read next to nothing makes every ratio against it huge (a median of 4 bytes
|
|
254
|
+
// against a 1 MB task reads as 250000x). Below these floors the median task is read as having
|
|
255
|
+
// read almost nothing: there is no ratio to take, and a task counts as having read data only from
|
|
256
|
+
// the floors up.
|
|
257
|
+
const MIN_VOLUME_BYTES = 1024 * 1024;
|
|
258
|
+
const MIN_VOLUME_RECORDS = 1000;
|
|
259
|
+
|
|
260
|
+
// Why the stage's slow tasks (non-failed, over TAIL_FACTOR x P50) were slow, from what each task
|
|
261
|
+
// logged. A task's excess is its duration over P50. Four causes claim it, in this order so no
|
|
262
|
+
// millisecond counts twice:
|
|
263
|
+
// 1. Data: had run time scaled with data volume, the task would have taken P50 x (volume ratio)
|
|
264
|
+
// against the median task, with volume the task's input plus shuffle-read, in bytes or in
|
|
265
|
+
// records, whichever is further above the median. This is the definition Spark's UI and AQE
|
|
266
|
+
// use for skew (a partition far larger than the median one), applied to run time.
|
|
267
|
+
// 2. GC time over the median task's.
|
|
268
|
+
// 3. Shuffle fetch wait over the median task's.
|
|
269
|
+
// 4. Host: what is left of the tail tasks on the one host that holds most of the tail.
|
|
270
|
+
// With a median task that read almost nothing there is no ratio to take, so GC and fetch wait claim their
|
|
271
|
+
// excess first and a task that read data owns what they leave: the time was GC or waiting unless
|
|
272
|
+
// the data is all that is left to explain it.
|
|
273
|
+
// Null when the stage has no tail. `tasks` is consumed once.
|
|
274
|
+
export function attributeTail(tasks , p50 ) {
|
|
275
|
+
const all = [];
|
|
276
|
+
const tail = [];
|
|
277
|
+
for (const t of tasks) {
|
|
278
|
+
if (t.failed) continue; // a failed attempt's metrics stop where it died
|
|
279
|
+
all.push(t);
|
|
280
|
+
if (t.duration > TAIL_FACTOR * p50) tail.push(t);
|
|
281
|
+
}
|
|
282
|
+
if (tail.length === 0) return null;
|
|
283
|
+
|
|
284
|
+
const bytesOf = (t ) => t.inputBytes + t.shuffleRead;
|
|
285
|
+
const recordsOf = (t ) => t.inputRecords + t.shuffleReadRecords;
|
|
286
|
+
const medianBytes = medianOf(all, bytesOf);
|
|
287
|
+
const medianRecords = medianOf(all, recordsOf);
|
|
288
|
+
const medianGc = medianOf(all, (t) => t.gcTime);
|
|
289
|
+
const medianFetch = medianOf(all, (t) => t.fetchWaitTime);
|
|
290
|
+
const bytesComparable = medianBytes >= MIN_VOLUME_BYTES;
|
|
291
|
+
const recordsComparable = medianRecords >= MIN_VOLUME_RECORDS;
|
|
292
|
+
const hasVolume = bytesComparable || recordsComparable;
|
|
293
|
+
const volumeRatio = (t ) => Math.max(
|
|
294
|
+
bytesComparable ? bytesOf(t) / medianBytes : 0,
|
|
295
|
+
recordsComparable ? recordsOf(t) / medianRecords : 0,
|
|
296
|
+
);
|
|
297
|
+
const readsData = (t ) => bytesOf(t) >= MIN_VOLUME_BYTES || recordsOf(t) >= MIN_VOLUME_RECORDS;
|
|
298
|
+
|
|
299
|
+
const tailHosts = new Map ();
|
|
300
|
+
const allHosts = new Map ();
|
|
301
|
+
for (const t of all) if (t.host) allHosts.set(t.host, (allHosts.get(t.host) ?? 0) + 1);
|
|
302
|
+
for (const t of tail) if (t.host) tailHosts.set(t.host, (tailHosts.get(t.host) ?? 0) + 1);
|
|
303
|
+
let topHost = null;
|
|
304
|
+
for (const [host, n] of tailHosts) if (topHost === null || n > tailHosts.get(topHost) ) topHost = host;
|
|
305
|
+
const hostConcentrated = topHost !== null
|
|
306
|
+
&& tailHosts.get(topHost) >= TAIL_HOST_MIN_TASKS
|
|
307
|
+
&& tailHosts.get(topHost) / tail.length >= TAIL_HOST_MIN_TAIL_SHARE
|
|
308
|
+
&& (tailHosts.get(topHost) / tail.length) / (allHosts.get(topHost) / all.length) >= TAIL_HOST_MIN_OVERREPRESENTATION;
|
|
309
|
+
|
|
310
|
+
let excessMs = 0, dataMs = 0, gcMs = 0, fetchWaitMs = 0, hostMs = 0, cpuNs = 0, runMs = 0;
|
|
311
|
+
const ratios = [];
|
|
312
|
+
for (const t of tail) {
|
|
313
|
+
const excess = t.duration - p50;
|
|
314
|
+
excessMs += excess;
|
|
315
|
+
let left = excess;
|
|
316
|
+
if (hasVolume) {
|
|
317
|
+
const ratio = volumeRatio(t);
|
|
318
|
+
ratios.push(ratio);
|
|
319
|
+
const data = Math.min(left, Math.max(0, p50 * (ratio - 1)));
|
|
320
|
+
dataMs += data; left -= data;
|
|
321
|
+
}
|
|
322
|
+
const gc = Math.min(left, Math.max(0, t.gcTime - medianGc));
|
|
323
|
+
gcMs += gc; left -= gc;
|
|
324
|
+
const fetch = Math.min(left, Math.max(0, t.fetchWaitTime - medianFetch));
|
|
325
|
+
fetchWaitMs += fetch; left -= fetch;
|
|
326
|
+
if (!hasVolume && readsData(t)) { dataMs += left; left = 0; }
|
|
327
|
+
if (hostConcentrated && t.host === topHost) { hostMs += left; }
|
|
328
|
+
cpuNs += t.executorCpuTime;
|
|
329
|
+
runMs += t.executorRunTime;
|
|
330
|
+
}
|
|
331
|
+
ratios.sort((a, b) => a - b);
|
|
332
|
+
return {
|
|
333
|
+
tasks: tail.length, excessMs, dataMs, gcMs, fetchWaitMs, hostMs,
|
|
334
|
+
host: hostConcentrated ? topHost : null,
|
|
335
|
+
hostTasks: hostConcentrated ? tailHosts.get(topHost ) : 0,
|
|
336
|
+
dataRatio: hasVolume ? medianOfSorted(Float64Array.from(ratios)) : null,
|
|
337
|
+
cpuPct: cpuNs > 0 && runMs > 0 ? Math.min(100, (cpuNs / 1e6 / runMs) * 100) : null,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function medianOf(tasks , valueOf ) {
|
|
342
|
+
return medianOfSorted(Float64Array.from(tasks, valueOf).sort());
|
|
343
|
+
}
|
|
344
|
+
|
|
213
345
|
// Wall-clock time during which at least one of the stage's tasks was running: the union of its
|
|
214
346
|
// [launch, finish) intervals. A stage's submittedAt..completedAt window also covers time it sat
|
|
215
347
|
// open with no task running (waiting for a free slot, or between retried tasks), which no
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// removed) and the token sets its similarity scores read. Pure.
|
|
4
4
|
|
|
5
5
|
import { cyrb53 } from './string-hash.js';
|
|
6
|
-
import { normalizeStageName, } from './stage-identity.js';
|
|
6
|
+
import { normalizeStageName, normalizedDetailOf, } from './stage-identity.js';
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
// Plumbing nodes: codegen boundaries and input adapters change with how Spark fuses a stage, not with
|
|
@@ -43,7 +43,7 @@ export function structuralKey(nodes ) {
|
|
|
43
43
|
const digestOf = (node ) => {
|
|
44
44
|
let d = digests.get(node);
|
|
45
45
|
if (d === undefined) {
|
|
46
|
-
d = cyrb53(JSON.stringify([normalizeStageName(node.name ?? ''),
|
|
46
|
+
d = cyrb53(JSON.stringify([normalizeStageName(node.name ?? ''), attributeNamesOf(node), below(node).sort()]));
|
|
47
47
|
digests.set(node, d);
|
|
48
48
|
}
|
|
49
49
|
return d;
|
|
@@ -53,6 +53,20 @@ export function structuralKey(nodes ) {
|
|
|
53
53
|
return cyrb53(JSON.stringify(roots));
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// A node's attribute names are read by the structural key of every stage it ran in and by the
|
|
57
|
+
// execution's plan structure; a node is never mutated after the parser posts it.
|
|
58
|
+
const attributeNamesCache = new WeakMap ();
|
|
59
|
+
|
|
60
|
+
/** `attributeNames` of a plan node's detail, memoized per node. The array is shared: do not change it. */
|
|
61
|
+
export function attributeNamesOf(node ) {
|
|
62
|
+
let names = attributeNamesCache.get(node);
|
|
63
|
+
if (names === undefined) {
|
|
64
|
+
names = attributeNames(node.detail ?? '');
|
|
65
|
+
attributeNamesCache.set(node, names);
|
|
66
|
+
}
|
|
67
|
+
return names;
|
|
68
|
+
}
|
|
69
|
+
|
|
56
70
|
const TOKEN_SPLIT = /[^A-Za-z0-9_.$]+/;
|
|
57
71
|
|
|
58
72
|
/** Sorted distinct tokens of a stage's attributed nodes (name and normalized detail) and its name.
|
|
@@ -64,7 +78,7 @@ export function detailTokens(stageName , nodes
|
|
|
64
78
|
for (const node of nodes) {
|
|
65
79
|
if (isPlumbing(node)) continue;
|
|
66
80
|
add(normalizeStageName(node.name ?? ''));
|
|
67
|
-
add(
|
|
81
|
+
add(normalizedDetailOf(node, normalize));
|
|
68
82
|
}
|
|
69
83
|
return [...tokens].sort();
|
|
70
84
|
}
|
|
@@ -88,11 +88,17 @@ export function tunedThresholdsOf(entry , overrides
|
|
|
88
88
|
return Object.keys(tuned).length > 0 ? tuned : null;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
// straggler judges a tail with skew's resolved thresholds (DetectorCtx.skewThresholds), so tuning skew
|
|
92
|
+
// changes which tails it reports without any `suppressedBy` link.
|
|
93
|
+
const THRESHOLD_DEPENDENCY = { straggler: 'skew' };
|
|
94
|
+
|
|
95
|
+
/** The tuned thresholds an entry's findings carry: its own, plus its `suppressedBy` entry's or the
|
|
96
|
+
* entry it reads thresholds from (named `<entry>.<threshold>`), since tuning either changes which
|
|
97
|
+
* of them survive. */
|
|
93
98
|
export function findingTunedThresholds(entry , overrides ) {
|
|
94
99
|
const own = tunedThresholdsOf(entry, overrides);
|
|
95
|
-
const
|
|
100
|
+
const suppressorType = entry.suppressedBy ?? THRESHOLD_DEPENDENCY[entry.type];
|
|
101
|
+
const suppressor = suppressorType ? entries.find((d) => d.type === suppressorType) : undefined;
|
|
96
102
|
const bySuppressor = suppressor ? tunedThresholdsOf(suppressor, overrides) : null;
|
|
97
103
|
if (!suppressor || !bySuppressor) return own;
|
|
98
104
|
const prefixed = Object.fromEntries(Object.entries(bySuppressor).map(([name, t]) => [`${suppressor.type}.${name}`, t]));
|
package/vendor-core/types.js
CHANGED
|
@@ -43,8 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
// Contract-pinned evidence `eventType`: the same fixed set as the parser's
|
|
45
45
|
// `evidenceInputs` counter keys, so provenance stays addressable against the
|
|
46
|
-
// documented `{ eventType, count }` shape
|
|
47
|
-
// from the counters they summarize).
|
|
46
|
+
// documented `{ eventType, count }` shape.
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
|
|
@@ -88,10 +87,10 @@
|
|
|
88
87
|
|
|
89
88
|
|
|
90
89
|
|
|
91
|
-
|
|
90
|
+
|
|
92
91
|
|
|
93
92
|
|
|
94
|
-
|
|
93
|
+
|
|
95
94
|
|
|
96
95
|
|
|
97
96
|
|
|
@@ -120,7 +119,7 @@
|
|
|
120
119
|
|
|
121
120
|
|
|
122
121
|
|
|
123
|
-
|
|
122
|
+
|
|
124
123
|
|
|
125
124
|
|
|
126
125
|
|
|
@@ -131,20 +130,51 @@
|
|
|
131
130
|
|
|
132
131
|
|
|
133
132
|
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
134
136
|
|
|
135
137
|
|
|
136
138
|
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
// The tail of a stage: its non-failed tasks over TAIL_FACTOR x P50. Each cause is the summed time
|
|
142
|
+
// (ms) of the tail's excess over P50 that the cause accounts for, taken in the order data, GC, fetch
|
|
143
|
+
// wait, host so that no millisecond counts twice; what none of them accounts for is
|
|
144
|
+
// excessMs - dataMs - gcMs - fetchWaitMs - hostMs.
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
137
165
|
|
|
138
166
|
|
|
139
167
|
|
|
140
168
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
169
|
+
|
|
170
|
+
|
|
144
171
|
|
|
145
172
|
|
|
146
173
|
|
|
147
|
-
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
148
178
|
|
|
149
179
|
|
|
150
180
|
|
|
@@ -161,6 +191,8 @@
|
|
|
161
191
|
|
|
162
192
|
|
|
163
193
|
|
|
194
|
+
|
|
195
|
+
|
|
164
196
|
|
|
165
197
|
|
|
166
198
|
|
|
@@ -179,19 +211,14 @@
|
|
|
179
211
|
|
|
180
212
|
|
|
181
213
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
192
219
|
|
|
193
220
|
|
|
194
|
-
|
|
221
|
+
|
|
195
222
|
|
|
196
223
|
|
|
197
224
|
|
|
@@ -289,6 +316,9 @@
|
|
|
289
316
|
|
|
290
317
|
|
|
291
318
|
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
292
322
|
|
|
293
323
|
|
|
294
324
|
|
|
@@ -316,6 +346,9 @@
|
|
|
316
346
|
|
|
317
347
|
|
|
318
348
|
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
|
|
319
352
|
|
|
320
353
|
|
|
321
354
|
|
|
@@ -332,15 +365,29 @@
|
|
|
332
365
|
|
|
333
366
|
|
|
334
367
|
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
335
372
|
|
|
336
373
|
|
|
337
374
|
|
|
338
375
|
|
|
339
376
|
|
|
340
377
|
|
|
341
|
-
|
|
342
|
-
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
|
|
343
383
|
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
|
|
344
391
|
|
|
345
392
|
|
|
346
393
|
// `Finding` is a union discriminated on `type`, one member per emitted finding type: see
|
|
@@ -353,7 +400,7 @@
|
|
|
353
400
|
|
|
354
401
|
|
|
355
402
|
|
|
356
|
-
|
|
403
|
+
|
|
357
404
|
|
|
358
405
|
|
|
359
406
|
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { mergeIntervals } from './intervals.js';
|
|
2
2
|
|
|
3
|
+
/** The union of the stages' [submittedAt, completedAt) windows, sorted: where stages were active. */
|
|
4
|
+
export function stageWindows(stages ) {
|
|
5
|
+
const intervals = [...stages.values()]
|
|
6
|
+
.filter((s) => s.submittedAt != null && s.completedAt != null)
|
|
7
|
+
.map((s) => [s.submittedAt , s.completedAt ]);
|
|
8
|
+
return mergeIntervals(intervals);
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
export function computeWallClock(app , stages ) {
|
|
4
12
|
const start = app?.startTime ?? 0;
|
|
5
13
|
const stageList = [...stages.values()].filter(s => s.submittedAt != null && s.completedAt != null);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Wasted core-hours summary. Pure, worker-agnostic reducer over the same inputs
|
|
2
|
-
// the memoryUtilization detector's idle-cores math uses:
|
|
2
|
+
// the memoryUtilization detector's idle-cores math uses: allocated core-time vs.
|
|
3
3
|
// core-time that actually ran tasks. Feeds a report widget only, no detector.
|
|
4
4
|
|
|
5
|
+
import { allocatedCoreMs } from './allocation.js';
|
|
5
6
|
import { computePeakConcurrentCores } from './core-count.js';
|
|
6
7
|
import { MS_PER_CORE_HOUR } from './format-utils.js';
|
|
7
8
|
|
|
@@ -32,29 +33,28 @@ const EMPTY = {
|
|
|
32
33
|
// SparkAppInfo | null before parsing completes), which the guard below already
|
|
33
34
|
// tolerates. `resources` is on app's shape so the computePeakConcurrentCores
|
|
34
35
|
// pass-through type-checks; real app objects always carry it. An omitted
|
|
35
|
-
// `executorsRemoved` means no executor left
|
|
36
|
+
// `executorsRemoved` means no executor left.
|
|
36
37
|
export function computeWastedCoreHours(
|
|
37
|
-
app
|
|
38
|
+
app ,
|
|
38
39
|
executorsAdded = [],
|
|
39
40
|
runAggregates ,
|
|
40
41
|
executorsRemoved = [],
|
|
41
42
|
) {
|
|
42
|
-
// Nullish (not falsy) guard on times: a literal startTime:0 is valid.
|
|
43
43
|
if (!runAggregates || app?.startTime == null || app?.endTime == null) return EMPTY;
|
|
44
44
|
const appDurationMs = app.endTime - app.startTime;
|
|
45
45
|
if (appDurationMs <= 0) return EMPTY;
|
|
46
46
|
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
|
|
47
|
+
// Capacity is the run's allocation (cores x time alive), the same as the idle findings. The
|
|
48
|
+
// application end is set here, so the allocation never needs the stages to find where a log stops.
|
|
49
|
+
const allocatedMs = allocatedCoreMs({ app, stages: new Map(), executors: { added: executorsAdded, removed: executorsRemoved } });
|
|
50
|
+
if (allocatedMs == null) return EMPTY;
|
|
51
|
+
// Peak concurrent cores, reported as the cluster size: an executor replaced mid-run counts once.
|
|
50
52
|
const totalCores = computePeakConcurrentCores(app, executorsAdded, executorsRemoved);
|
|
51
|
-
if (totalCores <= 0) return EMPTY;
|
|
52
53
|
|
|
53
|
-
const totalCoreHours =
|
|
54
|
+
const totalCoreHours = allocatedMs / MS_PER_CORE_HOUR;
|
|
54
55
|
const usefulCoreHours = (runAggregates.busyCoreMs ?? 0) / MS_PER_CORE_HOUR;
|
|
55
|
-
// Clamp:
|
|
56
|
-
//
|
|
57
|
-
// src/efficiency-model.js).
|
|
56
|
+
// Clamp: busyCoreMs is measured from task events while the allocation comes from executor
|
|
57
|
+
// events, so the difference can dip below zero (same guard as efficiency-model.ts).
|
|
58
58
|
const wastedCoreHours = Math.max(0, totalCoreHours - usefulCoreHours);
|
|
59
59
|
|
|
60
60
|
const topStages = Object.entries(runAggregates.perStage ?? {})
|