Skip to content

Commit

Permalink
Do not compute individual durations
Browse files Browse the repository at this point in the history
  • Loading branch information
Jym77 committed Jan 15, 2025
1 parent e72e461 commit 16affd3
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 126 deletions.
7 changes: 7 additions & 0 deletions .changeset/gold-schools-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@siteimprove/alfa-test-utils": minor
---

**Breaking:** Individual rules durations are not recorded anymore during audits.

This means that `Audit#durations` directly contains the common keys.
41 changes: 5 additions & 36 deletions docs/review/api/alfa-test-utils.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { Page } from '@siteimprove/alfa-web';
import { Performance as Performance_2 } from '@siteimprove/alfa-performance';
import type { Predicate } from '@siteimprove/alfa-predicate';
import { Result } from '@siteimprove/alfa-result';
import type { Rule } from '@siteimprove/alfa-act';
import { Sequence } from '@siteimprove/alfa-sequence';

// @public
Expand Down Expand Up @@ -167,42 +166,17 @@ export namespace Outcomes {
// @public
export namespace Performance {
const // (undocumented)
durationKeys: readonly ["applicability", "expectation", "total"];
// Warning: (ae-incompatible-release-tags) The symbol "CommonDurations" is marked as @public, but its signature references "Performance" which is marked as @internal
//
// (undocumented)
export type CommonDurations = {
[K in CommonKeys]: number;
};
commonKeys: readonly ["cascade", "aria-tree", "total"];
// @internal (undocumented)
export type CommonKeys = (typeof commonKeys)[number];
// @internal (undocumented)
export type DurationKey = (typeof durationKeys)[number];
// Warning: (ae-incompatible-release-tags) The symbol "Durations" is marked as @public, but its signature references "Performance" which is marked as @internal
export type Durations = {
common: CommonDurations;
rules: RulesDurations;
[K in CommonKeys]: number;
};
const // (undocumented)
commonKeys: readonly ["cascade", "aria-tree", "total"];
// @internal (undocumented)
export function empty(): Durations;
// @internal (undocumented)
export function emptyRuleDurations(): RuleDurations;
// @internal (undocumented)
export function recordCommon(durations: Durations): Performance_2<string>;
// @internal (undocumented)
export function recordRule(durations: Durations): Performance_2<RuleEvent>;
// Warning: (ae-incompatible-release-tags) The symbol "RuleDurations" is marked as @public, but its signature references "Performance" which is marked as @internal
//
// (undocumented)
export type RuleDurations = {
[K in DurationKey]: number;
};
// @internal (undocumented)
export type RuleEvent = Rule.Event<Flattened.Input, Flattened.Target, Flattened.Question, Flattened.Subject>;
export type RulesDurations = {
[key: string]: RuleDurations;
};
{};
}

Expand Down Expand Up @@ -238,6 +212,8 @@ export namespace SIP {
timestamp?: string;
httpsAgent?: Agent;
}): Promise<AxiosRequestConfig>;
// Warning: (ae-forgotten-export) The symbol "CamelCase" needs to be exported by the entry point index.d.ts
//
// (undocumented)
export type CommonDurations = {
[K in CamelCase<Performance.CommonKeys>]: number;
Expand All @@ -255,19 +231,12 @@ export namespace SIP {
Failed: number;
Passed: number;
CantTell: number;
Durations: RuleDurations;
}>;
SiteId?: number;
TestName?: string;
Version: `${number}.${number}.${number}`;
}
export function payload(audit: Audit | Audit.JSON, options: Partial<Options>, timestamp: string): Promise<Payload>;
// Warning: (ae-forgotten-export) The symbol "CamelCase" needs to be exported by the entry point index.d.ts
//
// (undocumented)
export type RuleDurations = {
[K in CamelCase<Performance.DurationKey>]: number;
};
{};
}
// (undocumented)
Expand Down
3 changes: 1 addition & 2 deletions packages/alfa-test-utils/src/audit/audit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ export namespace Audit {
export async function run(page: Page, options: Options = {}): Promise<Audit> {
const durations: Performance.Durations = Performance.empty();
const commonPerformance = Performance.recordCommon(durations);
const rulesPerformance = Performance.recordRule(durations);

const start = commonPerformance.mark("total").start;
sharedPerformance(commonPerformance, page);
Expand All @@ -151,7 +150,7 @@ export namespace Audit {
);

const audit = Sequence.from(
await alfaAudit.of(page, rulesToRun).evaluate(rulesPerformance)
await alfaAudit.of(page, rulesToRun).evaluate()
);
commonPerformance.measure("total", start);

Expand Down
62 changes: 4 additions & 58 deletions packages/alfa-test-utils/src/audit/performance.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import type { Rule } from "@siteimprove/alfa-act";
import { Array } from "@siteimprove/alfa-array";
import { Performance as alfaPerformance } from "@siteimprove/alfa-performance";
import type { Flattened } from "@siteimprove/alfa-rules";

const { isMeasure } = alfaPerformance.Measure;

Expand All @@ -11,81 +9,29 @@ const { isMeasure } = alfaPerformance.Measure;
* @public
*/
export namespace Performance {
const durationKeys = ["applicability", "expectation", "total"] as const;
/** @internal */
export type DurationKey = (typeof durationKeys)[number];
type RuleDurations = { [K in DurationKey]: number };

/**
* For each rule (key), records time taken for the applicability,
* the expectations, and total time.
*
* @public
*/
export type RulesDurations = { [key: string]: RuleDurations };

/** @internal */
export function emptyRuleDurations(): RuleDurations {
return { applicability: 0, expectation: 0, total: 0 };
}

const commonKeys = ["cascade", "aria-tree", "total"] as const;
/** @internal */
export type CommonKeys = (typeof commonKeys)[number];
type CommonDurations = { [K in CommonKeys]: number };

/**
* Records the duration of resolving the CSS cascade, building the accessibility
* tree, and running each rule.
*
* @remarks
* The cascade and accessibility tree are cached, so we store their performance
* separately to avoid unfairly "charging" the first rule to use and build them.
* tree, and running the full audit.
*
* @public
*/
export type Durations = { common: CommonDurations; rules: RulesDurations };
export type Durations = { [K in CommonKeys]: number };

/** @internal */
export function empty(): Durations {
return {
common: { cascade: 0, "aria-tree": 0, total: 0 },
rules: {},
};
}

/** @internal */
export type RuleEvent = Rule.Event<
Flattened.Input,
Flattened.Target,
Flattened.Question,
Flattened.Subject
>;

/** @internal */
export function recordRule(durations: Durations): alfaPerformance<RuleEvent> {
return alfaPerformance.of<Performance.RuleEvent>().on((entry) => {
if (isMeasure(entry)) {
const ruleId = entry.data.rule.uri;

if (durations.rules[ruleId] === undefined) {
durations.rules[ruleId] = emptyRuleDurations();
}
if (Array.includes(durationKeys, entry.data.name)) {
// Type is ensured by the previous test.
durations.rules[ruleId][entry.data.name as DurationKey] =
entry.duration;
}
}
});
return { cascade: 0, "aria-tree": 0, total: 0 };
}

/** @internal */
export function recordCommon(durations: Durations): alfaPerformance<string> {
return alfaPerformance.of<string>().on((entry) => {
if (isMeasure(entry) && Array.includes(commonKeys, entry.data)) {
// Type is ensured by the previous check
durations.common[entry.data as CommonKeys] = entry.duration;
durations[entry.data as CommonKeys] = entry.duration;
}
});
}
Expand Down
8 changes: 2 additions & 6 deletions packages/alfa-test-utils/src/report/sip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import type { CommitInformation } from "./commit-information.js";
export namespace SIP {
/** @internal */
export namespace Defaults {
export const URL =
"https://api.siteimprove.com/v2/a11y/AlfaDevCheck";
export const URL = "https://api.siteimprove.com/v2/a11y/AlfaDevCheck";
export const Title = "";
export const Name = undefined;
}
Expand Down Expand Up @@ -154,7 +153,6 @@ export namespace SIP {
*/
export namespace Metadata {
// We need to capitalize names for the API calls.
type RuleDurations = { [K in CamelCase<Performance.DurationKey>]: number };
type CommonDurations = { [K in CamelCase<Performance.CommonKeys>]: number };

/** @internal */
Expand Down Expand Up @@ -214,7 +212,6 @@ export namespace SIP {
Failed: number;
Passed: number;
CantTell: number;
Durations: RuleDurations;
}>;

/**
Expand Down Expand Up @@ -295,9 +292,8 @@ export namespace SIP {
).map(([RuleId, data]) => ({
RuleId,
...toCamelCase(data),
Durations: toCamelCase(audit.durations.rules[RuleId]),
})),
Durations: toCamelCase(audit.durations.common),
Durations: toCamelCase(audit.durations),
};

commitInfo.forEach((info) => (result.CommitInformation = info));
Expand Down
14 changes: 3 additions & 11 deletions packages/alfa-test-utils/test/audit/audit.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,9 @@ test(".run() build performance data", async (t) => {

// We cannot test real values due to instability, only checking they've been
// updated.
t.notEqual(actual.common.total, 0);
t.notEqual(actual.common.cascade, 0);
t.notEqual(actual.common["aria-tree"], 0);

t.deepEqual(Object.keys(actual.rules), [
"https://alfa.siteimprove.com/rules/sia-r2",
]);
const rule = actual.rules["https://alfa.siteimprove.com/rules/sia-r2"];
t.notEqual(rule.total, 0);
t.notEqual(rule.applicability, 0);
t.notEqual(rule.expectation, 0);
t.notEqual(actual.total, 0);
t.notEqual(actual.cascade, 0);
t.notEqual(actual["aria-tree"], 0);
});

test(".run() excludes occurrences in `<iframe>` by default", async (t) => {
Expand Down
15 changes: 2 additions & 13 deletions packages/alfa-test-utils/test/report/sip.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,7 @@ test("Metadata.payload() builds page URL from the page if specified", async (t)
test("Metadata.payload() includes global durations", async (t) => {
const actual = await Metadata.payload(
makeAudit({
durations: {
common: { cascade: 1, "aria-tree": 2, total: 3 },
rules: {},
},
durations: { cascade: 1, "aria-tree": 2, total: 3 },
}),
{},
timestamp
Expand All @@ -343,13 +340,7 @@ test("Metadata.payload() includes rule durations in aggregates", async (t) => {
["foo", { failed: 1, passed: 1, cantTell: 0 }],
["bar", { failed: 2, passed: 2, cantTell: 0 }],
]),
durations: {
common: { cascade: 1, "aria-tree": 1, total: 1 },
rules: {
foo: { applicability: 2, expectation: 2, total: 2 },
bar: { applicability: 3, expectation: 3, total: 3 },
},
},
durations: { cascade: 1, "aria-tree": 1, total: 1 },
}),
{},
timestamp
Expand All @@ -365,14 +356,12 @@ test("Metadata.payload() includes rule durations in aggregates", async (t) => {
Failed: 1,
Passed: 1,
CantTell: 0,
Durations: { Applicability: 2, Expectation: 2, Total: 2 },
},
{
RuleId: "bar",
Failed: 2,
Passed: 2,
CantTell: 0,
Durations: { Applicability: 3, Expectation: 3, Total: 3 },
},
],
})
Expand Down

0 comments on commit 16affd3

Please sign in to comment.