Skip to content

Commit 96ddcac

Browse files
finnurbrekiDevtools-frontend LUCI CQ
authored andcommitted
[AskAi]: Agentize the Slow Css Selector insight.
Example response: https://screenshot.googleplex.com/3qg5YZ8nQn2qMwn Also fix obvious typo in one of the UIStrings. Fixed: 405920696 Change-Id: Ic619d063edbfaf0fd30090695e4ac489bb8c55a7 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6916500 Commit-Queue: Finnur Thorarinsson <finnur@chromium.org> Reviewed-by: Connor Clark <cjamcl@chromium.org>
1 parent c5997c8 commit 96ddcac

5 files changed

Lines changed: 120 additions & 3 deletions

File tree

front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,48 @@ no origins were preconnected.
843843
- https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preconnect/
844844
=== end content
845845

846+
Title: PerformanceInsightFormatter SlowCssSelector serializes correctly when there are no results
847+
Content:
848+
## Insight Title: CSS Selector costs
849+
850+
## Insight Summary:
851+
This insight identifies CSS selectors that are slowing down your page's rendering performance.
852+
853+
## Detailed analysis:
854+
No CSS selector data was found. CSS selector stats need to be enabled in the performance panel settings.
855+
856+
## Estimated savings: none
857+
858+
## External resources:
859+
- https://developer.chrome.com/docs/devtools/performance/selector-stats
860+
=== end content
861+
862+
Title: PerformanceInsightFormatter SlowCssSelector serializes the correct details when CSS selectors are found
863+
Content:
864+
## Insight Title: CSS Selector costs
865+
866+
## Insight Summary:
867+
This insight identifies CSS selectors that are slowing down your page's rendering performance.
868+
869+
## Detailed analysis:
870+
One or more slow CSS selectors were identified as negatively affecting page performance:
871+
872+
Top selector match attempt:
873+
169 attempts for selector: '.gb_Bd > :only-child'
874+
875+
Total:
876+
Elapsed time: 0.0 ms
877+
Match attempts: 2444
878+
Match count: 465
879+
880+
If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/devtools/performance/selector-stats) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.
881+
882+
## Estimated savings: none
883+
884+
## External resources:
885+
- https://developer.chrome.com/docs/devtools/performance/selector-stats
886+
=== end content
887+
846888
Title: PerformanceInsightFormatter ThirdParties serializes correctly when there are no results
847889
Content:
848890
## Insight Title: 3rd parties

front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,28 @@ describeWithEnvironment('PerformanceInsightFormatter', () => {
412412
});
413413
});
414414

