Skip to content

Commit fa70380

Browse files
nolanlawsonwjhsf
andauthored
feat(ssr): add perf timings (#5143)
* fix: fix it * fix: fix tests and update names --------- Co-authored-by: Will Harney <[email protected]>
1 parent 8d3bc08 commit fa70380

File tree

9 files changed

+183
-77
lines changed

9 files changed

+183
-77
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"test:ci": "vitest run --workspace vitest.workspace.mjs --coverage",
2525
"test:karma": "nx test @lwc/integration-karma",
2626
"test:karma:start": "nx start @lwc/integration-karma",
27+
"test:hydration:start": "nx hydration:start @lwc/integration-karma",
2728
"test:integration": "nx sauce @lwc/integration-tests",
2829
"test:performance": "nx test @lwc/perf-benchmarks",
2930
"test:performance:best": "nx test:best @lwc/perf-benchmarks",

packages/@lwc/engine-core/src/framework/hydration.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ import { getScopeTokenClass } from './stylesheet';
5555
import { renderComponent } from './component';
5656
import { applyRefs } from './modules/refs';
5757
import { unwrapIfNecessary } from './sanitized-html-content';
58+
import {
59+
logGlobalOperationEndWithVM,
60+
logGlobalOperationStartWithVM,
61+
logOperationEnd,
62+
logOperationStart,
63+
OperationId,
64+
} from './profiler';
5865
import type { Classes } from './hydration-utils';
5966
import type {
6067
VNodes,
@@ -85,6 +92,8 @@ let hasMismatch = false;
8592
export function hydrateRoot(vm: VM) {
8693
hasMismatch = false;
8794

95+
logGlobalOperationStartWithVM(OperationId.GlobalSsrHydrate, vm);
96+
8897
runConnectedCallback(vm);
8998
hydrateVM(vm);
9099

@@ -98,6 +107,7 @@ export function hydrateRoot(vm: VM) {
98107
logHydrationWarning('Hydration completed with errors.');
99108
}
100109
}
110+
logGlobalOperationEndWithVM(OperationId.GlobalSsrHydrate, vm);
101111
}
102112

103113
function hydrateVM(vm: VM) {
@@ -111,7 +121,9 @@ function hydrateVM(vm: VM) {
111121
renderRoot: parentNode,
112122
renderer: { getFirstChild },
113123
} = vm;
124+
logOperationStart(OperationId.Patch, vm);
114125
hydrateChildren(getFirstChild(parentNode), children, parentNode, vm, false);
126+
logOperationEnd(OperationId.Patch, vm);
115127
runRenderedCallback(vm);
116128
}
117129

packages/@lwc/engine-core/src/framework/profiler.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@ export const enum OperationId {
2020
RenderedCallback = 4,
2121
DisconnectedCallback = 5,
2222
ErrorCallback = 6,
23-
GlobalHydrate = 7,
24-
GlobalRehydrate = 8,
23+
GlobalRender = 7,
24+
GlobalRerender = 8,
25+
GlobalSsrHydrate = 9,
2526
}
2627

27-
type GlobalOperationId = OperationId.GlobalHydrate | OperationId.GlobalRehydrate;
28+
type GlobalOperationId =
29+
| OperationId.GlobalRender
30+
| OperationId.GlobalRerender
31+
| OperationId.GlobalSsrHydrate;
2832

2933
const enum Phase {
3034
Start = 0,
@@ -60,8 +64,9 @@ const operationIdNameMapping = [
6064
'renderedCallback',
6165
'disconnectedCallback',
6266
'errorCallback',
63-
'lwc-hydrate',
64-
'lwc-rehydrate',
67+
'lwc-render',
68+
'lwc-rerender',
69+
'lwc-ssr-hydrate',
6570
] as const satisfies Record<OperationId, string>;
6671

6772
const operationTooltipMapping = [
@@ -79,10 +84,12 @@ const operationTooltipMapping = [
7984
'component disconnectedCallback()',
8085
// errorCallback
8186
'component errorCallback()',
82-
// lwc-hydrate
87+
// lwc-render
8388
'component first rendered',
84-
// lwc-rehydrate
89+
// lwc-rerender
8590
'component re-rendered',
91+
// lwc-ssr-hydrate
92+
'component hydrated from server-rendered HTML',
8693
] as const satisfies Record<OperationId, string>;
8794

8895
// Even if all the browser the engine supports implements the UserTiming API, we need to guard the measure APIs.
@@ -154,13 +161,14 @@ function getProperties(vm: VM<any, any>): [string, string][] {
154161
function getColor(opId: OperationId): TrackColor {
155162
// As of Sept 2024: primary (dark blue), secondary (light blue), tertiary (green)
156163
switch (opId) {
157-
// GlobalHydrate and Constructor tend to occur at the top level
158-
case OperationId.GlobalHydrate:
164+
// GlobalSsrHydrate, GlobalRender, and Constructor tend to occur at the top level
165+
case OperationId.GlobalRender:
166+
case OperationId.GlobalSsrHydrate:
159167
case OperationId.Constructor:
160168
return 'primary';
161-
// GlobalRehydrate also occurs at the top level, but we want to use tertiary (green) because it's easier to
169+
// GlobalRerender also occurs at the top level, but we want to use tertiary (green) because it's easier to
162170
// distinguish from primary, and at a glance you should be able to easily tell re-renders from first renders.
163-
case OperationId.GlobalRehydrate:
171+
case OperationId.GlobalRerender:
164172
return 'tertiary';
165173
// Everything else (patch/render/callbacks)
166174
default:

packages/@lwc/engine-core/src/framework/vm.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,11 @@ export function connectRootElement(elm: any) {
250250

251251
if (process.env.NODE_ENV !== 'production') {
252252
// Flush any logs for this VM so that the initial properties from the constructor don't "count"
253-
// in subsequent re-renders (lwc-rehydrate). Right now we're at the first render (lwc-hydrate).
253+
// in subsequent re-renders (lwc-rerender). Right now we're at the first render (lwc-hydrate).
254254
flushMutationLogsForVM(vm);
255255
}
256256

257-
logGlobalOperationStartWithVM(OperationId.GlobalHydrate, vm);
257+
logGlobalOperationStartWithVM(OperationId.GlobalRender, vm);
258258

259259
// Usually means moving the element from one place to another, which is observable via
260260
// life-cycle hooks.
@@ -265,7 +265,7 @@ export function connectRootElement(elm: any) {
265265
runConnectedCallback(vm);
266266
rehydrate(vm);
267267

268-
logGlobalOperationEndWithVM(OperationId.GlobalHydrate, vm);
268+
logGlobalOperationEndWithVM(OperationId.GlobalRender, vm);
269269
}
270270

271271
export function disconnectRootElement(elm: any) {
@@ -656,7 +656,7 @@ function flushRehydrationQueue() {
656656
const mutationLogs =
657657
process.env.NODE_ENV === 'production' ? undefined : getAndFlushMutationLogs();
658658

659-
logGlobalOperationStart(OperationId.GlobalRehydrate);
659+
logGlobalOperationStart(OperationId.GlobalRerender);
660660

661661
if (process.env.NODE_ENV !== 'production') {
662662
assert.invariant(
@@ -679,15 +679,15 @@ function flushRehydrationQueue() {
679679
ArrayUnshift.apply(rehydrateQueue, ArraySlice.call(vms, i + 1));
680680
}
681681
// we need to end the measure before throwing.
682-
logGlobalOperationEnd(OperationId.GlobalRehydrate, mutationLogs);
682+
logGlobalOperationEnd(OperationId.GlobalRerender, mutationLogs);
683683

684684
// re-throwing the original error will break the current tick, but since the next tick is
685685
// already scheduled, it should continue patching the rest.
686686
throw error;
687687
}
688688
}
689689

690-
logGlobalOperationEnd(OperationId.GlobalRehydrate, mutationLogs);
690+
logGlobalOperationEnd(OperationId.GlobalRerender, mutationLogs);
691691
}
692692

693693
export function runConnectedCallback(vm: VM) {

packages/@lwc/integration-karma/test/misc/performance-timing/index.spec.js

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ function testConstructor(expected) {
2020
});
2121
}
2222

23-
function testRehydration(expected) {
24-
it('component rehydration', () => {
23+
function testRerender(expected) {
24+
it('component rerender', () => {
2525
const elm = createElement('x-child', { is: Child });
2626
document.body.appendChild(elm);
2727

@@ -43,8 +43,8 @@ function testNestedTree(expected) {
4343
});
4444
}
4545

46-
function testNestedRehydration(expected) {
47-
it('captures component nested component tree rehydration', () => {
46+
function testNestedRerender(expected) {
47+
it('captures component nested component tree rerender', () => {
4848
const elm = createElement('x-parent', { is: Parent });
4949
document.body.appendChild(elm);
5050

@@ -92,40 +92,40 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
9292
describe.runIf(process.env.NODE_ENV === 'production')('production mode', () => {
9393
testConstructor([
9494
{
95-
label: /lwc-hydrate/,
95+
label: /lwc-render/,
9696
},
9797
]);
9898

99-
testRehydration([
99+
testRerender([
100100
{
101-
label: /lwc-rehydrate/,
101+
label: /lwc-rerender/,
102102
},
103103
]);
104104

105105
testNestedTree([
106106
{
107-
label: /lwc-hydrate/,
107+
label: /lwc-render/,
108108
},
109109
]);
110110

111-
testNestedRehydration([
111+
testNestedRerender([
112112
{
113-
label: /lwc-rehydrate/,
113+
label: /lwc-rerender/,
114114
},
115115
]);
116116

117117
testLifecycleHooks([
118118
{
119-
label: /lwc-hydrate/,
119+
label: /lwc-render/,
120120
},
121121
]);
122122

123123
testNestedComponentCreation([
124124
{
125-
label: /lwc-hydrate/,
125+
label: /lwc-render/,
126126
children: [
127127
{
128-
label: /lwc-hydrate/,
128+
label: /lwc-render/,
129129
},
130130
],
131131
},
@@ -138,7 +138,7 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
138138
label: /<x-child> - constructor/,
139139
},
140140
{
141-
label: /lwc-hydrate/,
141+
label: /lwc-render/,
142142
children: [
143143
{
144144
label: /<x-child> - render/,
@@ -150,9 +150,9 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
150150
},
151151
]);
152152

153-
testRehydration([
153+
testRerender([
154154
{
155-
label: /lwc-rehydrate/,
155+
label: /lwc-rerender/,
156156
children: [
157157
{
158158
label: /<x-child> - render/,
@@ -170,23 +170,23 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
170170
? [
171171
{ label: '<x-parent> - constructor', children: [] },
172172
{
173-
label: 'lwc-hydrate',
173+
label: 'lwc-render',
174174
children: [
175175
{ label: '<x-parent> - render', children: [] },
176176
{
177177
label: '<x-parent> - patch',
178178
children: [
179179
{ label: '<x-child> - constructor', children: [] },
180180
{
181-
label: 'lwc-hydrate',
181+
label: 'lwc-render',
182182
children: [
183183
{ label: '<x-child> - render', children: [] },
184184
{ label: '<x-child> - patch', children: [] },
185185
],
186186
},
187187
{ label: '<x-child> - constructor', children: [] },
188188
{
189-
label: 'lwc-hydrate',
189+
label: 'lwc-render',
190190
children: [
191191
{ label: '<x-child> - render', children: [] },
192192
{ label: '<x-child> - patch', children: [] },
@@ -202,7 +202,7 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
202202
label: /<x-parent> - constructor/,
203203
},
204204
{
205-
label: /lwc-hydrate/,
205+
label: /lwc-render/,
206206
children: [
207207
{
208208
label: /<x-parent> - render/,
@@ -235,9 +235,9 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
235235
]
236236
);
237237

238-
testNestedRehydration([
238+
testNestedRerender([
239239
{
240-
label: /lwc-rehydrate/,
240+
label: /lwc-rerender/,
241241
children: [
242242
{
243243
label: /<x-parent> - render/,
@@ -268,7 +268,7 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
268268
label: /<x-lifecycle> - constructor/,
269269
},
270270
{
271-
label: /lwc-hydrate/,
271+
label: /lwc-render/,
272272
children: [
273273
{
274274
label: /<x-lifecycle> - connectedCallback/,
@@ -294,7 +294,7 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
294294
label: /<x-nested> - constructor/,
295295
},
296296
{
297-
label: /lwc-hydrate/,
297+
label: /lwc-render/,
298298
children: [
299299
{
300300
label: /<x-nested> - render/,
@@ -306,7 +306,7 @@ describe.runIf(isUserTimingSupported && process.env.NODE_ENV !== 'production')(
306306
label: /<x-child> - constructor/,
307307
},
308308
{
309-
label: /lwc-hydrate/,
309+
label: /lwc-render/,
310310
children: [
311311
{
312312
label: /<x-child> - render/,

0 commit comments

Comments
 (0)