Skip to content
Draft
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
21 changes: 21 additions & 0 deletions app/components/summary-item.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Ui::Disclosure as |disclosure|>
<tr style={{this.nodeStyle}} class="list-row js-render-profile-item">

<@list.cell class="list-cell-main js-render-main-cell js-render-profile-name" style={{this.nameStyle}}>
{{@model.name}}
</@list.cell>

<@list.cell class="list-cell-main js-render-main-cell list-cell-value_numeric js-render-profile-duration">
{{@model.initial-render}}
</@list.cell>

<@list.cell class="list-cell-main js-render-main-cell list-cell-value_numeric js-render-profile-duration">
{{@model.avg-re-render}}
</@list.cell>

<@list.cell class="list-cell-main js-render-main-cell list-cell-value_numeric js-render-profile-timestamp">
{{@model.render-count}}
</@list.cell>
</tr>

</Ui::Disclosure>
17 changes: 17 additions & 0 deletions app/components/summary-item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Component from '@glimmer/component';

interface SummaryItemArgs {
model: {
name: string;
'initial-render': number;
'avg-re-render': number;
'render-count': number;
};
list: unknown; // or just leave this out
}

export default class SummaryItem extends Component<SummaryItemArgs> {
get row() {
return this.args.model;
}
}
10 changes: 10 additions & 0 deletions app/components/summary-render-table.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<List
class="js-render-tree "
@schema={{this.schema}} as |list|
>
<tbody>
{{#each this.rows as |row|}}
<SummaryItem @model={{row}} @list={{list}} @search={{this.search}} @list={{list}}/>
{{/each}}
</tbody>
</List>
88 changes: 88 additions & 0 deletions app/components/summary-render-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import Component from '@glimmer/component';

import summarySchema from '../schemas/summary-render-tree';

import escapeRegExp from '../utils/escape-reg-exp';

import type { RenderTreeModel } from '../routes/render-tree';

import isEmpty from '@ember/utils/lib/is_empty';

interface SummaryRenderArgs {
profiles: RenderTreeModel['profiles'];
searchValue: string;
}

// TODO handle for recursive cases also

export default class SummaryRenderTable extends Component<SummaryRenderArgs> {
get schema() {
return summarySchema;
}

get escapedSearch() {
return escapeRegExp(this.args.searchValue?.toLowerCase());
}

get rows() {
const profiles = this.args.profiles ?? [];

if (profiles.length === 0) {
return [];
}

// Flatten children (actual components)
const allComponents = profiles.flatMap((p) => p.children ?? []);

const grouped: Record<
string,
{
initial: number | null;
reRenders: number[];
}
> = {};

allComponents.forEach((profile) => {
const name = profile.name;

const time = profile.time; // precise ms

if (!grouped[name]) {
grouped[name] = { initial: null, reRenders: [] };
}

if (grouped[name].initial === null) {
// First time we see this component → initial render
grouped[name].initial = time;
} else {
// All later times → re-renders
grouped[name].reRenders.push(time);
}
});

return Object.entries(grouped)
.map(([name, data]) => {
const avgReRender = data.reRenders.length
? data.reRenders.reduce((a, b) => a + b, 0) / data.reRenders.length
: 0;

const count = data.reRenders.length + (data.initial ? 1 : 0);
return {
name,
'initial-render': data.initial ? Number(data.initial.toFixed(2)) : 0,
'avg-re-render': Number(avgReRender.toFixed(2)),
'render-count': count,
};
})
.filter((item) => {
if (isEmpty(this.escapedSearch)) {
return true;
}

const regExp = new RegExp(this.escapedSearch as string);
return !!item.name.toLowerCase().match(regExp);
})
.sort((a, b) => b['initial-render'] - a['initial-render'])
.slice(0, 5);
}
}
1 change: 1 addition & 0 deletions app/routes/render-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type RenderTreeController from '../controllers/render-tree';
import TabRoute from './tab';

export interface Profile {
time: number;
children: Array<Profile>;
name: string;
}
Expand Down
30 changes: 30 additions & 0 deletions app/schemas/summary-render-tree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Summary render performance schema.
*/
export default {
columns: [
{
id: 'name',
name: 'Component',
visible: true,
},
{
id: 'initial-render',
name: 'Initial Render Time (ms)',
visible: true,
numeric: true,
},
{
id: 'avg-re-render',
name: 'Avg Re-Render Time (ms)',
visible: true,
numeric: true,
},
{
id: 'render-count',
name: 'Render Count',
visible: true,
numeric: true,
},
],
};
7 changes: 5 additions & 2 deletions app/templates/render-tree.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@
</button>
</Ui::EmptyMessage>
{{else}}
<List
<!--TODO: Tab routing -->
<SummaryRenderTable @profiles={{this.model.profiles}} @searchValue={{this.searchValue}} />

{{!-- <List
class="js-render-tree list-css-striping"
@headerHeight={{this.headerHeight}}
@schema={{schema-for "render-tree"}} as |list|
Expand All @@ -48,5 +51,5 @@
<RenderItem @model={{item}} @search={{this.search}} @list={{list}} />
{{/each}}
</tbody>
</List>
</List>--}}
{{/if}}
26 changes: 26 additions & 0 deletions tests/integration/components/summary-item-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-inspector/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';

module('Integration | Component | summary-item', function (hooks) {
setupRenderingTest(hooks);

test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`<SummaryItem />`);

assert.dom().hasText('');

// Template block usage:
await render(hbs`
<SummaryItem>
template block text
</SummaryItem>
`);

assert.dom().hasText('template block text');
});
});
26 changes: 26 additions & 0 deletions tests/integration/components/summary-render-table-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-inspector/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';

module('Integration | Component | summary-render-table', function (hooks) {
setupRenderingTest(hooks);

test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`<SummaryRenderTable />`);

assert.dom().hasText('');

// Template block usage:
await render(hbs`
<SummaryRenderTable>
template block text
</SummaryRenderTable>
`);

assert.dom().hasText('template block text');
});
});