415+
describe('SlowCssSelector', () => {
416+
it('serializes correctly when there are no results', async function() {
417+
const {parsedTrace, insights} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');
418+
assert.isOk(insights);
419+
const firstNav = getFirstOrError(parsedTrace.Meta.navigationsByNavigationId.values());
420+
const insight = getInsightOrError('SlowCSSSelector', insights, firstNav);
421+
const formatter = new PerformanceInsightFormatter(PERF_AGENT_UNIT_FORMATTERS, parsedTrace, insight);
422+
const output = formatter.formatInsight();
423+
snapshotTester.assert(this, output);
424+
});
425+
426+
it('serializes the correct details when CSS selectors are found', async function() {
427+
const {parsedTrace, insights} = await TraceLoader.traceEngine(this, 'selector-stats.json.gz');
428+
assert.isOk(insights);
429+
const firstNav = getFirstOrError(parsedTrace.Meta.navigationsByNavigationId.values());
430+
const insight = getInsightOrError('SlowCSSSelector', insights, firstNav);
431+
const formatter = new PerformanceInsightFormatter(PERF_AGENT_UNIT_FORMATTERS, parsedTrace, insight);
432+
const output = formatter.formatInsight();
433+
snapshotTester.assert(this, output);
434+
});
435+
});
436+
415437
describe('ThirdParties', () => {
416438
it('serializes correctly when there are no results', async function() {
417439
const {parsedTrace, insights} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');

front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,47 @@ export class PerformanceInsightFormatter {
319319
return output;
320320
}
321321

322+
/**
323+
* Create an AI prompt string out of the Slow CSS Selector Insight model to use with Ask AI.
324+
* Note: This function accesses the UIStrings within SlowCSSSelector to help build the
325+
* AI prompt, but does not (and should not) call i18nString to localize these strings. They
326+
* should all be sent in English (at least for now).
327+
* @param insight The Network Dependency Tree Insight Model to query.
328+
* @returns a string formatted for sending to Ask AI.
329+
*/
330+
formatSlowCssSelectorsInsight(insight: Trace.Insights.Models.SlowCSSSelector.SlowCSSSelectorInsightModel): string {
331+
let output = '';
332+
333+
if (!insight.topSelectorElapsedMs && !insight.topSelectorMatchAttempts) {
334+
return Trace.Insights.Models.SlowCSSSelector.UIStrings.enableSelectorData;
335+
}
336+
337+
output += 'One or more slow CSS selectors were identified as negatively affecting page performance:\n\n';
338+
339+
if (insight.topSelectorElapsedMs) {
340+
output += `${
341+
Trace.Insights.Models.SlowCSSSelector.UIStrings.topSelectorElapsedTime} (as ranked by elapsed time in ms):\n`;
342+
output += `${this.#formatMicro(insight.topSelectorElapsedMs['elapsed (us)'])}: ${
343+
insight.topSelectorElapsedMs.selector}\n\n`;
344+
}
345+
346+
if (insight.topSelectorMatchAttempts) {
347+
output += Trace.Insights.Models.SlowCSSSelector.UIStrings.topSelectorMatchAttempt + ':\n';
348+
output += `${insight.topSelectorMatchAttempts.match_attempts} attempts for selector: '${
349+
insight.topSelectorMatchAttempts.selector}'\n\n`;
350+
}
351+
352+
output += `${Trace.Insights.Models.SlowCSSSelector.UIStrings.total}:\n`;
353+
output +=
354+
`${Trace.Insights.Models.SlowCSSSelector.UIStrings.elapsed}: ${this.#formatMicro(insight.totalElapsedMs)}\n`;
355+
output += `${Trace.Insights.Models.SlowCSSSelector.UIStrings.matchAttempts}: ${insight.totalMatchAttempts}\n`;
356+
output += `${Trace.Insights.Models.SlowCSSSelector.UIStrings.matchCount}: ${insight.totalMatchCount}\n\n`;
357+
358+
output += Trace.Insights.Models.SlowCSSSelector.UIStrings.description;
359+
360+
return output;
361+
}
362+
322363
/**
323364
* Create an AI prompt string out of the ThirdParties Insight model to use with Ask AI.
324365
* Note: This function accesses the UIStrings within ThirdParties to help build the
@@ -626,6 +667,10 @@ ${filesFormatted}`;
626667
return this.formatNetworkDependencyTreeInsight(this.#insight);
627668
}
628669

670+
if (Trace.Insights.Models.SlowCSSSelector.isSlowCSSSelectorInsight(this.#insight)) {
671+
return this.formatSlowCssSelectorsInsight(this.#insight);
672+
}
673+
629674
if (Trace.Insights.Models.ThirdParties.isThirdPartyInsight(this.#insight)) {
630675
return this.formatThirdPartiesInsight(this.#insight);
631676
}
@@ -679,7 +724,7 @@ ${filesFormatted}`;
679724
return `- https://web.dev/articles/lcp
680725
- https://web.dev/articles/optimize-lcp`;
681726
case 'SlowCSSSelector':
682-
return '';
727+
return '- https://developer.chrome.com/docs/devtools/performance/selector-stats';
683728
case 'ThirdParties':
684729
return '- https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/';
685730
case 'Viewport':
@@ -749,7 +794,7 @@ It is important that all of these checks pass to minimize the delay between the
749794
case 'RenderBlocking':
750795
return 'This insight identifies network requests that were render blocking. Render blocking requests are impactful because they are deemed critical to the page and therefore the browser stops rendering the page until it has dealt with these resources. For this insight make sure you fully inspect the details of each render blocking network request and prioritize your suggestions to the user based on the impact of each render blocking request.';
751796
case 'SlowCSSSelector':
752-
return '';
797+
return `This insight identifies CSS selectors that are slowing down your page's rendering performance.`;
753798
case 'ThirdParties':
754799
return 'This insight analyzes the performance impact of resources loaded from third-party servers and aggregates the performance cost, in terms of download transfer sizes and total amount of time that third party scripts spent executing on the main thread.';
755800
case 'Viewport':

front_end/models/trace/insights/SlowCSSSelector.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export const UIStrings = {
5656
/**
5757
* @description top CSS selector when ranked by elapsed time in ms
5858
*/
59-
topSelectorElapsedTime: 'Top selector elaspsed time',
59+
topSelectorElapsedTime: 'Top selector elapsed time',
6060
/**
6161
* @description top CSS selector when ranked by match attempt
6262
*/
@@ -114,6 +114,10 @@ function finalize(partialModel: PartialInsightModel<SlowCSSSelectorInsightModel>
114114
};
115115
}
116116

117+
export function isSlowCSSSelectorInsight(model: InsightModel): model is SlowCSSSelectorInsightModel {
118+
return model.insightKey === InsightKeys.SLOW_CSS_SELECTOR;
119+
}
120+
117121
export function generateInsight(
118122
parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): SlowCSSSelectorInsightModel {
119123
const selectorStatsData = parsedTrace.SelectorStats;

front_end/panels/timeline/components/insights/SlowCSSSelector.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export class SlowCSSSelector extends BaseInsightComponent<SlowCSSSelectorInsight
2626
override internalName = 'slow-css-selector';
2727
#selectorLocations = new Map<string, Protocol.CSS.SourceRange[]>();
2828

29+
protected override hasAskAiSupport(): boolean {
30+
return true;
31+
}
32+
2933
private async toSourceFileLocation(cssModel: SDK.CSSModel.CSSModel, selector: Trace.Types.Events.SelectorTiming):
3034
Promise<Linkifier.Linkifier.LinkifierData[]|undefined> {
3135
if (!cssModel) {

0 commit comments

Comments
 (0)