Files
twenty/packages/twenty-front/src/testing/profiling/utils/computeProfilingReport.ts
T
Lucas Bordeau de9321dcd9 Fixed sync between record value context selector and record store (#5517)
This PR introduces many improvements over the new profiling story
feature, with new tests and some refactor with main :
- Added use-context-selector for getting value faster in display fields
and created useRecordFieldValue() hook and RecordValueSetterEffect to
synchronize states
- Added performance test command in CI
- Refactored ExpandableList drill-downs with FieldFocusContext
- Refactored field button icon logic into getFieldButtonIcon util
- Added RelationFieldDisplay perf story
- Added RecordTableCell perf story
- First split test of useField.. hook with useRelationFieldDisplay()
- Fixed problem with set cell soft focus
- Isolated logic between display / soft focus and edit mode in the
related components to optimize performances for display mode.
- Added warmupRound config for performance story decorator
- Added variance in test reporting
2024-05-24 16:52:05 +02:00

104 lines
3.7 KiB
TypeScript

import { ProfilingDataPoint } from '~/testing/profiling/types/ProfilingDataPoint';
import { ProfilingReport } from '~/testing/profiling/types/ProfilingReportByRun';
export const computeProfilingReport = (
dataPoints: ProfilingDataPoint[],
varianceThreshold?: number,
) => {
const profilingReport = { total: {}, runs: {} } as ProfilingReport;
for (const dataPoint of dataPoints) {
profilingReport.runs[dataPoint.runName] = {
...profilingReport.runs[dataPoint.runName],
sumById: {
...profilingReport.runs[dataPoint.runName]?.sumById,
[dataPoint.id]:
(profilingReport.runs[dataPoint.runName]?.sumById?.[dataPoint.id] ??
0) + dataPoint.durationInMs,
},
sum:
(profilingReport.runs[dataPoint.runName]?.sum ?? 0) +
dataPoint.durationInMs,
};
}
for (const runName of Object.keys(profilingReport.runs)) {
const ids = Object.keys(profilingReport.runs[runName].sumById);
const valuesUnsorted = Object.values(profilingReport.runs[runName].sumById);
const valuesSortedAsc = [...valuesUnsorted].sort((a, b) => a - b);
const numberOfIds = ids.length;
const mean = profilingReport.runs[runName].sum / numberOfIds;
profilingReport.runs[runName].average = mean;
profilingReport.runs[runName].min = Math.min(
...Object.values(profilingReport.runs[runName].sumById),
);
profilingReport.runs[runName].max = Math.max(
...Object.values(profilingReport.runs[runName].sumById),
);
const intermediaryValuesForVariance = valuesUnsorted.map((value) =>
Math.pow(value - mean, 2),
);
profilingReport.runs[runName].variance =
intermediaryValuesForVariance.reduce((acc, curr) => acc + curr) /
numberOfIds;
const p50Index = Math.floor(numberOfIds * 0.5);
const p80Index = Math.floor(numberOfIds * 0.8);
const p90Index = Math.floor(numberOfIds * 0.9);
const p95Index = Math.floor(numberOfIds * 0.95);
const p99Index = Math.floor(numberOfIds * 0.99);
profilingReport.runs[runName].p50 = valuesSortedAsc[p50Index];
profilingReport.runs[runName].p80 = valuesSortedAsc[p80Index];
profilingReport.runs[runName].p90 = valuesSortedAsc[p90Index];
profilingReport.runs[runName].p95 = valuesSortedAsc[p95Index];
profilingReport.runs[runName].p99 = valuesSortedAsc[p99Index];
}
const runNamesForTotal = Object.keys(profilingReport.runs).filter((runName) =>
runName.startsWith('real-run'),
);
const runsForTotal = runNamesForTotal
.map((runName) => profilingReport.runs[runName])
.filter((run) => run.variance < (varianceThreshold ?? 0.2));
profilingReport.total = {
sum: Object.values(runsForTotal).reduce((acc, run) => acc + run.sum, 0),
average:
Object.values(runsForTotal).reduce((acc, run) => acc + run.average, 0) /
Object.keys(runsForTotal).length,
min: Math.min(...Object.values(runsForTotal).map((run) => run.min)),
max: Math.max(...Object.values(runsForTotal).map((run) => run.max)),
p50:
Object.values(runsForTotal).reduce((acc, run) => acc + run.p50, 0) /
Object.keys(runsForTotal).length,
p80:
Object.values(runsForTotal).reduce((acc, run) => acc + run.p80, 0) /
Object.keys(runsForTotal).length,
p90:
Object.values(runsForTotal).reduce((acc, run) => acc + run.p90, 0) /
Object.keys(runsForTotal).length,
p95:
Object.values(runsForTotal).reduce((acc, run) => acc + run.p95, 0) /
Object.keys(runsForTotal).length,
p99:
Object.values(runsForTotal).reduce((acc, run) => acc + run.p99, 0) /
Object.keys(runsForTotal).length,
dataPointCount: dataPoints.length,
variance:
runsForTotal.reduce((acc, run) => acc + run.variance, 0) /
runsForTotal.length,
};
return profilingReport;
};