Skip to content

Commit f1b16d4

Browse files
authored
Merge pull request #49 from buggregator/issue/#33-improve-callgrph-performance
Issue/#33 improve callgrph performance
2 parents 50a71a6 + 6ddcae6 commit f1b16d4

File tree

13 files changed

+479
-344
lines changed

13 files changed

+479
-344
lines changed

assets/digraph-builder.scss

Lines changed: 0 additions & 68 deletions
This file was deleted.

assets/index.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
@import "vendor.css";
2-
@import "digraph-builder.scss";
32

43
body {
54
@apply bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-50 p-0;

components/ProfilerPage/ProfilerPage.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
<Tabs :options="{ useUrlFragment: false }" @changed="tabChange">
2222
<Tab name="Call graph">
2323
<ProfilerPageCallGraph
24+
v-if="activeTab === 'Call graph'"
2425
:event="event.payload"
2526
@hover="setActiveEdge"
2627
@hide="setActiveEdge"
2728
/>
2829
</Tab>
2930
<Tab name="Flamechart">
3031
<ProfilePageFlamegraph
32+
v-if="activeTab === 'Flamechart'"
3133
:key="activeTab"
3234
:data-key="activeTab"
3335
:edges="event.payload.edges"
Lines changed: 61 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
<template>
22
<div
3+
ref="container"
34
class="profiler-page-call-graph"
45
:class="{ 'profiler-page-call-graph--fullscreen': isFullscreen }"
56
>
6-
<div v-if="metricLoading" class="profiler-page-call-graph__loading-wr">
7-
<div class="profiler-page-call-graph__loading">
8-
<div></div>
9-
<div></div>
10-
<div></div>
11-
</div>
12-
</div>
7+
<RenderGraph
8+
v-if="isReadyGraph && graphKey"
9+
:key="graphKey"
10+
:elements="graphElements"
11+
:height="graphHeight"
12+
>
13+
<template #default="{ data: { name, cost } }">
14+
<div class="profiler-page-call-graph__board">
15+
<h4 class="profiler-page-call-graph__board-title">
16+
{{ name }}
17+
</h4>
1318

14-
<div ref="graphviz" class="profiler-page-call-graph__graphviz"></div>
19+
<StatBoard :cost="cost" />
20+
</div>
21+
</template>
22+
</RenderGraph>
1523

1624
<div class="profiler-page-call-graph__toolbar">
1725
<button title="Full screen" @click="isFullscreen = !isFullscreen">
@@ -22,22 +30,22 @@
2230
</button>
2331
<button
2432
class="profiler-page-call-graph__toolbar-action"
25-
:class="{ 'font-bold': metric === 'cpu' }"
26-
@click="setMetric('cpu')"
33+
:class="{ 'font-bold': metric === graphMetrics.CPU }"
34+
@click="setMetric(graphMetrics.CPU)"
2735
>
2836
CPU
2937
</button>
3038
<button
3139
class="profiler-page-call-graph__toolbar-action"
32-
:class="{ 'font-bold': metric === 'pmu' }"
33-
@click="setMetric('pmu')"
40+
:class="{ 'font-bold': metric === graphMetrics.MEMORY_CHANGE }"
41+
@click="setMetric(graphMetrics.MEMORY_CHANGE)"
3442
>
3543
Memory change
3644
</button>
3745
<button
3846
class="profiler-page-call-graph__toolbar-action"
39-
:class="{ 'font-bold': metric === 'mu' }"
40-
@click="setMetric('mu')"
47+
:class="{ 'font-bold': metric === graphMetrics.MEMORY }"
48+
@click="setMetric(graphMetrics.MEMORY)"
4149
>
4250
Memory usage
4351
</button>
@@ -63,19 +71,16 @@
6371
</template>
6472

6573
<script lang="ts">
66-
import { selectAll } from "d3-selection";
67-
import { graphviz } from "d3-graphviz";
68-
import { Graphviz } from "@hpcc-js/wasm/graphviz";
69-
7074
import IconSvg from "~/components/IconSvg/IconSvg.vue";
7175
7276
import { defineComponent, PropType } from "vue";
73-
import { Profiler, ProfilerEdge } from "~/config/types";
74-
import { addSlashes, DigraphBuilder } from "~/utils/digraph-builder";
75-
import debounce from "lodash.debounce";
77+
import { GraphTypes, Profiler } from "~/config/types";
78+
import { calcGraphData } from "~/utils/calc-graph-data";
79+
import RenderGraph from "~/components/RenderGraph/RenderGraph.vue";
80+
import StatBoard from "~/components/StatBoard/StatBoard.vue";
7681
7782
export default defineComponent({
78-
components: { IconSvg },
83+
components: { StatBoard, RenderGraph, IconSvg },
7984
props: {
8085
event: {
8186
type: Object as PropType<Profiler>,
@@ -86,95 +91,40 @@ export default defineComponent({
8691
data() {
8792
return {
8893
isFullscreen: false,
89-
metric: "cpu",
90-
metricLoading: false,
94+
metric: GraphTypes.CPU as GraphTypes,
9195
threshold: 1,
96+
isReadyGraph: false,
9297
};
9398
},
94-
created(): void {
95-
Graphviz.load().then(() => {
96-
this.graph = graphviz(this.$refs.graphviz, {})
97-
.width("100%")
98-
.height("100%")
99-
.fit(true);
100-
101-
this.renderGraph();
102-
});
99+
computed: {
100+
graphElements() {
101+
return calcGraphData(this.event.edges, this.metric, this.threshold);
102+
},
103+
graphKey() {
104+
return `${this.metric}-${this.threshold}`;
105+
},
106+
graphMetrics() {
107+
return GraphTypes;
108+
},
109+
graphHeight() {
110+
return this.isFullscreen
111+
? window.innerHeight
112+
: (this.$refs.container as HTMLElement).offsetHeight;
113+
},
103114
},
104-
beforeUnmount() {
105-
this.graph.destroy();
115+
mounted() {
116+
// NOTE: need to show graph after parent render
117+
this.setReadyGraph();
106118
},
107119
methods: {
108-
setMetric(metric: string): void {
109-
this.metricLoading = true;
110-
111-
setTimeout(() => {
112-
this.metric = metric;
113-
this.renderGraph();
114-
this.metricLoading = false;
115-
}, 0);
120+
setMetric(metric: GraphTypes): void {
121+
this.metric = metric;
116122
},
117123
setThreshold(threshold: number): void {
118-
this.metricLoading = true;
119-
120-
const prevThreshold = this.threshold;
121124
this.threshold = threshold;
122-
123-
return debounce(() => {
124-
if (!threshold || prevThreshold === threshold) {
125-
return;
126-
}
127-
128-
setTimeout(() => {
129-
this.renderGraph();
130-
this.metricLoading = false;
131-
}, 0);
132-
}, 1000)();
133-
},
134-
135-
findEdge(name: string): ProfilerEdge | null {
136-
const found = Object.values(this.event.edges).filter(
137-
(v) => addSlashes(v.callee) === name
138-
);
139-
140-
if (!found || found.length === 0) {
141-
return null;
142-
}
143-
144-
return found[0] || null;
145125
},
146-
nodeHandler(): void {
147-
selectAll("g.node")
148-
.on("mouseover", (e, tag) => {
149-
const edge = this.findEdge(tag.key);
150-
151-
if (!edge) {
152-
return;
153-
}
154-
155-
this.$emit("hover", {
156-
callee: edge.callee,
157-
cost: edge.cost,
158-
position: {
159-
x: e.pageX,
160-
y: e.pageY,
161-
},
162-
});
163-
})
164-
.on("mouseout", () => {
165-
this.$emit("hide");
166-
});
167-
},
168-
renderGraph(): void {
169-
this.graph
170-
.renderDot(
171-
new DigraphBuilder(this.event.edges).build(
172-
this.metric,
173-
this.threshold
174-
),
175-
this.nodeHandler
176-
)
177-
.resetZoom();
126+
setReadyGraph(): void {
127+
this.isReadyGraph = true;
178128
},
179129
},
180130
});
@@ -184,11 +134,19 @@ export default defineComponent({
184134
@import "assets/mixins";
185135
186136
.profiler-page-call-graph {
187-
@apply relative flex rounded border border-gray-900 h-full;
137+
@apply relative flex rounded border border-gray-900 min-h-min min-w-min;
188138
}
189139
190140
.profiler-page-call-graph--fullscreen {
191-
@apply rounded-none mt-0 top-0 left-0 fixed w-full h-full;
141+
@apply rounded-none mt-0 top-0 left-0 fixed w-full h-full bg-gray-800 z-[99999];
142+
}
143+
144+
.profiler-page-call-graph__board {
145+
@apply border border-gray-600 bg-gray-800 h-full;
146+
}
147+
148+
.profiler-page-call-graph__board-title {
149+
@apply px-4 py-2 font-bold truncate text-gray-300;
192150
}
193151
194152
.profiler-page-call-graph__toolbar {
@@ -214,20 +172,4 @@ export default defineComponent({
214172
.profiler-page-call-graph__toolbar-input {
215173
@apply border-b bg-transparent border-gray-600 text-gray-600 w-8;
216174
}
217-
218-
.profiler-page-call-graph__loading-wr {
219-
@apply absolute m-auto top-0 left-0 right-0 bottom-0 flex justify-center items-center;
220-
}
221-
222-
.profiler-page-call-graph__loading {
223-
@apply z-50;
224-
225-
@include loading;
226-
}
227-
228-
.profiler-page-call-graph__graphviz {
229-
@apply flex-1 justify-items-stretch items-stretch bg-white;
230-
231-
max-height: 100vh;
232-
}
233175
</style>

0 commit comments

Comments
 (0)