Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benchmark/react/lynx.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default defineConfig({
jsOptions: {
minimizerOptions: {
mangle: false,
minify: false,
},
},
},
Expand All @@ -28,7 +29,6 @@ export default defineConfig({
'./cases/001-fib/index.ts',
],
'002-hello-reactLynx': [
'event-target-polyfill',
'./src/patchProfile.ts',
'./cases/002-hello-reactLynx/index.tsx',
],
Expand Down
10 changes: 10 additions & 0 deletions benchmark/react/src/RunBenchmarkUntil.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.

import { useEffect, useState } from '@lynx-js/react';

export const RunBenchmarkUntilHydrate = () => {
return <view id={`stop-benchmark-${__BACKGROUND__}`} />;
};

export const RunBenchmarkUntilEffect = () => {
const [stopBenchmark, setStopBenchmark] = useState(false);
useEffect(() => {
setStopBenchmark(true);
}, []);
return <view id={`stop-benchmark-${stopBenchmark}`} />;
};
85 changes: 57 additions & 28 deletions benchmark/react/src/patchProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,66 @@

import { hook } from './hook.js';

if (__BACKGROUND__) {
// eslint-disable-next-line no-global-assign
console = { ...console };
}

const PREFIX = __REPO_FILEPATH__.split('/').slice(0, -2).join('/');
const ignored: Record<string, boolean> = {};
const stack: string[] = [];
let depth = 0;

hook(console, 'profile', (old, name) => {
old!(name);
if (
(ignored[name!] ??= name === 'commitChanges'
|| name!.startsWith('ReactLynx::diff::'))
) {
stack.push('__IGNORED__');
} else {
stack.push(name!);
if (typeof Codspeed !== 'undefined') {
function shouldIgnoreBenchmark(name: string | undefined) {
if (
!name
|| name === 'ReactLynx::commit'
|| name === 'ReactLynx::commitChanges'
|| name === 'ReactLynx::transferRoot'
|| name === 'ReactLynx::BSI::setAttribute'
|| name.startsWith('OnLifecycleEvent::')
|| name.startsWith('ReactLynx::diff::')
|| name.startsWith('ReactLynx::render::')
) {
return true;
}
return false;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Codspeed.startBenchmark();
});

hook(console, 'profileEnd', (old) => {
Codspeed.stopBenchmark();
const name = stack.pop();
if (name === '__IGNORED__') {
Codspeed.zeroStats();
} else {
Codspeed.setExecutedBenchmark(
`${PREFIX}::${__webpack_chunkname__}-${name!}`,
);
}
old!();
});
hook(lynx.performance, 'profileStart', (old, name, option) => {
old!.call(lynx.performance, name, option);
if ((ignored[name] ??= shouldIgnoreBenchmark(name))) {
stack.push('__IGNORED__');
} else {
stack.push(name);
depth++;
if (depth > 1) {
console.log(
`Benchmark ${name} is ignored because it is nested, the stack: ${
stack.join(', ')
}`,
);
} else {
Codspeed.startBenchmark();
}
}
Comment thread
hzy marked this conversation as resolved.
});

hook(lynx.performance, 'profileEnd', (old) => {
const name = stack.pop()!;
if (name === '__IGNORED__') {
// Codspeed.zeroStats();
} else {
if (depth > 1) {
// ignored
} else {
Codspeed.stopBenchmark();
Codspeed.setExecutedBenchmark(
`${PREFIX}::${__webpack_chunkname__}-${
name
.replace(/^ReactLynx::/, '')
.replace(/::/g, '__')
}`,
);
}
depth--;
}
Comment thread
hzy marked this conversation as resolved.
old!.call(lynx.performance);
});
}
2 changes: 1 addition & 1 deletion packages/lynx/benchx_cli/scripts/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ console.log('noop')
}

const COMMIT = 'd6dd806293012c62e5104ad7ed2bed5c66f4f833';
const PICK_COMMIT = '033e8243747fa0b3ffc01e4b2df321d73a30597f';
const PICK_COMMIT = '1524ac02060bfc2e354e1865c989bc6f7a9882b1';
Comment thread
coderabbitai[bot] marked this conversation as resolved.

function checkCwd() {
try {
Expand Down
7 changes: 4 additions & 3 deletions packages/react/runtime/src/backgroundSnapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import type { Worklet } from '@lynx-js/react/worklet-runtime/bindings';

import { profileEnd, profileStart } from './debug/utils.js';
import { processGestureBackground } from './gesture/processGestureBagkround.js';
import type { GestureKind } from './gesture/types.js';
import { diffArrayAction, diffArrayLepus } from './hydrate.js';
Comment thread
hzy marked this conversation as resolved.
Expand Down Expand Up @@ -212,7 +213,7 @@ export class BackgroundSnapshotInstance {

setAttribute(key: string | number, value: unknown): void {
if (__PROFILE__) {
console.profile('setAttribute');
profileStart('ReactLynx::BSI::setAttribute');
Comment thread
hzy marked this conversation as resolved.
}
if (key === 'values') {
if (__globalSnapshotPatch) {
Expand Down Expand Up @@ -260,7 +261,7 @@ export class BackgroundSnapshotInstance {
}
this.__values = value as unknown[];
if (__PROFILE__) {
console.profileEnd();
profileEnd();
}
return;
}
Expand All @@ -279,7 +280,7 @@ export class BackgroundSnapshotInstance {
value,
);
if (__PROFILE__) {
console.profileEnd();
profileEnd();
}
}

Expand Down
23 changes: 23 additions & 0 deletions packages/react/runtime/src/debug/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2024 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.

/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */

const noop = () => {};

export const profileStart = /* @__PURE__ */ ((() => {
let p;
if (!(p = lynx.performance) || typeof p.profileStart !== 'function') {
return noop;
}
return p.profileStart.bind(p);
Comment thread
hzy marked this conversation as resolved.
})()) as typeof lynx.performance.profileStart;

export const profileEnd = /* @__PURE__ */ ((() => {
let p;
if (!(p = lynx.performance) || typeof p.profileEnd !== 'function') {
return noop;
}
return p.profileEnd.bind(p);
})()) as typeof lynx.performance.profileEnd;
5 changes: 3 additions & 2 deletions packages/react/runtime/src/lifecycle/destroy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import { __root } from '../root.js';
import { delayedEvents } from './event/delayEvents.js';
import { delayedLifecycleEvents } from './event/delayLifecycleEvents.js';
import { globalCommitTaskMap } from './patch/commit.js';
import { profileEnd, profileStart } from '../debug/utils.js';

function destroyBackground(): void {
if (__PROFILE__) {
console.profile('destroyBackground');
profileStart('ReactLynx::destroyBackground');
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
Expand All @@ -27,7 +28,7 @@ function destroyBackground(): void {
delayedEvents.length = 0;
}
if (__PROFILE__) {
console.profileEnd();
profileEnd();
}
}

Expand Down
15 changes: 14 additions & 1 deletion packages/react/runtime/src/lifecycle/event/jsReady.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2025 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.
import { profileEnd, profileStart } from '../../debug/utils.js';
import { LifecycleConstant } from '../../lifecycleConstant.js';
import { __root } from '../../root.js';

Expand All @@ -9,13 +10,25 @@ let jsReadyEventIdSwap: Record<string | number, number>;

function jsReady(): void {
isJSReady = true;

if (__PROFILE__) {
profileStart('ReactLynx::transferRoot');
profileStart('ReactLynx::serializeRoot');
}
const root = JSON.stringify(__root);
if (__PROFILE__) {
profileEnd();
}
__OnLifecycleEvent([
LifecycleConstant.firstScreen, /* FIRST_SCREEN */
{
root: JSON.stringify(__root),
root,
jsReadyEventIdSwap,
},
]);
if (__PROFILE__) {
profileEnd();
}
jsReadyEventIdSwap = {};
}

Expand Down
5 changes: 3 additions & 2 deletions packages/react/runtime/src/lifecycle/patch/commit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { takeWorkletRefInitValuePatch } from '../../worklet/workletRefPool.js';
import { getReloadVersion } from '../pass.js';
import type { SnapshotPatch } from './snapshotPatch.js';
import { takeGlobalSnapshotPatch } from './snapshotPatch.js';
import { profileEnd, profileStart } from '../../debug/utils.js';

let globalFlushOptions: FlushOptions = {};
function takeGlobalFlushOptions() {
Expand Down Expand Up @@ -181,7 +182,7 @@ function commitPatchUpdate(patchList: PatchList, patchOptions: GlobalPatchOption
// console.debug('commitPatchUpdate:', prettyFormatSnapshotPatch(patchList.patchList[0]?.snapshotPatch));

if (__PROFILE__) {
console.profile('commitChanges');
profileStart('ReactLynx::commitChanges');
}
markTiming('packChangesStart');
const obj: {
Expand All @@ -200,7 +201,7 @@ function commitPatchUpdate(patchList: PatchList, patchOptions: GlobalPatchOption
setPipeline(undefined);
}
if (__PROFILE__) {
console.profileEnd();
profileEnd();
}

return obj;
Expand Down
9 changes: 5 additions & 4 deletions packages/react/runtime/src/lifecycle/reload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ import { increaseReloadVersion } from './pass.js';
import { deinitGlobalSnapshotPatch } from './patch/snapshotPatch.js';
import { shouldDelayUiOps } from './ref/delay.js';
import { renderMainThread } from './render.js';
import { profileEnd, profileStart } from '../debug/utils.js';

function reloadMainThread(data: unknown, options: UpdatePageOption): void {
if (__PROFILE__) {
console.profile('reloadTemplate');
profileStart('ReactLynx::reloadMainThread');
}

increaseReloadVersion();
Expand Down Expand Up @@ -64,14 +65,14 @@ function reloadMainThread(data: unknown, options: UpdatePageOption): void {
__FlushElementTree(__page, options);

if (__PROFILE__) {
console.profileEnd();
profileEnd();
}
return;
}

function reloadBackground(updateData: Record<string, any>): void {
if (__PROFILE__) {
console.profile('reload');
profileStart('ReactLynx::reloadBackground');
}

deinitGlobalSnapshotPatch();
Expand All @@ -88,7 +89,7 @@ function reloadBackground(updateData: Record<string, any>): void {
render(__root.__jsx, __root as any);

if (__PROFILE__) {
console.profileEnd();
profileEnd();
}
}

Expand Down
9 changes: 5 additions & 4 deletions packages/react/runtime/src/lifecycle/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { isValidElement } from 'preact';

import { profileEnd, profileStart } from '../debug/utils.js';
Comment thread
hzy marked this conversation as resolved.
import { renderOpcodesInto } from '../opcodes.js';
import { render as renderToString } from '../renderToOpcodes/index.js';
import { __root } from '../root.js';
Expand All @@ -17,15 +18,15 @@ function renderMainThread(): void {
let opcodes;
try {
if (__PROFILE__) {
console.profile('renderToString');
profileStart('ReactLynx::renderMainThread');
}
opcodes = renderToString(__root.__jsx, undefined);
} catch (e) {
lynx.reportError(e as Error);
opcodes = [];
} finally {
if (__PROFILE__) {
console.profileEnd();
profileEnd();
}
}

Expand All @@ -40,15 +41,15 @@ function renderMainThread(): void {
}

if (__PROFILE__) {
console.profile('renderOpcodesInto');
profileStart('ReactLynx::renderOpcodes');
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
renderOpcodesInto(opcodes, __root as any);
if (__ENABLE_SSR__) {
__root.__opcodes = opcodes;
}
if (__PROFILE__) {
console.profileEnd();
profileEnd();
}
Comment thread
hzy marked this conversation as resolved.
}

Expand Down
7 changes: 7 additions & 0 deletions packages/react/runtime/src/lynx-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useState } from 'preact/hooks';
import type { Consumer, FC, ReactNode } from 'react';

import { factory, withInitDataInState } from './compat/initData.js';
import { profileEnd, profileStart } from './debug/utils.js';
import { useLynxGlobalEventListener } from './hooks/useLynxGlobalEventListener.js';
import { LifecycleConstant } from './lifecycleConstant.js';
import { flushDelayedLifecycleEvents } from './lynx/tt.js';
Expand Down Expand Up @@ -94,8 +95,14 @@ export const root: Root = {
preactProcess = cb;
};
try {
if (__PROFILE__) {
profileStart('ReactLynx::renderBackground');
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
render(jsx, __root as any);
if (__PROFILE__) {
profileEnd();
}
(preactProcess as (() => void) | undefined)?.();
} finally {
options.debounceRendering = oldDebounceRendering!;
Expand Down
Loading
Loading