feat: add PlanningDurationService for estimating planning duration
- Implemented PlanningDurationService to provide an indicative wait time before calculation based on user input and calendar settings. - Introduced duration estimation logic that considers horizon dates, balances, and rules without triggering a calculation. - Enhanced user input component to display estimated duration using the new service. - Updated translation files to include new duration estimate strings in multiple languages. - Added tests for PlanningDurationService to ensure accurate duration estimation and calibration. - Refactored leave planner service to remove hardcoded deadlines and improve worker responsiveness.
This commit is contained in:
1 parent
2edf2004f5
commit
bc8570d8ca
29 files changed
+1064
-123
No files matched your search
@@ -17,6 +17,8 @@ export interface BenchmarkMeasurement {
|
||||
planningMs: number;
|
||||
traceDeliveryMs: number;
|
||||
maxUiDelayMs: number;
|
||||
/** Chromium's main-thread heap only; worker memory needs a separate browser profile. */
|
||||
peakMainThreadHeapBytes?: number;
|
||||
planningWorkMs?: number;
|
||||
traceCaptureMs?: number;
|
||||
traceMaterializationMs?: number;
|
||||
@@ -147,6 +149,25 @@ export function benchmarkScenarios(): BenchmarkScenario[] {
|
||||
})),
|
||||
},
|
||||
},
|
||||
...[2, 3].map(
|
||||
(years): BenchmarkScenario => ({
|
||||
name: years === 2 ? 'two years' : 'three years',
|
||||
request: {
|
||||
horizon: { start: '2024-01-01', end: `${2024 + years}-01-01` },
|
||||
balances: Array.from({ length: years }, (_, index) => 2024 + index).flatMap(
|
||||
(year) =>
|
||||
(['cp', 'rtt'] as const).map((type) => ({
|
||||
id: `${type}-${year}`,
|
||||
type,
|
||||
quantity: type === 'cp' ? 20 : 10,
|
||||
availableFrom: `${year}-01-01`,
|
||||
expiryDate: `${year}-12-31`,
|
||||
})),
|
||||
),
|
||||
rules: [],
|
||||
},
|
||||
}),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -200,11 +221,17 @@ async function measureRepetition(
|
||||
const wallStart = performance.now();
|
||||
let lastTick = wallStart;
|
||||
let maxUiDelayMs = 0;
|
||||
let peakMainThreadHeapBytes: number | undefined;
|
||||
const measureDelay = () => {
|
||||
const current = performance.now();
|
||||
maxUiDelayMs = Math.max(maxUiDelayMs, current - lastTick - 50);
|
||||
lastTick = current;
|
||||
const heap = (performance as Performance & { memory?: { usedJSHeapSize: number } }).memory
|
||||
?.usedJSHeapSize;
|
||||
if (heap !== undefined)
|
||||
peakMainThreadHeapBytes = Math.max(peakMainThreadHeapBytes ?? 0, heap);
|
||||
};
|
||||
measureDelay();
|
||||
const heartbeat = setInterval(measureDelay, 50);
|
||||
try {
|
||||
const preparationStart = performance.now();
|
||||
@@ -242,6 +269,7 @@ async function measureRepetition(
|
||||
planningMs,
|
||||
traceDeliveryMs,
|
||||
maxUiDelayMs,
|
||||
peakMainThreadHeapBytes,
|
||||
...timings,
|
||||
wallMs,
|
||||
...summary,
|
||||
@@ -258,7 +286,7 @@ async function measureRepetition(
|
||||
|
||||
export function benchmarkReport(measurements: BenchmarkMeasurement[]): string {
|
||||
const header =
|
||||
'scenario\trepetition\tpreparation_ms\tplanning_ms\ttrace_delivery_ms\twall_ms\toutcome\tlast_stage\tplacements\tdeterministic\ttrace_status\ttrace_candidates\tmax_ui_delay_ms\tplanning_work_ms\ttrace_capture_ms\ttrace_materialization_ms\ttrace_transfer_ms';
|
||||
'scenario\trepetition\tpreparation_ms\tplanning_ms\ttrace_delivery_ms\twall_ms\toutcome\tlast_stage\tplacements\tdeterministic\ttrace_status\ttrace_candidates\tmax_ui_delay_ms\tplanning_work_ms\ttrace_capture_ms\ttrace_materialization_ms\ttrace_transfer_ms\tpeak_main_thread_heap_bytes';
|
||||
return [
|
||||
header,
|
||||
...measurements.map((item) =>
|
||||
@@ -280,6 +308,7 @@ export function benchmarkReport(measurements: BenchmarkMeasurement[]): string {
|
||||
item.traceCaptureMs?.toFixed(1) ?? '',
|
||||
item.traceMaterializationMs?.toFixed(1) ?? '',
|
||||
item.traceTransferMs?.toFixed(1) ?? '',
|
||||
item.peakMainThreadHeapBytes ?? '',
|
||||
].join('\t'),
|
||||
),
|
||||
].join('\n');
|
||||
|
||||
Reference in new issue
Block a user