33 class =" profiler-page-call-graph"
44 :class =" { 'profiler-page-call-graph--fullscreen': isFullscreen }"
55 >
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 >
13+
614 <div ref =" graphviz" class =" profiler-page-call-graph__graphviz" ></div >
15+
716 <div class =" profiler-page-call-graph__toolbar" >
817 <button title =" Full screen" @click =" isFullscreen = !isFullscreen" >
918 <IconSvg
1423 <button
1524 class =" profiler-page-call-graph__toolbar-action"
1625 :class =" { 'font-bold': metric === 'cpu' }"
17- @click =" metric = 'cpu'"
26+ @click =" setMetric( 'cpu') "
1827 >
1928 CPU
2029 </button >
2130 <button
2231 class =" profiler-page-call-graph__toolbar-action"
2332 :class =" { 'font-bold': metric === 'pmu' }"
24- @click =" metric = 'pmu'"
33+ @click =" setMetric( 'pmu') "
2534 >
2635 Memory change
2736 </button >
2837 <button
2938 class =" profiler-page-call-graph__toolbar-action"
3039 :class =" { 'font-bold': metric === 'mu' }"
31- @click =" metric = 'mu'"
40+ @click =" setMetric( 'mu') "
3241 >
3342 Memory usage
3443 </button >
3544 </div >
45+
46+ <div
47+ class =" profiler-page-call-graph__toolbar profiler-page-call-graph__toolbar--right"
48+ >
49+ <label class =" profiler-page-call-graph__toolbar-input-wr" >
50+ Threshold:
51+
52+ <input
53+ class =" profiler-page-call-graph__toolbar-input"
54+ type =" number"
55+ :value =" threshold"
56+ :min =" 0"
57+ :max =" 100"
58+ @input =" setThreshold($event.target.value)"
59+ />
60+ </label >
61+ </div >
3662 </div >
3763</template >
3864
@@ -46,6 +72,7 @@ import IconSvg from "~/components/IconSvg/IconSvg.vue";
4672import { defineComponent , PropType } from " vue" ;
4773import { Profiler , ProfilerEdge } from " ~/config/types" ;
4874import { addSlashes , DigraphBuilder } from " ~/utils/digraph-builder" ;
75+ import debounce from " lodash.debounce" ;
4976
5077export default defineComponent ({
5178 components: { IconSvg },
@@ -54,37 +81,55 @@ export default defineComponent({
5481 type: Object as PropType <Profiler >,
5582 required: true ,
5683 },
57- threshold: {
58- type: Number ,
59- default: 1 ,
60- },
6184 },
6285 emits: [" hover" , " hide" ],
6386 data() {
6487 return {
6588 isFullscreen: false ,
6689 metric: " cpu" ,
90+ metricLoading: false ,
91+ threshold: 1 ,
6792 };
6893 },
69- watch: {
70- threshold(): void {
71- this .renderGraph ();
72- },
73- metric(): void {
74- this .renderGraph ();
75- },
76- },
7794 created(): void {
78- this .renderGraph ();
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+ });
79103 },
80104 beforeUnmount() {
81105 this .graph .destroy ();
82106 },
83107 methods: {
84- buildDigraph(): string {
85- const builder = new DigraphBuilder (this .event .edges );
86-
87- return builder .build (this .metric , this .threshold );
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 );
116+ },
117+ setThreshold(threshold : number ): void {
118+ this .metricLoading = true ;
119+
120+ const prevThreshold = this .threshold ;
121+ 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 )();
88133 },
89134
90135 findEdge(name : string ): ProfilerEdge | null {
@@ -96,18 +141,19 @@ export default defineComponent({
96141 return null ;
97142 }
98143
99- return found [1 ] || null ;
144+ return found [0 ] || null ;
100145 },
101146 nodeHandler(): void {
102147 selectAll (" g.node" )
103148 .on (" mouseover" , (e , tag ) => {
104149 const edge = this .findEdge (tag .key );
150+
105151 if (! edge ) {
106152 return ;
107153 }
108154
109155 this .$emit (" hover" , {
110- name : edge .callee ,
156+ callee : edge .callee ,
111157 cost: edge .cost ,
112158 position: {
113159 x: e .pageX ,
@@ -120,19 +166,23 @@ export default defineComponent({
120166 });
121167 },
122168 renderGraph(): void {
123- Graphviz .load ().then (() => {
124- this .graph = graphviz (this .$refs .graphviz , {})
125- .width (" 100%" )
126- .height (" 100%" )
127- .fit (true )
128- .renderDot (this .buildDigraph (), this .nodeHandler );
129- });
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 ();
130178 },
131179 },
132180});
133181 </script >
134182
135183<style lang="scss" scoped>
184+ @import " assets/mixins" ;
185+
136186.profiler-page-call-graph {
137187 @apply relative flex rounded border border-gray-900 h-full ;
138188}
@@ -147,6 +197,10 @@ export default defineComponent({
147197 z-index : 9999 ;
148198}
149199
200+ .profiler-page-call-graph__toolbar--right {
201+ @apply right-5 left-auto ;
202+ }
203+
150204.profiler-page-call-graph__toolbar-icon {
151205 @apply w-4 h-4 fill-blue- 500;
152206}
@@ -155,68 +209,27 @@ export default defineComponent({
155209 @apply text-xs uppercase text-gray- 600;
156210}
157211
158- .profiler-page-call-graph__graphviz {
159- @apply flex-1 justify-items-stretch items-stretch bg-white ;
160-
161- .graph {
162- > polygon {
163- @apply fill-gray- 700;
164- }
165-
166- > path {
167- @apply fill-transparent ;
168- }
169- }
170-
171- .edge {
172- > path {
173- stroke-width : 2px ;
174- }
175-
176- > text {
177- @apply fill-white ml- 2;
178- }
179- }
180-
181- .node {
182- @apply cursor-pointer ;
183-
184- > path {
185- @apply rounded ;
186- stroke-width : 1 ;
187- }
188-
189- & .pmu {
190- > text {
191- @apply fill-white ;
192- }
212+ .profiler-page-call-graph__toolbar-input-wr {
213+ @apply text-xs uppercase text-gray- 600;
214+ }
193215
194- > path {
195- @apply fill-red- 600 stroke-red- 800 ;
196- }
216+ .profiler-page-call-graph__toolbar-input {
217+ @apply border-b bg-transparent border-gray- 600 text-gray-600 w- 8 ;
218+ }
197219
198- & :hover > path {
199- @apply fill-red- 800;
200- }
201- }
220+ .profiler-page-call-graph__loading-wr {
221+ @apply absolute m-auto top-0 left-0 right-0 bottom-0 flex justify-center items-center ;
222+ }
202223
203- & .default {
204- > text {
205- @apply fill-gray- 700;
206- }
224+ .profiler-page-call-graph__loading {
225+ @apply z- 50;
207226
208- > path {
209- @apply fill-gray-200 stroke-gray- 400;
210- }
227+ @include loading ;
228+ }
211229
212- & :hover > path {
213- @apply fill-gray- 300;
214- }
215- }
230+ .profiler-page-call-graph__graphviz {
231+ @apply flex-1 justify-items-stretch items-stretch bg-white ;
216232
217- > text {
218- @apply font-bold text-sm ;
219- }
220- }
233+ max-height : 100vh ;
221234}
222235 </style >
0 commit comments