Commit 27ad6cb7 authored by Denys Mishunov's avatar Denys Mishunov

Added all the essential User Timings to WebIDE

To be able to better tackle the performance issues in
WebIDE, we need to know what we measure and what we
optimise for. This commit brings several more User Timing
metrics into the mix which the further performance work
in WebIDE should be based upon.
parent 93862ef8
......@@ -5,10 +5,8 @@ import {
WEBIDE_MARK_APP_START,
WEBIDE_MARK_FILE_FINISH,
WEBIDE_MARK_FILE_CLICKED,
WEBIDE_MARK_TREE_FINISH,
WEBIDE_MEASURE_TREE_FROM_REQUEST,
WEBIDE_MEASURE_FILE_FROM_REQUEST,
WEBIDE_MEASURE_FILE_AFTER_INTERACTION,
WEBIDE_MEASURE_BEFORE_VUE,
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
import { modalTypes } from '../constants';
......@@ -19,12 +17,6 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { measurePerformance } from '../utils';
eventHub.$on(WEBIDE_MEASURE_TREE_FROM_REQUEST, () =>
measurePerformance(WEBIDE_MARK_TREE_FINISH, WEBIDE_MEASURE_TREE_FROM_REQUEST),
);
eventHub.$on(WEBIDE_MEASURE_FILE_FROM_REQUEST, () =>
measurePerformance(WEBIDE_MARK_FILE_FINISH, WEBIDE_MEASURE_FILE_FROM_REQUEST),
);
eventHub.$on(WEBIDE_MEASURE_FILE_AFTER_INTERACTION, () =>
measurePerformance(
WEBIDE_MARK_FILE_FINISH,
......@@ -84,7 +76,14 @@ export default {
document.querySelector('.navbar-gitlab').classList.add(`theme-${this.themeName}`);
},
beforeCreate() {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_APP_START });
performanceMarkAndMeasure({
mark: WEBIDE_MARK_APP_START,
measures: [
{
name: WEBIDE_MEASURE_BEFORE_VUE,
},
],
});
},
methods: {
...mapActions(['toggleFileFinder']),
......
......@@ -2,17 +2,13 @@
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import FileTree from '~/vue_shared/components/file_tree.vue';
import {
WEBIDE_MARK_TREE_START,
WEBIDE_MEASURE_TREE_FROM_REQUEST,
WEBIDE_MARK_FILE_CLICKED,
} from '~/performance/constants';
import { WEBIDE_MARK_FILE_CLICKED } from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
import eventHub from '../eventhub';
import IdeFileRow from './ide_file_row.vue';
import NavDropdown from './nav_dropdown.vue';
export default {
name: 'IdeTreeList',
components: {
GlSkeletonLoading,
NavDropdown,
......@@ -39,14 +35,6 @@ export default {
}
},
},
beforeCreate() {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_TREE_START });
},
updated() {
if (this.currentTree?.tree?.length) {
eventHub.$emit(WEBIDE_MEASURE_TREE_FROM_REQUEST);
}
},
methods: {
...mapActions(['toggleTreeOpen']),
clickedFile() {
......
......@@ -6,9 +6,10 @@ import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import {
WEBIDE_MARK_FILE_CLICKED,
WEBIDE_MARK_FILE_START,
WEBIDE_MARK_REPO_EDITOR_START,
WEBIDE_MARK_REPO_EDITOR_FINISH,
WEBIDE_MEASURE_REPO_EDITOR,
WEBIDE_MEASURE_FILE_AFTER_INTERACTION,
WEBIDE_MEASURE_FILE_FROM_REQUEST,
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
import eventHub from '../eventhub';
......@@ -28,6 +29,7 @@ import { getRulesWithTraversal } from '../lib/editorconfig/parser';
import mapRulesToMonaco from '../lib/editorconfig/rules_mapper';
export default {
name: 'RepoEditor',
components: {
ContentViewer,
DiffViewer,
......@@ -175,9 +177,6 @@ export default {
}
},
},
beforeCreate() {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FILE_START });
},
beforeDestroy() {
this.editor.dispose();
},
......@@ -204,6 +203,7 @@ export default {
]),
...mapActions('editor', ['updateFileEditor']),
initEditor() {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_REPO_EDITOR_START });
if (this.shouldHideEditor && (this.file.content || this.file.raw)) {
return;
}
......@@ -305,7 +305,15 @@ export default {
if (performance.getEntriesByName(WEBIDE_MARK_FILE_CLICKED).length) {
eventHub.$emit(WEBIDE_MEASURE_FILE_AFTER_INTERACTION);
} else {
eventHub.$emit(WEBIDE_MEASURE_FILE_FROM_REQUEST);
performanceMarkAndMeasure({
mark: WEBIDE_MARK_REPO_EDITOR_FINISH,
measures: [
{
name: WEBIDE_MEASURE_REPO_EDITOR,
start: WEBIDE_MARK_REPO_EDITOR_START,
},
],
});
}
},
refreshEditorDimensions() {
......
......@@ -3,6 +3,12 @@ import IdeRouter from '~/ide/ide_router_extension';
import { joinPaths } from '~/lib/utils/url_utility';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
import { performanceMarkAndMeasure } from '~/performance/utils';
import {
WEBIDE_MARK_FETCH_PROJECT_DATA_START,
WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
WEBIDE_MEASURE_FETCH_PROJECT_DATA,
} from '~/performance/constants';
import { syncRouterAndStore } from './sync_router_and_store';
Vue.use(IdeRouter);
......@@ -69,6 +75,7 @@ export const createRouter = store => {
router.beforeEach((to, from, next) => {
if (to.params.namespace && to.params.project) {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_PROJECT_DATA_START });
store
.dispatch('getProjectData', {
namespace: to.params.namespace,
......@@ -81,6 +88,15 @@ export const createRouter = store => {
const mergeRequestId = to.params.mrid;
if (branchId) {
performanceMarkAndMeasure({
mark: WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
measures: [
{
name: WEBIDE_MEASURE_FETCH_PROJECT_DATA,
start: WEBIDE_MARK_FETCH_PROJECT_DATA_START,
},
],
});
store.dispatch('openBranch', {
projectId,
branchId,
......
......@@ -2,6 +2,7 @@ import Vue from 'vue';
import { mapActions } from 'vuex';
import { identity } from 'lodash';
import Translate from '~/vue_shared/translate';
import PerformancePlugin from '~/performance/vue_performance_plugin';
import ide from './components/ide.vue';
import { createStore } from './stores';
import { createRouter } from './ide_router';
......@@ -11,6 +12,10 @@ import { DEFAULT_THEME } from './lib/themes';
Vue.use(Translate);
Vue.use(PerformancePlugin, {
components: ['FileTree'],
});
/**
* Function that receives the default store and returns an extended one.
* @callback extendStoreCallback
......
......@@ -3,6 +3,12 @@ import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import { deprecatedCreateFlash as flash } from '~/flash';
import { performanceMarkAndMeasure } from '~/performance/utils';
import {
WEBIDE_MARK_FETCH_BRANCH_DATA_START,
WEBIDE_MARK_FETCH_BRANCH_DATA_FINISH,
WEBIDE_MEASURE_FETCH_BRANCH_DATA,
} from '~/performance/constants';
import * as types from './mutation_types';
import { decorateFiles } from '../lib/files';
import { stageKeys, commitActionTypes } from '../constants';
......@@ -245,13 +251,23 @@ export const renameEntry = ({ dispatch, commit, state, getters }, { path, name,
dispatch('triggerFilesChange', { type: commitActionTypes.move, path, newPath });
};
export const getBranchData = ({ commit, state }, { projectId, branchId, force = false } = {}) =>
new Promise((resolve, reject) => {
export const getBranchData = ({ commit, state }, { projectId, branchId, force = false } = {}) => {
return new Promise((resolve, reject) => {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_BRANCH_DATA_START });
const currentProject = state.projects[projectId];
if (!currentProject || !currentProject.branches[branchId] || force) {
service
.getBranchData(projectId, branchId)
.then(({ data }) => {
performanceMarkAndMeasure({
mark: WEBIDE_MARK_FETCH_BRANCH_DATA_FINISH,
measures: [
{
name: WEBIDE_MEASURE_FETCH_BRANCH_DATA,
start: WEBIDE_MARK_FETCH_BRANCH_DATA_START,
},
],
});
const { id } = data.commit;
commit(types.SET_BRANCH, {
projectPath: projectId,
......@@ -291,6 +307,7 @@ export const getBranchData = ({ commit, state }, { projectId, branchId, force =
resolve(currentProject.branches[branchId]);
}
});
};
export * from './actions/tree';
export * from './actions/file';
......
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import { performanceMarkAndMeasure } from '~/performance/utils';
import {
WEBIDE_MARK_FETCH_FILE_DATA_START,
WEBIDE_MARK_FETCH_FILE_DATA_FINISH,
WEBIDE_MEASURE_FETCH_FILE_DATA,
} from '~/performance/constants';
import eventHub from '../../eventhub';
import service from '../../services';
import * as types from '../mutation_types';
......@@ -61,6 +67,7 @@ export const getFileData = (
{ state, commit, dispatch, getters },
{ path, makeFileActive = true, openFile = makeFileActive, toggleLoading = true },
) => {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_FILE_DATA_START });
const file = state.entries[path];
const fileDeletedAndReadded = getters.isFileDeletedAndReadded(path);
......@@ -81,6 +88,15 @@ export const getFileData = (
return service
.getFileData(url)
.then(({ data }) => {
performanceMarkAndMeasure({
mark: WEBIDE_MARK_FETCH_FILE_DATA_FINISH,
measures: [
{
name: WEBIDE_MEASURE_FETCH_FILE_DATA,
start: WEBIDE_MARK_FETCH_FILE_DATA_START,
},
],
});
if (data) commit(types.SET_FILE_DATA, { data, file });
if (openFile) commit(types.TOGGLE_FILE_OPEN, path);
......
import { defer } from 'lodash';
import { performanceMarkAndMeasure } from '~/performance/utils';
import {
WEBIDE_MARK_FETCH_FILES_FINISH,
WEBIDE_MEASURE_FETCH_FILES,
WEBIDE_MARK_FETCH_FILES_START,
} from '~/performance/constants';
import { __ } from '../../../locale';
import service from '../../services';
import * as types from '../mutation_types';
......@@ -46,8 +52,9 @@ export const setDirectoryData = ({ state, commit }, { projectId, branchId, treeL
});
};
export const getFiles = ({ state, commit, dispatch }, payload = {}) =>
new Promise((resolve, reject) => {
export const getFiles = ({ state, commit, dispatch }, payload = {}) => {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_FILES_START });
return new Promise((resolve, reject) => {
const { projectId, branchId, ref = branchId } = payload;
if (
......@@ -61,6 +68,15 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) =>
service
.getFiles(selectedProject.path_with_namespace, ref)
.then(({ data }) => {
performanceMarkAndMeasure({
mark: WEBIDE_MARK_FETCH_FILES_FINISH,
measures: [
{
name: WEBIDE_MEASURE_FETCH_FILES,
start: WEBIDE_MARK_FETCH_FILES_START,
},
],
});
const { entries, treeList } = decorateFiles({ data });
commit(types.SET_ENTRIES, entries);
......@@ -85,6 +101,7 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) =>
resolve();
}
});
};
export const restoreTree = ({ dispatch, commit, state }, path) => {
const entry = state.entries[path];
......
......@@ -19,16 +19,27 @@ export const SNIPPET_MEASURE_BLOBS_CONTENT = 'snippet-blobs-content';
// Marks
export const WEBIDE_MARK_APP_START = 'webide-app-start';
export const WEBIDE_MARK_TREE_START = 'webide-tree-start';
export const WEBIDE_MARK_TREE_FINISH = 'webide-tree-finished';
export const WEBIDE_MARK_FILE_START = 'webide-file-start';
export const WEBIDE_MARK_FILE_CLICKED = 'webide-file-clicked';
export const WEBIDE_MARK_FILE_FINISH = 'webide-file-finished';
export const WEBIDE_MARK_REPO_EDITOR_START = 'webide-init-editor-start';
export const WEBIDE_MARK_REPO_EDITOR_FINISH = 'webide-init-editor-finish';
export const WEBIDE_MARK_FETCH_BRANCH_DATA_START = 'webide-getBranchData-start';
export const WEBIDE_MARK_FETCH_BRANCH_DATA_FINISH = 'webide-getBranchData-finish';
export const WEBIDE_MARK_FETCH_FILE_DATA_START = 'webide-getFileData-start';
export const WEBIDE_MARK_FETCH_FILE_DATA_FINISH = 'webide-getFileData-finish';
export const WEBIDE_MARK_FETCH_FILES_START = 'webide-getFiles-start';
export const WEBIDE_MARK_FETCH_FILES_FINISH = 'webide-getFiles-finish';
export const WEBIDE_MARK_FETCH_PROJECT_DATA_START = 'webide-getProjectData-start';
export const WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH = 'webide-getProjectData-finish';
// Measures
export const WEBIDE_MEASURE_TREE_FROM_REQUEST = 'webide-tree-loading-from-request';
export const WEBIDE_MEASURE_FILE_FROM_REQUEST = 'webide-file-loading-from-request';
export const WEBIDE_MEASURE_FILE_AFTER_INTERACTION = 'webide-file-loading-after-interaction';
export const WEBIDE_MEASURE_FETCH_PROJECT_DATA = 'WebIDE: Project data';
export const WEBIDE_MEASURE_FETCH_BRANCH_DATA = 'WebIDE: Branch data';
export const WEBIDE_MEASURE_FETCH_FILE_DATA = 'WebIDE: File data';
export const WEBIDE_MEASURE_BEFORE_VUE = 'WebIDE: Before Vue app';
export const WEBIDE_MEASURE_REPO_EDITOR = 'WebIDE: Repo Editor';
export const WEBIDE_MEASURE_FETCH_FILES = 'WebIDE: Fetch Files';
//
// MR Diffs namespace
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment