Skip to content

Commit

Permalink
feat(runtime): add performance profiling
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Oct 9, 2019
1 parent 0aca665 commit f5817a0
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/compiler/app-core/build-conditionals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export function updateBuildConditionals(config: d.Config, b: d.Build) {
b.isDebug = (config.logLevel === 'debug');
b.isDev = !!config.devMode;
b.lifecycleDOMEvents = !!(b.isDebug || config._isTesting || config._lifecycleDOMEvents);
b.profile = !!(config.flags && config.flags.profile);
b.profile = !!(config.profile);
b.hotModuleReplacement = !!(config.devMode && config.devServer && config.devServer.reloadStrategy === 'hmr' && !config._isTesting);
b.updatable = (b.updatable || b.hydrateClientSide || b.hotModuleReplacement);
b.member = (b.member || b.updatable || b.mode || b.lifecycle);
Expand Down
1 change: 1 addition & 0 deletions src/compiler/config/validate-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export function validateConfig(config: d.Config, diagnostics: d.Diagnostic[], se

setBooleanConfig(config, 'buildEs5', 'es5', !config.devMode);
setBooleanConfig(config, 'buildDist', 'esm', !config.devMode || config.buildEs5);
setBooleanConfig(config, 'profile', 'profile', config.devMode);

// setup the outputTargets
validateOutputTargets(config, diagnostics);
Expand Down
1 change: 1 addition & 0 deletions src/declarations/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export interface Config extends StencilConfig {
logLevel?: 'error'|'warn'|'info'|'debug'|string;
rootDir?: string;
suppressLogs?: boolean;
profile?: boolean;
_isValidated?: boolean;
_isTesting?: boolean;
_lifecycleDOMEvents?: boolean;
Expand Down
7 changes: 6 additions & 1 deletion src/runtime/bootstrap-lazy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import { doc, getHostRef, plt, registerHost, supportsShadowDom, win } from '@pla
import { hmrStart } from './hmr-component';
import { HYDRATE_ID, PLATFORM_FLAGS, PROXY_FLAGS } from './runtime-constants';
import { appDidLoad, forceUpdate } from './update-component';
import { createTime } from './profile';


export const bootstrapLazy = (lazyBundles: d.LazyBundlesRuntimeData, options: d.CustomElementsDefineOptions = {}) => {
// if (BUILD.profile) {
// performance.mark('st:app:start');
// }
const endBootstrap = createTime('bootstrapLazy');
const cmpTags: string[] = [];
const exclude = options.exclude || [];
const head = doc.head;
Expand Down Expand Up @@ -123,7 +128,6 @@ export const bootstrapLazy = (lazyBundles: d.LazyBundlesRuntimeData, options: d.
cmpMeta.$lazyBundleIds$ = lazyBundle[0];

if (!exclude.includes(tagName) && !customElements.get(tagName)) {
cmpTags.push(tagName);
customElements.define(
tagName,
proxyComponent(HostElement as any, cmpMeta, PROXY_FLAGS.isElementConstructor) as any
Expand All @@ -138,4 +142,5 @@ export const bootstrapLazy = (lazyBundles: d.LazyBundlesRuntimeData, options: d.

// Fallback appLoad event
plt.jmp(() => appLoadFallback = setTimeout(appDidLoad, 30));
endBootstrap();
};
3 changes: 3 additions & 0 deletions src/runtime/connected-callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HYDRATE_ID, NODE_TYPE, PLATFORM_FLAGS } from './runtime-constants';
import { initializeClientHydrate } from './client-hydrate';
import { initializeComponent } from './initialize-component';
import { attachToAncestor, safeCall } from './update-component';
import { createTime } from './profile';

export const fireConnectedCallback = (instance: any) => {
if (BUILD.lazyLoad && BUILD.connectedCallback) {
Expand All @@ -17,6 +18,7 @@ export const fireConnectedCallback = (instance: any) => {

export const connectedCallback = (elm: d.HostElement, cmpMeta: d.ComponentRuntimeMeta) => {
if ((plt.$flags$ & PLATFORM_FLAGS.isTmpDisconnected) === 0) {
const endConnected = createTime('connectedCallback', cmpMeta.$tagName$);
// connectedCallback
const hostRef = getHostRef(elm);

Expand Down Expand Up @@ -101,6 +103,7 @@ export const connectedCallback = (elm: d.HostElement, cmpMeta: d.ComponentRuntim
}
}
fireConnectedCallback(hostRef.$lazyInstance$);
endConnected();
}
};

Expand Down
9 changes: 8 additions & 1 deletion src/runtime/initialize-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import { computeMode } from './mode';
import { getScopeId, registerStyle } from './styles';
import { fireConnectedCallback } from './connected-callback';
import { PROXY_FLAGS } from './runtime-constants';
import { createTime } from './profile';


export const initializeComponent = async (elm: d.HostElement, hostRef: d.HostRef, cmpMeta: d.ComponentRuntimeMeta, hmrVersionId?: string, Cstr?: any) => {

// initializeComponent
if ((BUILD.lazyLoad || BUILD.style) && (hostRef.$flags$ & HOST_FLAGS.hasInitializedComponent) === 0) {
// we haven't initialized this element yet
Expand Down Expand Up @@ -40,6 +42,7 @@ export const initializeComponent = async (elm: d.HostElement, hostRef: d.HostRef
throw new Error(`Constructor for "${cmpMeta.$tagName$}#${hostRef.$modeName$}" was not found`);
}
if (BUILD.member && !Cstr.isProxied) {
const endProxyInstance = createTime('proxyInstance', cmpMeta.$tagName$);
// we'eve never proxied this Constructor before
// let's add the getters/setters to its prototype before
// the first time we create an instance of the implementation
Expand All @@ -48,8 +51,10 @@ export const initializeComponent = async (elm: d.HostElement, hostRef: d.HostRef
}
proxyComponent(Cstr, cmpMeta, PROXY_FLAGS.proxyState);
Cstr.isProxied = true;
endProxyInstance();
}

const endNewInstance = createTime('newInstance', cmpMeta.$tagName$);
// ok, time to construct the instance
// but let's keep track of when we start and stop
// so that the getters/setters don't incorrectly step on data
Expand All @@ -72,14 +77,15 @@ export const initializeComponent = async (elm: d.HostElement, hostRef: d.HostRef
if (BUILD.watchCallback) {
hostRef.$flags$ |= HOST_FLAGS.isWatchReady;
}
endNewInstance();
fireConnectedCallback(hostRef.$lazyInstance$);

} else {
Cstr = elm.constructor as any;
}

const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$);
const scopeId = BUILD.mode ? getScopeId(cmpMeta.$tagName$, hostRef.$modeName$) : getScopeId(cmpMeta.$tagName$);

if (BUILD.style && !styles.has(scopeId) && Cstr.style) {
// this component has styles but we haven't registered them yet
let style = Cstr.style;
Expand All @@ -94,6 +100,7 @@ export const initializeComponent = async (elm: d.HostElement, hostRef: d.HostRef

registerStyle(scopeId, style, !!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation));
}
endRegisterStyles();
}

// we've successfully created a lazy instance
Expand Down
16 changes: 16 additions & 0 deletions src/runtime/profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { BUILD } from '@build-conditionals';

let i = 0;
export const createTime = (fnName: string, tagName = '') => {
if (BUILD.profile) {
const key = `st:${fnName}:${tagName}:${i++}`;
// Start
performance.mark(key);

// End
return () => performance.measure(`[Stencil] ${fnName}() <${tagName}>`, key);
} else {
return () => { return; };
}
};

4 changes: 3 additions & 1 deletion src/runtime/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BUILD } from '@build-conditionals';
import { CMP_FLAGS } from '@utils';
import { doc, plt, styles, supportsConstructibleStylesheets, supportsShadowDom } from '@platform';
import { HYDRATE_ID, NODE_TYPE } from './runtime-constants';
import { createTime } from './profile';


const rootAppliedStyles: d.RootAppliedStyleMap = /*@__PURE__*/new WeakMap();
Expand Down Expand Up @@ -89,7 +90,7 @@ export const addStyle = (styleContainerNode: any, cmpMeta: d.ComponentRuntimeMet
};

export const attachStyles = (elm: d.HostElement, cmpMeta: d.ComponentRuntimeMeta, mode: string) => {

const endAttachStyles = createTime('attachStyles', cmpMeta.$tagName$);
const scopeId = addStyle(
(BUILD.shadowDom && supportsShadowDom && elm.shadowRoot)
? elm.shadowRoot
Expand All @@ -110,6 +111,7 @@ export const attachStyles = (elm: d.HostElement, cmpMeta: d.ComponentRuntimeMeta
elm.classList.add(scopeId + '-s');
}
}
endAttachStyles();
};


Expand Down
21 changes: 20 additions & 1 deletion src/runtime/update-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CMP_FLAGS, HOST_FLAGS } from '@utils';
import { consoleError, doc, getHostRef, nextTick, plt, writeTask } from '@platform';
import { HYDRATED_CLASS, PLATFORM_FLAGS } from './runtime-constants';
import { renderVdom } from './vdom/vdom-render';
import { createTime } from './profile';

export const attachToAncestor = (hostRef: d.HostRef, ancestorComponent: d.HostElement) => {
if (BUILD.asyncLoading && ancestorComponent && !hostRef.$onRenderResolve$) {
Expand All @@ -20,7 +21,7 @@ export const scheduleUpdate = (elm: d.HostElement, hostRef: d.HostRef, cmpMeta:
hostRef.$flags$ |= HOST_FLAGS.needsRerender;
return;
}

const endSchedule = createTime('scheduleUpdate', cmpMeta.$tagName$);
const ancestorComponent = hostRef.$ancestorComponent$;
const instance = BUILD.lazyLoad ? hostRef.$lazyInstance$ : elm as any;
const update = () => updateComponent(elm, hostRef, cmpMeta, instance, isInitialLoad);
Expand Down Expand Up @@ -62,6 +63,8 @@ export const scheduleUpdate = (elm: d.HostElement, hostRef: d.HostRef, cmpMeta:
elm['s-rc'] = undefined;
}

endSchedule();

// there is no ancestorc omponent or the ancestor component
// has already fired off its lifecycle update then
// fire off the initial update
Expand All @@ -73,14 +76,17 @@ export const scheduleUpdate = (elm: d.HostElement, hostRef: d.HostRef, cmpMeta:

const updateComponent = (elm: d.RenderNode, hostRef: d.HostRef, cmpMeta: d.ComponentRuntimeMeta, instance: any, isInitialLoad: boolean) => {
// updateComponent
const endUpdate = createTime('update', cmpMeta.$tagName$);
if (BUILD.style && isInitialLoad) {
// DOM WRITE!
attachStyles(elm, cmpMeta, hostRef.$modeName$);
}

const endRender = createTime('render', cmpMeta.$tagName$);
if (BUILD.isDev) {
hostRef.$flags$ |= HOST_FLAGS.dev_stateMutation;
}

if (BUILD.hasRenderFn || BUILD.reflect) {
if (BUILD.vdomRender || BUILD.reflect) {
try {
Expand Down Expand Up @@ -128,6 +134,8 @@ const updateComponent = (elm: d.RenderNode, hostRef: d.HostRef, cmpMeta: d.Compo
if (BUILD.updatable || BUILD.lazyLoad) {
hostRef.$flags$ |= HOST_FLAGS.hasRendered;
}
endRender();
endUpdate();

if (BUILD.asyncLoading) {
const childrenPromises = elm['s-p'];
Expand All @@ -146,9 +154,13 @@ const updateComponent = (elm: d.RenderNode, hostRef: d.HostRef, cmpMeta: d.Compo


export const postUpdateComponent = (elm: d.HostElement, hostRef: d.HostRef, cmpMeta: d.ComponentRuntimeMeta) => {
const endPostUpdate = createTime('postUpdate', cmpMeta.$tagName$);
const instance = BUILD.lazyLoad ? hostRef.$lazyInstance$ : elm as any;
const ancestorComponent = hostRef.$ancestorComponent$;

if (BUILD.isDev) {
hostRef.$flags$ |= HOST_FLAGS.dev_stateMutation;
}
if (BUILD.cmpDidRender) {
safeCall(instance, 'componentDidRender');
}
Expand Down Expand Up @@ -190,6 +202,9 @@ export const postUpdateComponent = (elm: d.HostElement, hostRef: d.HostRef, cmpM
if (BUILD.hotModuleReplacement) {
elm['s-hmr-load'] && elm['s-hmr-load']();
}
if (BUILD.isDev) {
hostRef.$flags$ &= ~HOST_FLAGS.dev_stateMutation;
}

if (BUILD.method && BUILD.lazyLoad) {
hostRef.$onInstanceResolve$(elm);
Expand All @@ -206,6 +221,7 @@ export const postUpdateComponent = (elm: d.HostElement, hostRef: d.HostRef, cmpM
}
hostRef.$flags$ &= ~(HOST_FLAGS.isWaitingForChildren | HOST_FLAGS.needsRerender);
}
endPostUpdate();
// ( •_•)
// ( •_•)>⌐■-■
// (⌐■_■)
Expand Down Expand Up @@ -235,6 +251,9 @@ export const appDidLoad = () => {
plt.$flags$ |= PLATFORM_FLAGS.appLoaded;
}
emitLifecycleEvent(doc, 'appload');
// if (BUILD.profile) {
// performance.measure('[Stencil] App Did Load', 'st:app:start');
// }
};

export const safeCall = (instance: any, method: string, arg?: any) => {
Expand Down

0 comments on commit f5817a0

Please sign in to comment.