diff --git a/packages/twenty-front/src/testing/profiling/components/ProfilingQueueEffect.tsx b/packages/twenty-front/src/testing/profiling/components/ProfilingQueueEffect.tsx
index a00f22aaf..22307b316 100644
--- a/packages/twenty-front/src/testing/profiling/components/ProfilingQueueEffect.tsx
+++ b/packages/twenty-front/src/testing/profiling/components/ProfilingQueueEffect.tsx
@@ -2,7 +2,7 @@ import { useEffect } from 'react';
import { useRecoilState } from 'recoil';
import { TIME_BETWEEN_TEST_RUNS_IN_MS } from '~/testing/profiling/constants/TimeBetweenTestRunsInMs';
-import { currentProfilingRunIndexState } from '~/testing/profiling/states/currentProfilingRunState';
+import { currentProfilingRunIndexState } from '~/testing/profiling/states/currentProfilingRunIndexState';
import { profilingQueueState } from '~/testing/profiling/states/profilingQueueState';
import { profilingSessionRunsState } from '~/testing/profiling/states/profilingSessionRunsState';
import { profilingSessionStatusState } from '~/testing/profiling/states/profilingSessionStatusState';
@@ -12,10 +12,12 @@ export const ProfilingQueueEffect = ({
profilingId,
numberOfTestsPerRun,
numberOfRuns,
+ warmUpRounds,
}: {
profilingId: string;
numberOfTestsPerRun: number;
numberOfRuns: number;
+ warmUpRounds: number;
}) => {
const [currentProfilingRunIndex, setCurrentProfilingRunIndex] =
useRecoilState(currentProfilingRunIndexState);
@@ -38,9 +40,9 @@ export const ProfilingQueueEffect = ({
setCurrentProfilingRunIndex(0);
const newTestRuns = [
- 'warm-up-1',
- 'warm-up-2',
- 'warm-up-3',
+ ...[
+ ...Array.from({ length: warmUpRounds }, (_, i) => `warm-up-${i}`),
+ ],
...[
...Array.from({ length: numberOfRuns }, (_, i) => `real-run-${i}`),
],
@@ -76,9 +78,13 @@ export const ProfilingQueueEffect = ({
return;
}
- await new Promise((resolve) =>
- setTimeout(resolve, TIME_BETWEEN_TEST_RUNS_IN_MS),
- );
+ const timeInMs = profilingSessionRuns[
+ currentProfilingRunIndex
+ ].startsWith('warm-up')
+ ? TIME_BETWEEN_TEST_RUNS_IN_MS * 2
+ : TIME_BETWEEN_TEST_RUNS_IN_MS;
+
+ await new Promise((resolve) => setTimeout(resolve, timeInMs));
const nextIndex = currentProfilingRunIndex + 1;
@@ -109,6 +115,7 @@ export const ProfilingQueueEffect = ({
profilingSessionRuns,
setProfilingSessionRuns,
numberOfRuns,
+ warmUpRounds,
]);
return <>>;
diff --git a/packages/twenty-front/src/testing/profiling/components/ProfilingReporter.tsx b/packages/twenty-front/src/testing/profiling/components/ProfilingReporter.tsx
index 7c1ea5bdb..91c6e26e3 100644
--- a/packages/twenty-front/src/testing/profiling/components/ProfilingReporter.tsx
+++ b/packages/twenty-front/src/testing/profiling/components/ProfilingReporter.tsx
@@ -3,7 +3,9 @@ import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
import { PROFILING_REPORTER_DIV_ID } from '~/testing/profiling/constants/ProfilingReporterDivId';
+import { currentProfilingRunIndexState } from '~/testing/profiling/states/currentProfilingRunIndexState';
import { profilingSessionDataPointsState } from '~/testing/profiling/states/profilingSessionDataPointsState';
+import { profilingSessionStatusState } from '~/testing/profiling/states/profilingSessionStatusState';
import { computeProfilingReport } from '~/testing/profiling/utils/computeProfilingReport';
const StyledTable = styled.table`
@@ -24,6 +26,12 @@ export const ProfilingReporter = () => {
profilingSessionDataPointsState,
);
+ const [currentProfilingRunIndex] = useRecoilState(
+ currentProfilingRunIndexState,
+ );
+
+ const [profilingSessionStatus] = useRecoilState(profilingSessionStatusState);
+
const profilingReport = useMemo(
() => computeProfilingReport(profilingSessionDataPoints),
[profilingSessionDataPoints],
@@ -34,6 +42,10 @@ export const ProfilingReporter = () => {
data-profiling-report={JSON.stringify(profilingReport)}
id={PROFILING_REPORTER_DIV_ID}
>
+
Profiling report
+
+ Run #{currentProfilingRunIndex} - Status {profilingSessionStatus}
+
@@ -46,6 +58,7 @@ export const ProfilingReporter = () => {
| P95 |
P99 |
Max |
+ Variance |
@@ -59,6 +72,9 @@ export const ProfilingReporter = () => {
{Math.round(profilingReport.total.p95 * 1000) / 1000}ms |
{Math.round(profilingReport.total.p99 * 1000) / 1000}ms |
{Math.round(profilingReport.total.max * 1000) / 1000}ms |
+
+ {Math.round(profilingReport.total.variance * 1000000) / 1000000}
+ |
{Object.entries(profilingReport.runs).map(([runName, report]) => (
@@ -71,6 +87,7 @@ export const ProfilingReporter = () => {
| {Math.round(report.p95 * 1000) / 1000}ms |
{Math.round(report.p99 * 1000) / 1000}ms |
{Math.round(report.max * 1000) / 1000}ms |
+ {Math.round(report.variance * 1000000) / 1000000} |
))}
diff --git a/packages/twenty-front/src/testing/profiling/states/currentProfilingRunIndexState.ts b/packages/twenty-front/src/testing/profiling/states/currentProfilingRunIndexState.ts
new file mode 100644
index 000000000..da05d7303
--- /dev/null
+++ b/packages/twenty-front/src/testing/profiling/states/currentProfilingRunIndexState.ts
@@ -0,0 +1,6 @@
+import { atom } from 'recoil';
+
+export const currentProfilingRunIndexState = atom({
+ key: 'currentProfilingRunIndexState',
+ default: 0,
+});
diff --git a/packages/twenty-front/src/testing/profiling/types/ProfilingReportByRun.ts b/packages/twenty-front/src/testing/profiling/types/ProfilingReportByRun.ts
index f2714c702..302a3361e 100644
--- a/packages/twenty-front/src/testing/profiling/types/ProfilingReportByRun.ts
+++ b/packages/twenty-front/src/testing/profiling/types/ProfilingReportByRun.ts
@@ -10,6 +10,7 @@ export type ProfilingReportItem = {
p99: number;
min: number;
max: number;
+ variance: number;
};
export type ProfilingReport = {
diff --git a/packages/twenty-front/src/testing/profiling/utils/computeProfilingReport.ts b/packages/twenty-front/src/testing/profiling/utils/computeProfilingReport.ts
index d9afc33be..3c8ea9c69 100644
--- a/packages/twenty-front/src/testing/profiling/utils/computeProfilingReport.ts
+++ b/packages/twenty-front/src/testing/profiling/utils/computeProfilingReport.ts
@@ -1,7 +1,10 @@
import { ProfilingDataPoint } from '~/testing/profiling/types/ProfilingDataPoint';
import { ProfilingReport } from '~/testing/profiling/types/ProfilingReportByRun';
-export const computeProfilingReport = (dataPoints: ProfilingDataPoint[]) => {
+export const computeProfilingReport = (
+ dataPoints: ProfilingDataPoint[],
+ varianceThreshold?: number,
+) => {
const profilingReport = { total: {}, runs: {} } as ProfilingReport;
for (const dataPoint of dataPoints) {
@@ -27,8 +30,9 @@ export const computeProfilingReport = (dataPoints: ProfilingDataPoint[]) => {
const numberOfIds = ids.length;
- profilingReport.runs[runName].average =
- profilingReport.runs[runName].sum / numberOfIds;
+ const mean = profilingReport.runs[runName].sum / numberOfIds;
+
+ profilingReport.runs[runName].average = mean;
profilingReport.runs[runName].min = Math.min(
...Object.values(profilingReport.runs[runName].sumById),
@@ -38,6 +42,14 @@ export const computeProfilingReport = (dataPoints: ProfilingDataPoint[]) => {
...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);
@@ -55,9 +67,9 @@ export const computeProfilingReport = (dataPoints: ProfilingDataPoint[]) => {
runName.startsWith('real-run'),
);
- const runsForTotal = runNamesForTotal.map(
- (runName) => profilingReport.runs[runName],
- );
+ 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),
@@ -82,6 +94,9 @@ export const computeProfilingReport = (dataPoints: ProfilingDataPoint[]) => {
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;
diff --git a/packages/twenty-front/src/testing/profiling/utils/getProfilingStory.ts b/packages/twenty-front/src/testing/profiling/utils/getProfilingStory.ts
index 4c5cd0a82..959c7f9c2 100644
--- a/packages/twenty-front/src/testing/profiling/utils/getProfilingStory.ts
+++ b/packages/twenty-front/src/testing/profiling/utils/getProfilingStory.ts
@@ -11,19 +11,21 @@ export const getProfilingStory = ({
averageThresholdInMs,
numberOfRuns,
numberOfTestsPerRun,
+ warmUpRounds,
}: {
componentName: string;
p95ThresholdInMs?: number;
averageThresholdInMs: number;
numberOfRuns: number;
numberOfTestsPerRun: number;
+ warmUpRounds?: number;
}): StoryObj => ({
decorators: [ProfilerDecorator],
parameters: {
numberOfRuns,
numberOfTests: numberOfTestsPerRun,
componentName,
- chromatic: { disableSnapshot: true },
+ warmUpRounds,
},
play: async ({ canvasElement }) => {
await findByTestId(
diff --git a/yarn.lock b/yarn.lock
index 79bc74bda..d28dfe038 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -46630,6 +46630,7 @@ __metadata:
type-fest: "npm:4.10.1"
typeorm: "npm:^0.3.17"
typescript: "npm:5.3.3"
+ use-context-selector: "npm:^2.0.0"
use-debounce: "npm:^10.0.0"
uuid: "npm:^9.0.0"
vite: "npm:^5.0.0"
@@ -47659,6 +47660,16 @@ __metadata:
languageName: node
linkType: hard
+"use-context-selector@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "use-context-selector@npm:2.0.0"
+ peerDependencies:
+ react: ">=18.0.0"
+ scheduler: ">=0.19.0"
+ checksum: 4eb6054ab8996ae8b3f87f9d102e576066e5a8b9db5db2c891128ae920bd64bcdcb4e93a13bc99658ef16280929a8331fc8ac45177f4acd716c425b1bc31135a
+ languageName: node
+ linkType: hard
+
"use-debounce@npm:^10.0.0":
version: 10.0.0
resolution: "use-debounce@npm:10.0.0"