Skip to content

Commit c739428

Browse files
committed
feat(profiling): refactorign profiling code, grafana#5286
1 parent 2a7d2ff commit c739428

File tree

9 files changed

+143
-114
lines changed

9 files changed

+143
-114
lines changed

public/app/core/components/grafana_app.ts

Lines changed: 3 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import _ from 'lodash';
66
import angular from 'angular';
77
import $ from 'jquery';
88
import coreModule from 'app/core/core_module';
9+
import {profiler} from 'app/core/profiler';
910

1011
export class GrafanaCtrl {
1112

@@ -15,14 +16,10 @@ export class GrafanaCtrl {
1516
$scope.init = function() {
1617
$scope.contextSrv = contextSrv;
1718

18-
$scope._ = _;
19-
20-
$rootScope.profilingEnabled = store.getBool('profilingEnabled') || config.buildInfo.env === 'development';
21-
$rootScope.performance = { loadStart: new Date().getTime() };
2219
$rootScope.appSubUrl = config.appSubUrl;
20+
$scope._ = _;
2321

24-
if ($rootScope.profilingEnabled) { $scope.initProfiling(); }
25-
22+
profiler.init(config, $rootScope);
2623
alertSrv.init();
2724
utilSrv.init();
2825

@@ -59,82 +56,6 @@ export class GrafanaCtrl {
5956
"#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7"
6057
];
6158

62-
$scope.getTotalWatcherCount = function() {
63-
var count = 0;
64-
var scopes = 0;
65-
var root = $(document.getElementsByTagName('body'));
66-
67-
var f = function (element) {
68-
if (element.data().hasOwnProperty('$scope')) {
69-
scopes++;
70-
angular.forEach(element.data().$scope.$$watchers, function () {
71-
count++;
72-
});
73-
}
74-
75-
angular.forEach(element.children(), function (childElement) {
76-
f($(childElement));
77-
});
78-
};
79-
80-
f(root);
81-
$rootScope.performance.scopeCount = scopes;
82-
return count;
83-
};
84-
85-
$scope.initProfiling = function() {
86-
var count = 0;
87-
88-
$scope.$watch(function digestCounter() {
89-
count++;
90-
}, function() {
91-
// something
92-
});
93-
94-
$rootScope.performance.panels = [];
95-
96-
$scope.$on('refresh', function() {
97-
if ($rootScope.performance.panels.length > 0) {
98-
var totalRender = 0;
99-
var totalQuery = 0;
100-
101-
_.each($rootScope.performance.panels, function(panelTiming: any) {
102-
totalRender += panelTiming.render;
103-
totalQuery += panelTiming.query;
104-
});
105-
106-
console.log('total query: ' + totalQuery);
107-
console.log('total render: ' + totalRender);
108-
console.log('avg render: ' + totalRender / $rootScope.performance.panels.length);
109-
}
110-
111-
$rootScope.performance.panels = [];
112-
});
113-
114-
$scope.onAppEvent('dashboard-loaded', function() {
115-
count = 0;
116-
117-
setTimeout(function() {
118-
console.log("Dashboard::Performance Total Digests: " + count);
119-
console.log("Dashboard::Performance Total Watchers: " + $scope.getTotalWatcherCount());
120-
console.log("Dashboard::Performance Total ScopeCount: " + $rootScope.performance.scopeCount);
121-
122-
var timeTaken = $rootScope.performance.allPanelsInitialized - $rootScope.performance.dashboardLoadStart;
123-
console.log("Dashboard::Performance - All panels initialized in " + timeTaken + " ms");
124-
125-
// measure digest performance
126-
var rootDigestStart = window.performance.now();
127-
for (var i = 0; i < 30; i++) {
128-
$rootScope.$apply();
129-
}
130-
console.log("Dashboard::Performance Root Digest " + ((window.performance.now() - rootDigestStart) / 30));
131-
132-
}, 3000);
133-
134-
});
135-
136-
};
137-
13859
$scope.init();
13960
}
14061
}

public/app/core/profiler.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
///<reference path="../headers/common.d.ts" />
2+
//
3+
import $ from 'jquery';
4+
import _ from 'lodash';
5+
import angular from 'angular';
6+
7+
export class Profiler {
8+
panelsRendered: number;
9+
enabled: boolean;
10+
panels: any[];
11+
panelsInitCount: any;
12+
timings: any;
13+
digestCounter: any;
14+
$rootScope: any;
15+
scopeCount: any;
16+
17+
init(config, $rootScope) {
18+
this.enabled = config.buildInfo.env === 'development';
19+
this.timings = {};
20+
this.timings.appStart = { loadStart: new Date().getTime() };
21+
this.$rootScope = $rootScope;
22+
23+
if (!this.enabled) {
24+
return;
25+
}
26+
27+
$rootScope.$watch(() => {
28+
this.digestCounter++;
29+
return false;
30+
}, () => {});
31+
32+
$rootScope.$on('refresh', this.refresh.bind(this));
33+
$rootScope.onAppEvent('dashboard-fetched', this.dashboardFetched.bind(this));
34+
$rootScope.onAppEvent('dashboard-initialized', this.dashboardInitialized.bind(this));
35+
$rootScope.onAppEvent('panel-initialized', this.panelInitialized.bind(this));
36+
}
37+
38+
refresh() {
39+
if (this.panels.length > 0) {
40+
var totalRender = 0;
41+
var totalQuery = 0;
42+
43+
for (let panelTiming of this.panels) {
44+
totalRender += panelTiming.render;
45+
totalQuery += panelTiming.query;
46+
}
47+
48+
console.log('panel count: ' + this.panels.length);
49+
console.log('total query: ' + totalQuery);
50+
console.log('total render: ' + totalRender);
51+
console.log('avg render: ' + totalRender / this.panels.length);
52+
}
53+
this.$rootScope.panels = [];
54+
}
55+
56+
dashboardFetched() {
57+
this.timings.dashboardLoadStart = new Date().getTime();
58+
this.panelsInitCount = 0;
59+
this.digestCounter = 0;
60+
this.panelsInitCount = 0;
61+
this.panelsRendered = 0;
62+
this.panels = [];
63+
}
64+
65+
dashboardInitialized() {
66+
setTimeout(() => {
67+
console.log("Dashboard::Performance Total Digests: " + this.digestCounter);
68+
console.log("Dashboard::Performance Total Watchers: " + this.getTotalWatcherCount());
69+
console.log("Dashboard::Performance Total ScopeCount: " + this.scopeCount);
70+
71+
var timeTaken = this.timings.lastPanelInitializedAt - this.timings.dashboardLoadStart;
72+
console.log("Dashboard::Performance All panels initialized in " + timeTaken + " ms");
73+
74+
// measure digest performance
75+
var rootDigestStart = window.performance.now();
76+
for (var i = 0; i < 30; i++) {
77+
this.$rootScope.$apply();
78+
}
79+
80+
console.log("Dashboard::Performance Root Digest " + ((window.performance.now() - rootDigestStart) / 30));
81+
}, 3000);
82+
}
83+
84+
getTotalWatcherCount() {
85+
var count = 0;
86+
var scopes = 0;
87+
var root = $(document.getElementsByTagName('body'));
88+
89+
var f = function (element) {
90+
if (element.data().hasOwnProperty('$scope')) {
91+
scopes++;
92+
angular.forEach(element.data().$scope.$$watchers, function () {
93+
count++;
94+
});
95+
}
96+
97+
angular.forEach(element.children(), function (childElement) {
98+
f($(childElement));
99+
});
100+
};
101+
102+
f(root);
103+
this.scopeCount = scopes;
104+
return count;
105+
}
106+
107+
renderingCompleted(panelId, panelTimings) {
108+
this.panelsRendered++;
109+
110+
if (this.enabled) {
111+
panelTimings.renderEnd = new Date().getTime();
112+
this.panels.push({
113+
panelId: panelId,
114+
query: panelTimings.queryEnd - panelTimings.queryStart,
115+
render: panelTimings.renderEnd - panelTimings.renderStart,
116+
});
117+
}
118+
}
119+
120+
panelInitialized() {
121+
if (!this.enabled) {
122+
return;
123+
}
124+
125+
this.panelsInitCount++;
126+
this.timings.lastPanelInitializedAt = new Date().getTime();
127+
}
128+
129+
}
130+
131+
var profiler = new Profiler();
132+
export {profiler};

public/app/features/annotations/annotations_srv.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ define([
1414

1515
this.init = function() {
1616
$rootScope.onAppEvent('refresh', this.clearCache, $rootScope);
17-
$rootScope.onAppEvent('dashboard-loaded', this.clearCache, $rootScope);
17+
$rootScope.onAppEvent('dashboard-initialized', this.clearCache, $rootScope);
1818
};
1919

2020
this.clearCache = function() {

public/app/features/dashboard/dashboardCtrl.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ function (angular, $, config, moment) {
3535
};
3636

3737
$scope.setupDashboard = function(data) {
38-
$rootScope.performance.dashboardLoadStart = new Date().getTime();
39-
$rootScope.performance.panelsInitialized = 0;
40-
$rootScope.performance.panelsRendered = 0;
41-
4238
var dashboard = dashboardSrv.create(data.dashboard, data.meta);
4339
dashboardSrv.setCurrent(dashboard);
4440

@@ -68,7 +64,7 @@ function (angular, $, config, moment) {
6864
});
6965
}
7066

71-
$scope.appEvent("dashboard-loaded", $scope.dashboard);
67+
$scope.appEvent("dashboard-initialized", $scope.dashboard);
7268
}).catch(function(err) {
7369
if (err.data && err.data.message) { err.message = err.data.message; }
7470
$scope.appEvent("alert-error", ['Dashboard init failed', 'Template variables could not be initialized: ' + err.message]);
@@ -84,7 +80,6 @@ function (angular, $, config, moment) {
8480
};
8581

8682
$scope.broadcastRefresh = function() {
87-
$rootScope.performance.panelsRendered = 0;
8883
$rootScope.$broadcast('refresh');
8984
};
9085

public/app/features/dashboard/dashboardLoaderSrv.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ function (angular, moment, _, $, kbn, dateMath, impressionStore) {
4747
}
4848

4949
promise.then(function(result) {
50+
$rootScope.appEvent("dashboard-fetched", result.dashboard);
51+
5052
if (result.meta.dashboardNotFound !== true) {
5153
impressionStore.impressions.addDashboardImpression(result.dashboard.id);
5254
}

public/app/features/dashboard/viewStateSrv.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,6 @@ function (angular, _, $) {
5151

5252
$scope.onAppEvent('panel-initialized', function(evt, payload) {
5353
self.registerPanel(payload.scope);
54-
55-
if ($scope.profilingEnabled) {
56-
$scope.performance.panelsInitialized++;
57-
if ($scope.performance.panelsInitialized === $scope.performance.panelCount) {
58-
$scope.performance.allPanelsInitialized = new Date().getTime();
59-
}
60-
}
6154
});
6255

6356
this.update(this.getQueryStringState());

public/app/features/panel/panel_ctrl.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import config from 'app/core/config';
44
import _ from 'lodash';
55
import angular from 'angular';
66
import $ from 'jquery';
7+
import {profiler} from 'app/core/profiler';
78

89
const TITLE_HEIGHT = 25;
910
const EMPTY_TITLE_HEIGHT = 9;
@@ -59,21 +60,7 @@ export class PanelCtrl {
5960
}
6061

6162
renderingCompleted() {
62-
this.$scope.$root.performance.panelsRendered++;
63-
this.timing.renderEnd = new Date().getTime();
64-
if (this.$scope.$root.profilingEnabled) {
65-
this.$scope.$root.performance.panels.push({
66-
panelId: this.panel.id,
67-
query: this.timing.queryEnd - this.timing.queryStart,
68-
render: this.timing.renderEnd - this.timing.renderStart,
69-
});
70-
71-
if (this.$scope.$root.performance.panelsRendered === this.$scope.$root.performance.panelCount) {
72-
this.$scope.$root.performance.allPanelsRendered = new Date().getTime();
73-
var timeTaken = this.$scope.$root.performance.allPanelsRendered - this.$scope.$root.performance.dashboardLoadStart;
74-
console.log("Dashboard::Performance - All panels rendered in " + timeTaken + " ms");
75-
}
76-
}
63+
profiler.renderingCompleted(this.panel.id, this.timing);
7764
}
7865

7966
refresh() {

public/app/features/panel/solo_panel_ctrl.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function (angular, $) {
2525
$scope.initDashboard(result, $scope);
2626
});
2727

28-
$scope.onAppEvent("dashboard-loaded", $scope.initPanelScope);
28+
$scope.onAppEvent("dashboard-initialized", $scope.initPanelScope);
2929
};
3030

3131
$scope.initPanelScope = function() {

public/test/specs/dashboardViewStateSrv-specs.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ define([
3131
it('should update querystring and view state', function() {
3232
var updateState = {fullscreen: true, edit: true, panelId: 1};
3333
viewState.update(updateState);
34-
expect(location.search()).to.eql({fullscreen: true, edit: true, panelId: 1, org: 19});
34+
expect(location.search()).to.eql({fullscreen: true, edit: true, panelId: 1});
3535
expect(viewState.dashboard.meta.fullscreen).to.be(true);
3636
expect(viewState.state.fullscreen).to.be(true);
3737
});
@@ -41,7 +41,6 @@ define([
4141
it('should remove params from query string', function() {
4242
viewState.update({fullscreen: true, panelId: 1, edit: true});
4343
viewState.update({fullscreen: false});
44-
expect(location.search()).to.eql({org: 19});
4544
expect(viewState.dashboard.meta.fullscreen).to.be(false);
4645
expect(viewState.state.fullscreen).to.be(null);
4746
});

0 commit comments

Comments
 (0)