IDEA-207119 precise app start-up time

This commit is contained in:
Vladimir Krivosheev
2019-02-22 22:17:07 +01:00
parent 7077217bf1
commit 0045099470
14 changed files with 2225 additions and 757 deletions
@@ -88,6 +88,7 @@ define("ComponentsChartManager", ["require", "exports", "@amcharts/amcharts4/cha
nameAxisLabel.horizontalCenter = "right";
nameAxis.renderer.minGridDistance = 1;
nameAxis.renderer.grid.template.location = 0;
nameAxis.renderer.grid.template.disabled = true;
}
configureDurationAxis() {
const durationAxis = this.chart.yAxes.push(new am4charts.DurationAxis());
@@ -119,7 +120,31 @@ define("ComponentsChartManager", ["require", "exports", "@amcharts/amcharts4/cha
}
exports.ComponentsChartManager = ComponentsChartManager;
});
define("TimeLineChartManager", ["require", "exports", "core", "@amcharts/amcharts4/charts", "@amcharts/amcharts4/core"], function (require, exports, core_2, am4charts, am4core) {
define("timeLineChartHelper", ["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function computeLevels(items) {
let lastAllocatedColorIndex = 0;
for (let i = 0; i < items.length; i++) {
const item = items[i];
let level = 0;
for (let j = i - 1; j >= 0; j--) {
const prevItem = items[j];
if (prevItem.end >= item.end) {
level = prevItem.level + 1;
item.colorIndex = prevItem.colorIndex;
break;
}
}
if (item.colorIndex === undefined) {
item.colorIndex = lastAllocatedColorIndex++;
}
item.level = level;
}
}
exports.computeLevels = computeLevels;
});
define("TimeLineChartManager", ["require", "exports", "core", "@amcharts/amcharts4/charts", "@amcharts/amcharts4/core", "timeLineChartHelper"], function (require, exports, core_2, am4charts, am4core, timeLineChartHelper_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// https://github.com/almende/vis/blob/master/examples/timeline/dataHandling/dataSerialization.html
@@ -145,6 +170,7 @@ define("TimeLineChartManager", ["require", "exports", "core", "@amcharts/amchart
levelAxis.renderer.grid.template.location = 0;
levelAxis.renderer.minGridDistance = 1;
levelAxis.renderer.labels.template.disabled = true;
// levelAxis.renderer.grid.template.disabled = true
return levelAxis;
}
configureDurationAxis() {
@@ -182,6 +208,11 @@ define("TimeLineChartManager", ["require", "exports", "core", "@amcharts/amchart
// https://www.amcharts.com/docs/v4/tutorials/auto-adjusting-chart-height-based-on-a-number-of-data-items/
// noinspection SpellCheckingInspection
this.chart.events.on("datavalidated", () => {
const grid = this.chart.yAxes.getIndex(0).renderer.grid;
// hide all grid lines except first and last
for (let i = 1; i < (grid.length - 1); i++) {
grid.getIndex(i).disabled = true;
}
const chart = this.chart;
const adjustHeight = chart.data.reduce((max, item) => Math.max(item.rowIndex, max), 0) * 35 - levelAxis.pixelHeight;
// get current chart height
@@ -193,7 +224,7 @@ define("TimeLineChartManager", ["require", "exports", "core", "@amcharts/amchart
render(ijData) {
const items = ijData.items;
const firstStart = new Date(items[0].start);
const timeOffset = items[0].start;
const timeOffset = 0;
const data = transformIjData(ijData, timeOffset);
this.chart.data = data;
const originalItems = items;
@@ -202,45 +233,27 @@ define("TimeLineChartManager", ["require", "exports", "core", "@amcharts/amchart
}
}
exports.TimelineChartManager = TimelineChartManager;
function computeLevels(items) {
for (let i = 0; i < items.length; i++) {
const item = items[i];
let level = 0;
for (let j = i - 1; j >= 0; j--) {
const prevItem = items[j];
if (prevItem.end >= item.end) {
level = prevItem.level + 1;
break;
}
}
item.level = level;
}
}
function transformIjData(input, timeOffset) {
const colorSet = new am4core.ColorSet();
const transformedItems = new Array(input.items.length);
computeLevels(input.items);
timeLineChartHelper_1.computeLevels(input.items);
// we cannot use actual level as row index because in this case labels will be overlapped, so,
// row index simply incremented till empirical limit (6).
let rowIndex = 0;
for (let i = 0; i < input.items.length; i++) {
const item = input.items[i];
if (rowIndex > 5 && item.level === 0) {
rowIndex = 0;
}
const result = {
name: item.name,
start: item.start - timeOffset,
end: item.end - timeOffset,
duration: item.duration,
// level: item.isSubItem ? 2 : 1
// level: "l" + getLevel(i, input.items, transformedItems).toString(),
// level: getLevel(i, input.items, transformedItems),
// level: item.level,
rowIndex: rowIndex++,
color: colorSet.getIndex(item.level),
color: colorSet.getIndex(item.colorIndex),
level: item.level,
};
if (rowIndex > 6) {
rowIndex = 0;
}
transformedItems[i] = result;
}
transformedItems.sort((a, b) => a.rowIndex - b.rowIndex);
@@ -253,550 +266,527 @@ define("dev", ["require", "exports", "TimeLineChartManager"], function (require,
Object.defineProperty(exports, "__esModule", { value: true });
const data = {
"items": [
{
"name": "app initialization preparation",
"duration": 2744,
"start": 0,
"end": 2744
},
{
"name": "app initialization",
"duration": 307,
"start": 1550844299966,
"end": 1550844300273
"duration": 302,
"start": 2744,
"end": 3046
},
{
"name": "plugins initialization",
"description": "plugin count: 189",
"duration": 353,
"start": 1550844300280,
"end": 1550844300633
"duration": 369,
"start": 3053,
"end": 3423
},
{
"name": "plugin descriptors loading",
"isSubItem": true,
"duration": 265,
"start": 1550844300281,
"end": 1550844300546
"duration": 281,
"start": 3054,
"end": 3335
},
{
"name": "app components initialization",
"description": "component count: 101",
"duration": 3254,
"start": 1550844300634,
"end": 1550844303888
"duration": 3029,
"start": 3424,
"end": 6453
},
{
"name": "app components registration",
"isSubItem": true,
"duration": 330,
"start": 1550844300634,
"end": 1550844300964
"duration": 323,
"start": 3424,
"end": 3747
},
{
"name": "app components registered callback",
"isSubItem": true,
"duration": 111,
"start": 1550844300964,
"end": 1550844301075
"start": 3747,
"end": 3859
},
{
"name": "app components creation",
"isSubItem": true,
"duration": 2813,
"start": 1550844301075,
"end": 1550844303888
"duration": 2594,
"start": 3859,
"end": 6453
},
{
"name": "app initialized callback",
"duration": 242,
"start": 1550844303888,
"end": 1550844304130
"duration": 229,
"start": 6453,
"end": 6683
},
{
"name": "project components initialization",
"description": "component count: 210",
"duration": 2295,
"start": 1550844304955,
"end": 1550844307250
"duration": 2008,
"start": 7490,
"end": 9498
},
{
"name": "project components registration",
"isSubItem": true,
"duration": 782,
"start": 1550844304955,
"end": 1550844305737
"duration": 760,
"start": 7490,
"end": 8250
},
{
"name": "project components creation",
"isSubItem": true,
"duration": 1513,
"start": 1550844305737,
"end": 1550844307250
"duration": 1248,
"start": 8250,
"end": 9498
},
{
"name": "project pre-startup",
"isSubItem": true,
"duration": 33,
"start": 1550844310824,
"end": 1550844310857
"duration": 29,
"start": 11277,
"end": 11307
},
{
"name": "project startup",
"isSubItem": true,
"duration": 1,
"start": 1550844310857,
"end": 1550844310858
},
{
"name": "default project components creation",
"isSubItem": true,
"duration": 17,
"start": 1550844311117,
"end": 1550844311134
"duration": 0,
"start": 11307,
"end": 11307
},
{
"name": "default project components initialization",
"description": "component count: 24",
"isSubItem": true,
"duration": 17,
"start": 1550844311117,
"end": 1550844311134
"duration": 11,
"start": 11510,
"end": 11522
},
{
"name": "default project components registration",
"isSubItem": true,
"duration": 0,
"start": 1550844311117,
"end": 1550844311117
"start": 11510,
"end": 11511
},
{
"name": "default project components creation",
"duration": 11,
"start": 11511,
"end": 11522
},
{
"name": "unknown",
"duration": 1251,
"start": 1550844311117,
"end": 1550844312368
"duration": 1157,
"start": 11522,
"end": 12679
}
],
"components": [
{
"name": "com.intellij.openapi.components.impl.ServiceManagerImpl",
"duration": 35,
"start": 1550844300964,
"end": 1550844300999
"duration": 37,
"start": 3747,
"end": 3785
},
{
"name": "com.intellij.openapi.util.registry.RegistryState",
"duration": 95,
"start": 1550844301079,
"end": 1550844301174
"duration": 99,
"start": 3862,
"end": 3962
},
{
"name": "com.intellij.internal.statistic.updater.StatisticsJobsScheduler",
"duration": 16,
"start": 1550844301175,
"end": 1550844301191
"start": 3962,
"end": 3978
},
{
"name": "com.intellij.configurationStore.StoreAwareProjectManager",
"duration": 121,
"start": 1550844301191,
"end": 1550844301312
"duration": 122,
"start": 3978,
"end": 4101
},
{
"name": "com.intellij.openapi.vfs.PlatformVirtualFileManager",
"duration": 117,
"start": 1550844301191,
"end": 1550844301308
"duration": 118,
"start": 3978,
"end": 4097
},
{
"name": "com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl",
"duration": 99,
"start": 1550844301193,
"end": 1550844301292
"duration": 98,
"start": 3981,
"end": 4080
},
{
"name": "com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl",
"duration": 93,
"start": 1550844301193,
"end": 1550844301286
"start": 3981,
"end": 4074
},
{
"name": "com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl",
"duration": 543,
"start": 1550844301312,
"end": 1550844301855
"duration": 448,
"start": 4101,
"end": 4549
},
{
"name": "com.intellij.openapi.editor.impl.EditorFactoryImpl",
"duration": 308,
"start": 1550844301860,
"end": 1550844302168
"duration": 306,
"start": 4554,
"end": 4861
},
{
"name": "com.intellij.openapi.actionSystem.impl.ActionManagerImpl",
"duration": 294,
"start": 1550844301862,
"end": 1550844302156
"duration": 293,
"start": 4556,
"end": 4849
},
{
"name": "com.intellij.openapi.keymap.impl.KeymapManagerImpl",
"duration": 17,
"start": 1550844301862,
"end": 1550844301879
"duration": 15,
"start": 4556,
"end": 4571
},
{
"name": "com.intellij.history.integration.LocalHistoryImpl",
"duration": 15,
"start": 1550844302168,
"end": 1550844302183
"duration": 13,
"start": 4861,
"end": 4874
},
{
"name": "com.intellij.ide.ui.laf.LafManagerImpl",
"duration": 222,
"start": 1550844302196,
"end": 1550844302418
"duration": 220,
"start": 4885,
"end": 5105
},
{
"name": "com.intellij.util.net.ssl.CertificateManager",
"duration": 68,
"start": 1550844302446,
"end": 1550844302514
"duration": 72,
"start": 5131,
"end": 5204
},
{
"name": "com.intellij.openapi.util.registry.RegistryExtensionCollector",
"duration": 13,
"start": 1550844302523,
"end": 1550844302536
"start": 5210,
"end": 5223
},
{
"name": "com.intellij.openapi.wm.impl.FocusManagerImpl",
"duration": 19,
"start": 1550844302536,
"end": 1550844302555
"duration": 20,
"start": 5223,
"end": 5243
},
{
"name": "com.intellij.openapi.wm.impl.WindowManagerImpl",
"duration": 16,
"start": 1550844302537,
"end": 1550844302553
"duration": 15,
"start": 5225,
"end": 5241
},
{
"name": "com.intellij.ide.IdeTooltipManager",
"duration": 16,
"start": 1550844302555,
"end": 1550844302571
"start": 5243,
"end": 5260
},
{
"name": "com.intellij.ide.MacOSApplicationProvider",
"duration": 21,
"start": 1550844302583,
"end": 1550844302604
"start": 5271,
"end": 5292
},
{
"name": "com.intellij.openapi.updateSettings.impl.UpdateCheckerComponent",
"duration": 52,
"start": 1550844302604,
"end": 1550844302656
"duration": 50,
"start": 5292,
"end": 5343
},
{
"name": "com.intellij.util.indexing.FileBasedIndexImpl",
"duration": 617,
"start": 1550844302656,
"end": 1550844303273
"duration": 527,
"start": 5343,
"end": 5871
},
{
"name": "com.intellij.psi.stubs.SerializationManagerImpl",
"duration": 15,
"start": 1550844303272,
"end": 1550844303287
"duration": 11,
"start": 5871,
"end": 5883
},
{
"name": "com.intellij.psi.stubs.StubIndexImpl",
"duration": 139,
"start": 1550844303279,
"end": 1550844303418
"duration": 100,
"start": 5872,
"end": 5973
},
{
"name": "com.intellij.openapi.actionSystem.ex.QuickListsManager",
"duration": 20,
"start": 1550844303426,
"end": 1550844303446
"duration": 18,
"start": 5978,
"end": 5996
},
{
"name": "com.intellij.execution.ExecutorRegistryImpl",
"duration": 23,
"start": 1550844303457,
"end": 1550844303480
"duration": 22,
"start": 6006,
"end": 6029
},
{
"name": "com.intellij.util.xml.impl.JavaDomApplicationComponent",
"duration": 11,
"start": 6031,
"end": 6042
},
{
"name": "com.intellij.openapi.projectRoots.impl.DefaultJdkConfigurator",
"duration": 92,
"start": 1550844303493,
"end": 1550844303585
"duration": 84,
"start": 6044,
"end": 6129
},
{
"name": "org.intellij.lang.xpath.xslt.impl.XsltConfigImpl",
"duration": 11,
"start": 1550844303595,
"end": 1550844303606
},
{
"name": "com.intellij.stats.completion.CompletionTrackerInitializer",
"duration": 11,
"start": 1550844303612,
"end": 1550844303623
"duration": 10,
"start": 6138,
"end": 6149
},
{
"name": "com.intellij.stats.personalization.impl.ApplicationUserFactorStorage",
"duration": 13,
"start": 1550844303623,
"end": 1550844303636
"duration": 14,
"start": 6165,
"end": 6180
},
{
"name": "com.intellij.completion.FeatureManagerImpl",
"duration": 15,
"start": 1550844303636,
"end": 1550844303651
"duration": 13,
"start": 6180,
"end": 6193
},
{
"name": "com.jetbrains.cidr.lang.dfa.contextSensitive.OCSourceGliderComponent",
"duration": 154,
"start": 1550844303651,
"end": 1550844303805
"duration": 160,
"start": 6194,
"end": 6354
},
{
"name": "com.intellij.j2ee.appServerIntegrations.impl.ApplicationServersManagerImpl",
"duration": 14,
"start": 6354,
"end": 6369
},
{
"name": "org.jetbrains.android.AndroidPlugin",
"duration": 23,
"start": 1550844303819,
"end": 1550844303842
"start": 6376,
"end": 6400
},
{
"name": "org.jetbrains.plugins.ruby.gem.GemManager",
"duration": 12,
"start": 1550844303873,
"end": 1550844303885
"name": "com.jetbrains.python.testing.VFSTestFrameworkListener",
"duration": 15,
"start": 6425,
"end": 6440
},
{
"name": "com.intellij.openapi.vfs.encoding.EncodingProjectManagerImpl",
"duration": 21,
"start": 1550844305756,
"end": 1550844305777
"duration": 20,
"start": 8266,
"end": 8286
},
{
"name": "com.intellij.openapi.wm.impl.ToolWindowManagerImpl",
"duration": 19,
"start": 1550844305777,
"end": 1550844305796
"duration": 20,
"start": 8287,
"end": 8307
},
{
"name": "com.intellij.openapi.roots.impl.ProjectRootManagerComponent",
"duration": 13,
"start": 1550844305797,
"end": 1550844305810
"start": 8308,
"end": 8321
},
{
"name": "com.intellij.psi.impl.PsiManagerImpl",
"duration": 14,
"start": 1550844305810,
"end": 1550844305824
"duration": 13,
"start": 8321,
"end": 8335
},
{
"name": "com.intellij.psi.impl.PsiDocumentManagerImpl",
"duration": 16,
"start": 8336,
"end": 8353
},
{
"name": "com.intellij.openapi.module.impl.ModuleManagerComponent",
"duration": 42,
"start": 1550844305832,
"end": 1550844305874
"duration": 35,
"start": 8353,
"end": 8388
},
{
"name": "com.intellij.openapi.fileEditor.impl.PsiAwareFileEditorManagerImpl",
"duration": 21,
"start": 1550844305875,
"end": 1550844305896
"duration": 20,
"start": 8389,
"end": 8410
},
{
"name": "com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl",
"duration": 17,
"start": 1550844305904,
"end": 1550844305921
"duration": 16,
"start": 8418,
"end": 8434
},
{
"name": "com.intellij.codeInsight.daemon.impl.DaemonListeners",
"duration": 211,
"start": 1550844305921,
"end": 1550844306132
"duration": 202,
"start": 8434,
"end": 8637
},
{
"name": "com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl",
"duration": 21,
"start": 1550844305975,
"end": 1550844305996
"start": 8487,
"end": 8509
},
{
"name": "com.intellij.openapi.vcs.changes.VcsDirtyScopeManagerImpl",
"duration": 115,
"start": 1550844305996,
"end": 1550844306111
"duration": 109,
"start": 8509,
"end": 8618
},
{
"name": "com.intellij.openapi.vcs.changes.ChangeListManagerImpl",
"duration": 113,
"start": 1550844305997,
"end": 1550844306110
"duration": 107,
"start": 8509,
"end": 8617
},
{
"name": "com.intellij.openapi.vcs.changes.ChangesViewManager",
"duration": 68,
"start": 1550844306003,
"end": 1550844306071
"duration": 62,
"start": 8515,
"end": 8577
},
{
"name": "com.intellij.codeInsight.daemon.impl.GeneralHighlightingPassFactory",
"duration": 35,
"start": 1550844306132,
"end": 1550844306167
"duration": 32,
"start": 8637,
"end": 8669
},
{
"name": "com.intellij.codeInsight.navigation.CtrlMouseHandler",
"duration": 16,
"start": 1550844306171,
"end": 1550844306187
"duration": 13,
"start": 8673,
"end": 8687
},
{
"name": "com.intellij.openapi.roots.impl.PushedFilePropertiesUpdaterImpl",
"duration": 16,
"start": 1550844306187,
"end": 1550844306203
"duration": 13,
"start": 8687,
"end": 8701
},
{
"name": "com.intellij.packaging.impl.artifacts.ArtifactManagerImpl",
"duration": 10,
"start": 8717,
"end": 8727
},
{
"name": "com.intellij.compiler.CompilerConfigurationImpl",
"duration": 10,
"start": 8728,
"end": 8738
},
{
"name": "com.intellij.openapi.vcs.changes.shelf.ShelvedChangesViewManager",
"duration": 30,
"start": 1550844306259,
"end": 1550844306289
"duration": 27,
"start": 8754,
"end": 8781
},
{
"name": "com.intellij.xdebugger.impl.XDebuggerManagerImpl",
"duration": 89,
"start": 1550844306302,
"end": 1550844306391
"duration": 88,
"start": 8794,
"end": 8882
},
{
"name": "com.intellij.execution.scratch.JavaScratchCompilationSupport",
"duration": 37,
"start": 1550844306421,
"end": 1550844306458
"duration": 41,
"start": 8911,
"end": 8953
},
{
"name": "com.intellij.stats.personalization.impl.UserFactorsManagerImpl",
"duration": 18,
"start": 1550844306474,
"end": 1550844306492
"duration": 19,
"start": 8973,
"end": 8992
},
{
"name": "com.intellij.tasks.impl.TaskManagerImpl",
"duration": 48,
"start": 1550844306492,
"end": 1550844306540
"duration": 50,
"start": 8992,
"end": 9043
},
{
"name": "com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager",
"duration": 193,
"start": 1550844306540,
"end": 1550844306733
"duration": 212,
"start": 9043,
"end": 9256
},
{
"name": "com.intellij.ide.palette.impl.PaletteToolWindowManager",
"duration": 20,
"start": 1550844306733,
"end": 1550844306753
},
{
"name": "org.jetbrains.idea.maven.navigator.MavenProjectsNavigator",
"duration": 18,
"start": 1550844306764,
"end": 1550844306782
},
{
"name": "org.osmorc.OsmorcProjectComponent",
"duration": 19,
"start": 1550844306786,
"end": 1550844306805
"duration": 14,
"start": 9256,
"end": 9270
},
{
"name": "com.jetbrains.cidr.lang.symbols.symtable.FileSymbolTablesCache",
"duration": 14,
"start": 1550844306805,
"end": 1550844306819
"duration": 10,
"start": 9298,
"end": 9308
},
{
"name": "com.jetbrains.cidr.lang.hmap.OCHeaderMapManager",
"duration": 86,
"start": 1550844306821,
"end": 1550844306907
},
{
"name": "com.jetbrains.cidr.cpp.compdb.CompDBWorkspace",
"duration": 21,
"start": 1550844306913,
"end": 1550844306934
"duration": 45,
"start": 9309,
"end": 9354
},
{
"name": "com.intellij.jpa.JpaProjectComponent",
"duration": 67,
"start": 1550844306934,
"end": 1550844307001
},
{
"name": "com.intellij.psi.impl.source.jsp.JspContextManagerImpl",
"duration": 11,
"start": 1550844307010,
"end": 1550844307021
"duration": 31,
"start": 9362,
"end": 9394
},
{
"name": "com.android.tools.idea.gradle.project.AndroidGradleProjectComponent",
"duration": 75,
"start": 1550844307031,
"end": 1550844307106
"duration": 33,
"start": 9414,
"end": 9447
},
{
"name": "com.android.tools.idea.res.PsiProjectListener",
"duration": 62,
"start": 1550844307106,
"end": 1550844307168
},
{
"name": "org.jetbrains.plugins.terminal.TerminalView",
"duration": 15,
"start": 1550844307178,
"end": 1550844307193
},
{
"name": "com.intellij.lang.javascript.frameworks.webpack.Webpack4PluginProviderRegistrar",
"duration": 21,
"start": 1550844307199,
"end": 1550844307220
"duration": 12,
"start": 9447,
"end": 9459
},
{
"name": "com.intellij.openapi.roots.impl.ModuleRootManagerComponent",
"duration": 123,
"start": 1550844307294,
"end": 1550844307417
"duration": 75,
"start": 9530,
"end": 9605
},
{
"name": "com.intellij.facet.FacetManagerImpl",
"duration": 33,
"start": 1550844307417,
"end": 1550844307450
"duration": 18,
"start": 9605,
"end": 9624
}
],
"preloadActivities": [
{
"name": "com.intellij.ide.ui.OptionsTopHitProvider$Activity",
"duration": 1726,
"start": 1550844303962,
"end": 1550844305688
},
{
"name": "com.intellij.openapi.actionSystem.impl.ActionPreloader",
"duration": 6322,
"start": 1550844305688,
"end": 1550844312010
"duration": 1639,
"start": 6530,
"end": 8169
}
],
"totalDurationComputed": 7702,
"totalDurationActual": 12402
"totalDurationComputed": 9883,
"totalDurationActual": 12679
};
function main() {
const container = document.getElementById("visualization");
@@ -888,3 +878,49 @@ define("main", ["require", "exports", "@amcharts/amcharts4/core", "@amcharts/amc
return core_3.getInputElement("ijPort");
}
});
define("timeLineChartHelper.test", ["require", "exports", "timeLineChartHelper"], function (require, exports, timeLineChartHelper_2) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
test("adds 1 + 2 to equal 3", () => {
const items = [
{
"name": "default project components creation",
"duration": 13,
"start": 1550854187320,
"end": 1550854187333
},
{
"name": "default project components registration",
"isSubItem": true,
"duration": 0,
"start": 1550854187320,
"end": 1550854187320
},
{
"name": "default project components initialization",
"description": "component count: 24",
"isSubItem": true,
"duration": 13,
"start": 1550854187320,
"end": 1550854187333
},
];
timeLineChartHelper_2.computeLevels(items);
expect(items.map(it => {
return { name: it.name, level: it.level };
})).toMatchObject([
{
"name": "default project components creation",
"level": 0,
},
{
"name": "default project components registration",
"level": 1,
},
{
"name": "default project components initialization",
"level": 1,
},
]);
});
});
@@ -6,7 +6,9 @@
"@amcharts/amcharts4": "4.1.9"
},
"devDependencies": {
"@types/jest": "^24.0.6",
"@types/parcel-env": "^0.0.0",
"jest": "^24.1.0",
"parcel-bundler": "^1.11.0",
"typescript": "^3.3.3"
},
@@ -14,6 +16,7 @@
"compile": "tsc --outFile out/index.js --module amd",
"//": "chrome://flags/#allow-insecure-localhost to tell Chrome to ignore cert warnings on localhost",
"serve": "caddy -quic -host localhost -port 8080 \"ext .html\" \"log stdout\" \"tls self_signed\" \"bind 127.0.0.1\"",
"dev": "parcel dev.html"
"dev": "parcel dev.html",
"test": "parcel build src/timeLineChartHelper.test.ts --out-dir dist/test --no-minify && jest dist/test"
}
}
@@ -26,6 +26,7 @@ export class ComponentsChartManager extends XYChartManager {
nameAxisLabel.horizontalCenter = "right"
nameAxis.renderer.minGridDistance = 1
nameAxis.renderer.grid.template.location = 0
nameAxis.renderer.grid.template.disabled = true
}
private configureDurationAxis(): void {
@@ -1,7 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
import {InputData, Item, XYChartManager} from "./core"
import {InputData, XYChartManager} from "./core"
import * as am4charts from "@amcharts/amcharts4/charts"
import * as am4core from "@amcharts/amcharts4/core"
import {computeLevels, TimeLineItem} from "./timeLineChartHelper"
// https://github.com/almende/vis/blob/master/examples/timeline/dataHandling/dataSerialization.html
// do not group because it makes hard to understand results
@@ -30,6 +31,7 @@ export class TimelineChartManager extends XYChartManager {
levelAxis.renderer.grid.template.location = 0
levelAxis.renderer.minGridDistance = 1
levelAxis.renderer.labels.template.disabled = true
// levelAxis.renderer.grid.template.disabled = true
return levelAxis
}
@@ -72,6 +74,12 @@ export class TimelineChartManager extends XYChartManager {
// https://www.amcharts.com/docs/v4/tutorials/auto-adjusting-chart-height-based-on-a-number-of-data-items/
// noinspection SpellCheckingInspection
this.chart.events.on("datavalidated", () => {
const grid = this.chart.yAxes.getIndex(0)!!.renderer.grid
// hide all grid lines except first and last
for (let i = 1; i < (grid.length - 1); i++) {
grid.getIndex(i)!!.disabled = true
}
const chart = this.chart
const adjustHeight = chart.data.reduce((max, item) => Math.max(item.rowIndex, max), 0) * 35 - levelAxis.pixelHeight
@@ -86,7 +94,7 @@ export class TimelineChartManager extends XYChartManager {
render(ijData: InputData) {
const items = ijData.items
const firstStart = new Date(items[0].start)
const timeOffset = items[0].start
const timeOffset = 0
const data = transformIjData(ijData, timeOffset)
this.chart.data = data
@@ -97,22 +105,6 @@ export class TimelineChartManager extends XYChartManager {
}
}
function computeLevels(items: Array<Item>) {
for (let i = 0; i < items.length; i++) {
const item = items[i]
let level = 0
for (let j = i - 1; j >= 0; j--) {
const prevItem = items[j] as TimeLineItem
if (prevItem.end >= item.end) {
level = prevItem.level + 1
break
}
}
(item as TimeLineItem).level = level
}
}
function transformIjData(input: InputData, timeOffset: number): Array<any> {
const colorSet = new am4core.ColorSet()
const transformedItems = new Array<any>(input.items.length)
@@ -123,31 +115,24 @@ function transformIjData(input: InputData, timeOffset: number): Array<any> {
let rowIndex = 0
for (let i = 0; i < input.items.length; i++) {
const item = input.items[i] as TimeLineItem
if (rowIndex > 5 && item.level === 0) {
rowIndex = 0
}
const result: any = {
name: item.name,
start: item.start - timeOffset,
end: item.end - timeOffset,
duration: item.duration,
// level: item.isSubItem ? 2 : 1
// level: "l" + getLevel(i, input.items, transformedItems).toString(),
// level: getLevel(i, input.items, transformedItems),
// level: item.level,
rowIndex: rowIndex++,
color: colorSet.getIndex(item.level),
color: colorSet.getIndex(item.colorIndex),
level: item.level,
}
if (rowIndex > 6) {
rowIndex = 0
}
transformedItems[i] = result
}
transformedItems.sort((a, b) => a.rowIndex - b.rowIndex)
return transformedItems
}
interface TimeLineItem extends Item {
level: number
rowIndex: number
}
@@ -10,8 +10,6 @@ export interface Item {
end: number
duration: number
isSubItem?: boolean
}
export interface InputData {
@@ -5,550 +5,527 @@ import {TimelineChartManager} from "./TimeLineChartManager"
const data: InputData = {
"items": [
{
"name": "app initialization preparation",
"duration": 2744,
"start": 0,
"end": 2744
},
{
"name": "app initialization",
"duration": 307,
"start": 1550844299966,
"end": 1550844300273
"duration": 302,
"start": 2744,
"end": 3046
},
{
"name": "plugins initialization",
"description": "plugin count: 189",
"duration": 353,
"start": 1550844300280,
"end": 1550844300633
"duration": 369,
"start": 3053,
"end": 3423
},
{
"name": "plugin descriptors loading",
"isSubItem": true,
"duration": 265,
"start": 1550844300281,
"end": 1550844300546
"duration": 281,
"start": 3054,
"end": 3335
},
{
"name": "app components initialization",
"description": "component count: 101",
"duration": 3254,
"start": 1550844300634,
"end": 1550844303888
"duration": 3029,
"start": 3424,
"end": 6453
},
{
"name": "app components registration",
"isSubItem": true,
"duration": 330,
"start": 1550844300634,
"end": 1550844300964
"duration": 323,
"start": 3424,
"end": 3747
},
{
"name": "app components registered callback",
"isSubItem": true,
"duration": 111,
"start": 1550844300964,
"end": 1550844301075
"start": 3747,
"end": 3859
},
{
"name": "app components creation",
"isSubItem": true,
"duration": 2813,
"start": 1550844301075,
"end": 1550844303888
"duration": 2594,
"start": 3859,
"end": 6453
},
{
"name": "app initialized callback",
"duration": 242,
"start": 1550844303888,
"end": 1550844304130
"duration": 229,
"start": 6453,
"end": 6683
},
{
"name": "project components initialization",
"description": "component count: 210",
"duration": 2295,
"start": 1550844304955,
"end": 1550844307250
"duration": 2008,
"start": 7490,
"end": 9498
},
{
"name": "project components registration",
"isSubItem": true,
"duration": 782,
"start": 1550844304955,
"end": 1550844305737
"duration": 760,
"start": 7490,
"end": 8250
},
{
"name": "project components creation",
"isSubItem": true,
"duration": 1513,
"start": 1550844305737,
"end": 1550844307250
"duration": 1248,
"start": 8250,
"end": 9498
},
{
"name": "project pre-startup",
"isSubItem": true,
"duration": 33,
"start": 1550844310824,
"end": 1550844310857
"duration": 29,
"start": 11277,
"end": 11307
},
{
"name": "project startup",
"isSubItem": true,
"duration": 1,
"start": 1550844310857,
"end": 1550844310858
},
{
"name": "default project components creation",
"isSubItem": true,
"duration": 17,
"start": 1550844311117,
"end": 1550844311134
"duration": 0,
"start": 11307,
"end": 11307
},
{
"name": "default project components initialization",
"description": "component count: 24",
"isSubItem": true,
"duration": 17,
"start": 1550844311117,
"end": 1550844311134
"duration": 11,
"start": 11510,
"end": 11522
},
{
"name": "default project components registration",
"isSubItem": true,
"duration": 0,
"start": 1550844311117,
"end": 1550844311117
"start": 11510,
"end": 11511
},
{
"name": "default project components creation",
"duration": 11,
"start": 11511,
"end": 11522
},
{
"name": "unknown",
"duration": 1251,
"start": 1550844311117,
"end": 1550844312368
"duration": 1157,
"start": 11522,
"end": 12679
}
],
"components": [
{
"name": "com.intellij.openapi.components.impl.ServiceManagerImpl",
"duration": 35,
"start": 1550844300964,
"end": 1550844300999
"duration": 37,
"start": 3747,
"end": 3785
},
{
"name": "com.intellij.openapi.util.registry.RegistryState",
"duration": 95,
"start": 1550844301079,
"end": 1550844301174
"duration": 99,
"start": 3862,
"end": 3962
},
{
"name": "com.intellij.internal.statistic.updater.StatisticsJobsScheduler",
"duration": 16,
"start": 1550844301175,
"end": 1550844301191
"start": 3962,
"end": 3978
},
{
"name": "com.intellij.configurationStore.StoreAwareProjectManager",
"duration": 121,
"start": 1550844301191,
"end": 1550844301312
"duration": 122,
"start": 3978,
"end": 4101
},
{
"name": "com.intellij.openapi.vfs.PlatformVirtualFileManager",
"duration": 117,
"start": 1550844301191,
"end": 1550844301308
"duration": 118,
"start": 3978,
"end": 4097
},
{
"name": "com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl",
"duration": 99,
"start": 1550844301193,
"end": 1550844301292
"duration": 98,
"start": 3981,
"end": 4080
},
{
"name": "com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl",
"duration": 93,
"start": 1550844301193,
"end": 1550844301286
"start": 3981,
"end": 4074
},
{
"name": "com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl",
"duration": 543,
"start": 1550844301312,
"end": 1550844301855
"duration": 448,
"start": 4101,
"end": 4549
},
{
"name": "com.intellij.openapi.editor.impl.EditorFactoryImpl",
"duration": 308,
"start": 1550844301860,
"end": 1550844302168
"duration": 306,
"start": 4554,
"end": 4861
},
{
"name": "com.intellij.openapi.actionSystem.impl.ActionManagerImpl",
"duration": 294,
"start": 1550844301862,
"end": 1550844302156
"duration": 293,
"start": 4556,
"end": 4849
},
{
"name": "com.intellij.openapi.keymap.impl.KeymapManagerImpl",
"duration": 17,
"start": 1550844301862,
"end": 1550844301879
"duration": 15,
"start": 4556,
"end": 4571
},
{
"name": "com.intellij.history.integration.LocalHistoryImpl",
"duration": 15,
"start": 1550844302168,
"end": 1550844302183
"duration": 13,
"start": 4861,
"end": 4874
},
{
"name": "com.intellij.ide.ui.laf.LafManagerImpl",
"duration": 222,
"start": 1550844302196,
"end": 1550844302418
"duration": 220,
"start": 4885,
"end": 5105
},
{
"name": "com.intellij.util.net.ssl.CertificateManager",
"duration": 68,
"start": 1550844302446,
"end": 1550844302514
"duration": 72,
"start": 5131,
"end": 5204
},
{
"name": "com.intellij.openapi.util.registry.RegistryExtensionCollector",
"duration": 13,
"start": 1550844302523,
"end": 1550844302536
"start": 5210,
"end": 5223
},
{
"name": "com.intellij.openapi.wm.impl.FocusManagerImpl",
"duration": 19,
"start": 1550844302536,
"end": 1550844302555
"duration": 20,
"start": 5223,
"end": 5243
},
{
"name": "com.intellij.openapi.wm.impl.WindowManagerImpl",
"duration": 16,
"start": 1550844302537,
"end": 1550844302553
"duration": 15,
"start": 5225,
"end": 5241
},
{
"name": "com.intellij.ide.IdeTooltipManager",
"duration": 16,
"start": 1550844302555,
"end": 1550844302571
"start": 5243,
"end": 5260
},
{
"name": "com.intellij.ide.MacOSApplicationProvider",
"duration": 21,
"start": 1550844302583,
"end": 1550844302604
"start": 5271,
"end": 5292
},
{
"name": "com.intellij.openapi.updateSettings.impl.UpdateCheckerComponent",
"duration": 52,
"start": 1550844302604,
"end": 1550844302656
"duration": 50,
"start": 5292,
"end": 5343
},
{
"name": "com.intellij.util.indexing.FileBasedIndexImpl",
"duration": 617,
"start": 1550844302656,
"end": 1550844303273
"duration": 527,
"start": 5343,
"end": 5871
},
{
"name": "com.intellij.psi.stubs.SerializationManagerImpl",
"duration": 15,
"start": 1550844303272,
"end": 1550844303287
"duration": 11,
"start": 5871,
"end": 5883
},
{
"name": "com.intellij.psi.stubs.StubIndexImpl",
"duration": 139,
"start": 1550844303279,
"end": 1550844303418
"duration": 100,
"start": 5872,
"end": 5973
},
{
"name": "com.intellij.openapi.actionSystem.ex.QuickListsManager",
"duration": 20,
"start": 1550844303426,
"end": 1550844303446
"duration": 18,
"start": 5978,
"end": 5996
},
{
"name": "com.intellij.execution.ExecutorRegistryImpl",
"duration": 23,
"start": 1550844303457,
"end": 1550844303480
"duration": 22,
"start": 6006,
"end": 6029
},
{
"name": "com.intellij.util.xml.impl.JavaDomApplicationComponent",
"duration": 11,
"start": 6031,
"end": 6042
},
{
"name": "com.intellij.openapi.projectRoots.impl.DefaultJdkConfigurator",
"duration": 92,
"start": 1550844303493,
"end": 1550844303585
"duration": 84,
"start": 6044,
"end": 6129
},
{
"name": "org.intellij.lang.xpath.xslt.impl.XsltConfigImpl",
"duration": 11,
"start": 1550844303595,
"end": 1550844303606
},
{
"name": "com.intellij.stats.completion.CompletionTrackerInitializer",
"duration": 11,
"start": 1550844303612,
"end": 1550844303623
"duration": 10,
"start": 6138,
"end": 6149
},
{
"name": "com.intellij.stats.personalization.impl.ApplicationUserFactorStorage",
"duration": 13,
"start": 1550844303623,
"end": 1550844303636
"duration": 14,
"start": 6165,
"end": 6180
},
{
"name": "com.intellij.completion.FeatureManagerImpl",
"duration": 15,
"start": 1550844303636,
"end": 1550844303651
"duration": 13,
"start": 6180,
"end": 6193
},
{
"name": "com.jetbrains.cidr.lang.dfa.contextSensitive.OCSourceGliderComponent",
"duration": 154,
"start": 1550844303651,
"end": 1550844303805
"duration": 160,
"start": 6194,
"end": 6354
},
{
"name": "com.intellij.j2ee.appServerIntegrations.impl.ApplicationServersManagerImpl",
"duration": 14,
"start": 6354,
"end": 6369
},
{
"name": "org.jetbrains.android.AndroidPlugin",
"duration": 23,
"start": 1550844303819,
"end": 1550844303842
"start": 6376,
"end": 6400
},
{
"name": "org.jetbrains.plugins.ruby.gem.GemManager",
"duration": 12,
"start": 1550844303873,
"end": 1550844303885
"name": "com.jetbrains.python.testing.VFSTestFrameworkListener",
"duration": 15,
"start": 6425,
"end": 6440
},
{
"name": "com.intellij.openapi.vfs.encoding.EncodingProjectManagerImpl",
"duration": 21,
"start": 1550844305756,
"end": 1550844305777
"duration": 20,
"start": 8266,
"end": 8286
},
{
"name": "com.intellij.openapi.wm.impl.ToolWindowManagerImpl",
"duration": 19,
"start": 1550844305777,
"end": 1550844305796
"duration": 20,
"start": 8287,
"end": 8307
},
{
"name": "com.intellij.openapi.roots.impl.ProjectRootManagerComponent",
"duration": 13,
"start": 1550844305797,
"end": 1550844305810
"start": 8308,
"end": 8321
},
{
"name": "com.intellij.psi.impl.PsiManagerImpl",
"duration": 14,
"start": 1550844305810,
"end": 1550844305824
"duration": 13,
"start": 8321,
"end": 8335
},
{
"name": "com.intellij.psi.impl.PsiDocumentManagerImpl",
"duration": 16,
"start": 8336,
"end": 8353
},
{
"name": "com.intellij.openapi.module.impl.ModuleManagerComponent",
"duration": 42,
"start": 1550844305832,
"end": 1550844305874
"duration": 35,
"start": 8353,
"end": 8388
},
{
"name": "com.intellij.openapi.fileEditor.impl.PsiAwareFileEditorManagerImpl",
"duration": 21,
"start": 1550844305875,
"end": 1550844305896
"duration": 20,
"start": 8389,
"end": 8410
},
{
"name": "com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl",
"duration": 17,
"start": 1550844305904,
"end": 1550844305921
"duration": 16,
"start": 8418,
"end": 8434
},
{
"name": "com.intellij.codeInsight.daemon.impl.DaemonListeners",
"duration": 211,
"start": 1550844305921,
"end": 1550844306132
"duration": 202,
"start": 8434,
"end": 8637
},
{
"name": "com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl",
"duration": 21,
"start": 1550844305975,
"end": 1550844305996
"start": 8487,
"end": 8509
},
{
"name": "com.intellij.openapi.vcs.changes.VcsDirtyScopeManagerImpl",
"duration": 115,
"start": 1550844305996,
"end": 1550844306111
"duration": 109,
"start": 8509,
"end": 8618
},
{
"name": "com.intellij.openapi.vcs.changes.ChangeListManagerImpl",
"duration": 113,
"start": 1550844305997,
"end": 1550844306110
"duration": 107,
"start": 8509,
"end": 8617
},
{
"name": "com.intellij.openapi.vcs.changes.ChangesViewManager",
"duration": 68,
"start": 1550844306003,
"end": 1550844306071
"duration": 62,
"start": 8515,
"end": 8577
},
{
"name": "com.intellij.codeInsight.daemon.impl.GeneralHighlightingPassFactory",
"duration": 35,
"start": 1550844306132,
"end": 1550844306167
"duration": 32,
"start": 8637,
"end": 8669
},
{
"name": "com.intellij.codeInsight.navigation.CtrlMouseHandler",
"duration": 16,
"start": 1550844306171,
"end": 1550844306187
"duration": 13,
"start": 8673,
"end": 8687
},
{
"name": "com.intellij.openapi.roots.impl.PushedFilePropertiesUpdaterImpl",
"duration": 16,
"start": 1550844306187,
"end": 1550844306203
"duration": 13,
"start": 8687,
"end": 8701
},
{
"name": "com.intellij.packaging.impl.artifacts.ArtifactManagerImpl",
"duration": 10,
"start": 8717,
"end": 8727
},
{
"name": "com.intellij.compiler.CompilerConfigurationImpl",
"duration": 10,
"start": 8728,
"end": 8738
},
{
"name": "com.intellij.openapi.vcs.changes.shelf.ShelvedChangesViewManager",
"duration": 30,
"start": 1550844306259,
"end": 1550844306289
"duration": 27,
"start": 8754,
"end": 8781
},
{
"name": "com.intellij.xdebugger.impl.XDebuggerManagerImpl",
"duration": 89,
"start": 1550844306302,
"end": 1550844306391
"duration": 88,
"start": 8794,
"end": 8882
},
{
"name": "com.intellij.execution.scratch.JavaScratchCompilationSupport",
"duration": 37,
"start": 1550844306421,
"end": 1550844306458
"duration": 41,
"start": 8911,
"end": 8953
},
{
"name": "com.intellij.stats.personalization.impl.UserFactorsManagerImpl",
"duration": 18,
"start": 1550844306474,
"end": 1550844306492
"duration": 19,
"start": 8973,
"end": 8992
},
{
"name": "com.intellij.tasks.impl.TaskManagerImpl",
"duration": 48,
"start": 1550844306492,
"end": 1550844306540
"duration": 50,
"start": 8992,
"end": 9043
},
{
"name": "com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager",
"duration": 193,
"start": 1550844306540,
"end": 1550844306733
"duration": 212,
"start": 9043,
"end": 9256
},
{
"name": "com.intellij.ide.palette.impl.PaletteToolWindowManager",
"duration": 20,
"start": 1550844306733,
"end": 1550844306753
},
{
"name": "org.jetbrains.idea.maven.navigator.MavenProjectsNavigator",
"duration": 18,
"start": 1550844306764,
"end": 1550844306782
},
{
"name": "org.osmorc.OsmorcProjectComponent",
"duration": 19,
"start": 1550844306786,
"end": 1550844306805
"duration": 14,
"start": 9256,
"end": 9270
},
{
"name": "com.jetbrains.cidr.lang.symbols.symtable.FileSymbolTablesCache",
"duration": 14,
"start": 1550844306805,
"end": 1550844306819
"duration": 10,
"start": 9298,
"end": 9308
},
{
"name": "com.jetbrains.cidr.lang.hmap.OCHeaderMapManager",
"duration": 86,
"start": 1550844306821,
"end": 1550844306907
},
{
"name": "com.jetbrains.cidr.cpp.compdb.CompDBWorkspace",
"duration": 21,
"start": 1550844306913,
"end": 1550844306934
"duration": 45,
"start": 9309,
"end": 9354
},
{
"name": "com.intellij.jpa.JpaProjectComponent",
"duration": 67,
"start": 1550844306934,
"end": 1550844307001
},
{
"name": "com.intellij.psi.impl.source.jsp.JspContextManagerImpl",
"duration": 11,
"start": 1550844307010,
"end": 1550844307021
"duration": 31,
"start": 9362,
"end": 9394
},
{
"name": "com.android.tools.idea.gradle.project.AndroidGradleProjectComponent",
"duration": 75,
"start": 1550844307031,
"end": 1550844307106
"duration": 33,
"start": 9414,
"end": 9447
},
{
"name": "com.android.tools.idea.res.PsiProjectListener",
"duration": 62,
"start": 1550844307106,
"end": 1550844307168
},
{
"name": "org.jetbrains.plugins.terminal.TerminalView",
"duration": 15,
"start": 1550844307178,
"end": 1550844307193
},
{
"name": "com.intellij.lang.javascript.frameworks.webpack.Webpack4PluginProviderRegistrar",
"duration": 21,
"start": 1550844307199,
"end": 1550844307220
"duration": 12,
"start": 9447,
"end": 9459
},
{
"name": "com.intellij.openapi.roots.impl.ModuleRootManagerComponent",
"duration": 123,
"start": 1550844307294,
"end": 1550844307417
"duration": 75,
"start": 9530,
"end": 9605
},
{
"name": "com.intellij.facet.FacetManagerImpl",
"duration": 33,
"start": 1550844307417,
"end": 1550844307450
"duration": 18,
"start": 9605,
"end": 9624
}
],
"preloadActivities": [
{
"name": "com.intellij.ide.ui.OptionsTopHitProvider$Activity",
"duration": 1726,
"start": 1550844303962,
"end": 1550844305688
},
{
"name": "com.intellij.openapi.actionSystem.impl.ActionPreloader",
"duration": 6322,
"start": 1550844305688,
"end": 1550844312010
"duration": 1639,
"start": 6530,
"end": 8169
}
],
"totalDurationComputed": 7702,
"totalDurationActual": 12402
"totalDurationComputed": 9883,
"totalDurationActual": 12679
}
function main() {
@@ -0,0 +1,45 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
import {computeLevels, TimeLineItem} from "./timeLineChartHelper"
test("sort", () => {
const items = [
{
"name": "default project components creation",
"duration": 13,
"start": 1550854187320,
"end": 1550854187333
},
{
"name": "default project components registration",
"isSubItem": true,
"duration": 0,
"start": 1550854187320,
"end": 1550854187320
},
{
"name": "default project components initialization",
"description": "component count: 24",
"isSubItem": true,
"duration": 13,
"start": 1550854187320,
"end": 1550854187333
},
]
computeLevels(items)
expect(items.map(it => {
return {name: it.name, level: (it as TimeLineItem).level}
})).toMatchObject([
{
"name": "default project components creation",
"level": 0,
},
{
"name": "default project components registration",
"level": 1,
},
{
"name": "default project components initialization",
"level": 1,
},
])
})
@@ -0,0 +1,30 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
import {Item} from "./core"
export interface TimeLineItem extends Item {
level: number
rowIndex: number
colorIndex: number
}
export function computeLevels(items: Array<Item>) {
let lastAllocatedColorIndex = 0
for (let i = 0; i < items.length; i++) {
const item = items[i] as TimeLineItem
let level = 0
for (let j = i - 1; j >= 0; j--) {
const prevItem = items[j] as TimeLineItem
if (prevItem.end >= item.end) {
level = prevItem.level + 1
item.colorIndex = prevItem.colorIndex
break
}
}
if (item.colorIndex === undefined) {
item.colorIndex = lastAllocatedColorIndex++
}
item.level = level
}
}
File diff suppressed because it is too large Load Diff
@@ -43,9 +43,11 @@ import org.picocontainer.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public abstract class ComponentManagerImpl extends UserDataHolderBase implements ComponentManagerEx, Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.components.ComponentManager");
public static final long COMPONENT_MEASURE_THRESHOLD = TimeUnit.MILLISECONDS.toNanos(10);
private volatile MutablePicoContainer myPicoContainer;
private volatile boolean myDisposed;
@@ -110,14 +112,14 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
myComponentConfigCount = componentConfigCount;
if (componentsRegistered != null) {
measureToken = isNeededToMeasure ? StartUpMeasurer.start(measureTokenNamePrefix + StartUpMeasurer.Phases.COMPONENTS_REGISTERED_CALLBACK_SUFFIX) : null;
measureToken = isNeededToMeasure ? totalMeasureToken.startChild(measureTokenNamePrefix + StartUpMeasurer.Phases.COMPONENTS_REGISTERED_CALLBACK_SUFFIX) : null;
componentsRegistered.run();
if (measureToken != null) {
measureToken.end();
}
}
measureToken = isNeededToMeasure ? StartUpMeasurer.start(measureTokenNamePrefix + StartUpMeasurer.Phases.CREATE_COMPONENTS_SUFFIX) : null;
measureToken = isNeededToMeasure ? totalMeasureToken.startChild(measureTokenNamePrefix + StartUpMeasurer.Phases.CREATE_COMPONENTS_SUFFIX) : null;
createComponents(indicator);
if (measureToken != null) {
measureToken.end();
@@ -465,7 +467,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
return instance;
}
long startTime = System.currentTimeMillis();
long startTime = System.nanoTime();
instance = super.getComponentInstance(picoContainer);
@@ -494,8 +496,8 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
((BaseComponent)instance).initComponent();
}
long endTime = System.currentTimeMillis();
if ((endTime - startTime) > 10 && (LOG.isDebugEnabled() || ApplicationInfoImpl.getShadowInstance().isEAP())) {
long endTime = System.nanoTime();
if ((endTime - startTime) > COMPONENT_MEASURE_THRESHOLD && (LOG.isDebugEnabled() || ApplicationInfoImpl.getShadowInstance().isEAP())) {
StartUpMeasurer.reportComponentInitialized(instance.getClass(), startTime, endTime);
}
}
@@ -8,11 +8,14 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;
public final class StartUpMeasurer {
// use constants for better overview of existing phases (and preserve consistent naming)
// `what + noun` is used as scheme for name to make analyzing easier (to visually group - `components loading/initialization/etc`, not to put common part of name to end of)
public static final class Phases {
// this phase name is not fully clear - it is time from `PluginManager.start` to `IdeaApplication.initApplication`
public static final String PREPARE_TO_INIT_APP = "app initialization preparation";
// this phase name is not fully clear - it is time from `IdeaApplication.initApplication` to `IdeaApplication.run`
public static final String INIT_APP = "app initialization";
@@ -35,7 +38,7 @@ public final class StartUpMeasurer {
public static final String COMPONENT_INITIALIZED_INTERNAL_NAME = "_component initialized";
public static final String PRELOAD_ACTIVITY_FINISHED = "_preload activity finished";
private static final long startTime = System.currentTimeMillis();
private static final long startTime = System.nanoTime();
private static final ConcurrentLinkedQueue<Item> items = new ConcurrentLinkedQueue<>();
@@ -54,11 +57,11 @@ public final class StartUpMeasurer {
}
public static void reportComponentInitialized(@NotNull Class<?> componentClass, long startTime, long endTime) {
new Item(COMPONENT_INITIALIZED_INTERNAL_NAME, componentClass.getName(), startTime).end(endTime);
new Item(COMPONENT_INITIALIZED_INTERNAL_NAME, componentClass.getName(), startTime, null).end(endTime);
}
@NotNull
public static List<Item> getAndClear() {
public static List<Item> processAndClear(@NotNull Consumer<Item> consumer) {
ArrayList<Item> list = new ArrayList<>();
while (true) {
Item item = items.poll();
@@ -66,7 +69,7 @@ public final class StartUpMeasurer {
break;
}
list.add(item);
consumer.accept(item);
}
return list;
}
@@ -78,14 +81,31 @@ public final class StartUpMeasurer {
private final long start;
private long end;
// null doesn't mean root - not obligated to set parent, only as hint
private final Item parent;
private Item(@Nullable String name, @Nullable String description) {
this(name, description, System.currentTimeMillis());
this(name, description, System.nanoTime(), null);
}
private Item(@Nullable String name, @Nullable String description, long start) {
private Item(@Nullable String name, @Nullable String description, long start, @Nullable Item parent) {
this.name = name;
this.description = StringUtil.nullize(description);
this.start = start;
this.parent = parent;
}
@Nullable
public Item getParent() {
return parent;
}
// and how do we can sort correctly, when parent item equals to child (start and end) and also there is another child with start equals to end?
// so, parent added to API but as it was not enough, decided to measure time in nanoseconds instead of ms to mitigate such situations
@Override
@NotNull
public Item startChild(@NotNull String name) {
return new Item(name, null, System.nanoTime(), this);
}
@NotNull
@@ -111,7 +131,7 @@ public final class StartUpMeasurer {
if (description != null) {
this.description = description;
}
end = System.currentTimeMillis();
end = System.nanoTime();
items.add(this);
}
@@ -124,11 +144,19 @@ public final class StartUpMeasurer {
public void close() {
end();
}
@Override
public String toString() {
return name;
}
}
public interface MeasureToken extends AutoCloseable {
void end(@Nullable String description);
@NotNull
Item startChild(@NotNull String name);
default void end() {
end(null);
}
@@ -8,9 +8,12 @@ import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupActivity
import com.intellij.util.StartUpMeasurer
import com.intellij.util.StartUpMeasurer.Item
import gnu.trove.THashMap
import java.io.StringWriter
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import java.util.function.Consumer
class StartUpPerformanceReporter : StartupActivity, DumbAware {
private val activationCount = AtomicInteger()
@@ -18,8 +21,34 @@ class StartUpPerformanceReporter : StartupActivity, DumbAware {
var lastReport: String? = null
private set
companion object {
// need to be exposed for tests, but I don't want to expose as top-level function, so, as companion object
fun sortItems(items: MutableList<Item>) {
items.sortWith(Comparator { o1, o2 ->
if (o1 == o2.parent) {
return@Comparator -1
}
else if (o2 == o1.parent) {
return@Comparator 1
}
when {
o1.start > o2.start -> 1
o1.start < o2.start -> -1
else -> {
when {
o1.end > o2.end -> -1
o1.end < o2.end -> 1
else -> 0
}
}
}
})
}
}
override fun runActivity(project: Project) {
val end = System.currentTimeMillis()
val end = System.nanoTime()
val activationNumber = activationCount.incrementAndGet()
// even if this activity executed in a pooled thread, better if it will not affect start-up in any way,
ApplicationManager.getApplication().executeOnPooledThread {
@@ -30,40 +59,24 @@ class StartUpPerformanceReporter : StartupActivity, DumbAware {
private fun logStats(end: Long, activationNumber: Int) {
val log = Logger.getInstance(StartUpMeasurer::class.java)
val items: MutableList<StartUpMeasurer.Item> = StartUpMeasurer.getAndClear()
val activityDescriptors = listOf(ActivityDescriptor(StartUpMeasurer.COMPONENT_INITIALIZED_INTERNAL_NAME, "components"),
ActivityDescriptor(StartUpMeasurer.PRELOAD_ACTIVITY_FINISHED, "preloadActivities"))
val items = mutableListOf<Item>()
val activities = THashMap<String, MutableList<Item>>()
StartUpMeasurer.processAndClear(Consumer { item ->
if (activityDescriptors.any { it.itemName === item.name }) {
activities.getOrPut(item.name) { mutableListOf() }.add(item)
}
else {
items.add(item)
}
})
if (items.isEmpty() || (ApplicationManager.getApplication().isUnitTestMode && activationNumber > 2)) {
return
}
// project components initialization must be first
// {
// "name": "project components registration",
// "duration": 398,
// "start": 1550307664977,
// "end": 1550307665375
// },
// {
// "name": "project components initialization",
// "description": "component count: 212",
// "duration": 1302,
// "start": 1550307664977,
// "end": 1550307666279
// },
// {
// "name": "project components creation",
// "isSubItem": true,
// "duration": 904,
// "start": 1550307665375,
// "end": 1550307666279
// },
items.sortWith(Comparator { o1, o2 ->
val diff = (o1.start - o2.start).toInt()
if (diff != 0) {
return@Comparator diff
}
(o2.end - o1.end).toInt()
})
sortItems(items)
val stringWriter = StringWriter()
val logPrefix = "=== Start: StartUp Measurement ===\n"
@@ -72,18 +85,14 @@ class StartUpPerformanceReporter : StartupActivity, DumbAware {
writer.setIndent(" ")
writer.beginObject()
writer.name("version").value("1")
val startTime = if (activationNumber == 0) StartUpMeasurer.getStartTime() else items.first().start
writer.name("items")
writer.beginArray()
var totalDuration = if (activationNumber == 0) writeUnknown(writer, StartUpMeasurer.getStartTime(), items.get(0).start) else 0
val activities = THashMap<String, MutableList<StartUpMeasurer.Item>>()
val activityDescriptors = listOf(ActivityDescriptor(StartUpMeasurer.COMPONENT_INITIALIZED_INTERNAL_NAME, "components"),
ActivityDescriptor(StartUpMeasurer.PRELOAD_ACTIVITY_FINISHED, "preloadActivities"))
var totalDuration = if (activationNumber == 0) writeUnknown(writer, startTime, items.first().start, startTime) else 0
for ((index, item) in items.withIndex()) {
if (activityDescriptors.any { it.itemName === item.name }) {
activities.getOrPut(item.name) { mutableListOf() }.add(item)
continue
}
writer.beginObject()
writer.name("name").value(item.name)
if (item.description != null) {
@@ -91,28 +100,24 @@ class StartUpPerformanceReporter : StartupActivity, DumbAware {
}
val duration = item.end - item.start
if (isSubItem(item, index, items)) {
// for debug purposes (check that isSubItem computed correctly)
writer.name("isSubItem").value(true)
}
else {
if (!isSubItem(item, index, items)) {
totalDuration += duration
}
writeItemTimeInfo(item, duration, writer)
writeItemTimeInfo(item, duration, startTime, writer)
writer.endObject()
}
totalDuration += writeUnknown(writer, items.last().end, end)
totalDuration += writeUnknown(writer, items.last().end, end, startTime)
writer.endArray()
for (activityDescriptor in activityDescriptors) {
val list = activities.get(activityDescriptor.itemName) ?: continue
writeActivities(list, writer, activityDescriptor.jsonFieldName)
sortItems(list)
writeActivities(list, startTime, writer, activityDescriptor.jsonFieldName)
}
writer.name("totalDurationComputed").value(totalDuration)
writer.name("totalDurationActual").value(end - items.first().start)
writer.name("totalDurationComputed").value(TimeUnit.NANOSECONDS.toMillis(totalDuration))
writer.name("totalDurationActual").value(TimeUnit.NANOSECONDS.toMillis(end - startTime))
writer.endObject()
writer.flush()
@@ -126,7 +131,7 @@ class StartUpPerformanceReporter : StartupActivity, DumbAware {
log.info(string)
}
private fun writeActivities(slowComponents: List<StartUpMeasurer.Item>, writer: JsonWriter, fieldName: String) {
private fun writeActivities(slowComponents: List<Item>, offset: Long, writer: JsonWriter, fieldName: String) {
if (slowComponents.isEmpty()) {
return
}
@@ -138,20 +143,24 @@ class StartUpPerformanceReporter : StartupActivity, DumbAware {
for (item in slowComponents) {
writer.beginObject()
writer.name("name").value(item.description)
writeItemTimeInfo(item, item.end - item.start, writer)
writeItemTimeInfo(item, item.end - item.start, offset, writer)
writer.endObject()
}
writer.endArray()
}
private fun writeItemTimeInfo(item: StartUpMeasurer.Item, duration: Long, writer: JsonWriter) {
writer.name("duration").value(duration)
writer.name("start").value(item.start)
writer.name("end").value(item.end)
private fun writeItemTimeInfo(item: Item, duration: Long, offset: Long, writer: JsonWriter) {
writer.name("duration").value(TimeUnit.NANOSECONDS.toMillis(duration))
writer.name("start").value(TimeUnit.NANOSECONDS.toMillis(item.start - offset))
writer.name("end").value(TimeUnit.NANOSECONDS.toMillis(item.end - offset))
}
private fun isSubItem(item: StartUpMeasurer.Item, itemIndex: Int, list: List<StartUpMeasurer.Item>): Boolean {
private fun isSubItem(item: Item, itemIndex: Int, list: List<Item>): Boolean {
if (item.parent != null) {
return true
}
var index = itemIndex
while (true) {
val prevItem = list.getOrNull(--index) ?: return false
@@ -162,17 +171,18 @@ class StartUpPerformanceReporter : StartupActivity, DumbAware {
}
}
private fun writeUnknown(writer: JsonWriter, start: Long, end: Long): Long {
private fun writeUnknown(writer: JsonWriter, start: Long, end: Long, offset: Long): Long {
val duration = end - start
if (duration <= 1) {
val durationInMs = TimeUnit.NANOSECONDS.toMillis(duration)
if (durationInMs <= 1) {
return 0
}
writer.beginObject()
writer.name("name").value("unknown")
writer.name("duration").value(duration)
writer.name("start").value(start)
writer.name("end").value(end)
writer.name("duration").value(durationInMs)
writer.name("start").value(TimeUnit.NANOSECONDS.toMillis(start - offset))
writer.name("end").value(TimeUnit.NANOSECONDS.toMillis(end - offset))
writer.endObject()
return duration
}
@@ -1,4 +1,4 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.plugins;
import com.intellij.diagnostic.IdeErrorsDialog;
@@ -27,6 +27,7 @@ import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.StartUpMeasurer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,14 +47,15 @@ import java.util.stream.Collectors;
public class PluginManager extends PluginManagerCore {
public static final String INSTALLED_TXT = "installed.txt";
@SuppressWarnings("StaticNonFinalField") public static long startupStart;
@SuppressWarnings("StaticNonFinalField")
public static StartUpMeasurer.MeasureToken startupStart;
/**
* Called via reflection
*/
@SuppressWarnings({"UnusedDeclaration", "HardCodedStringLiteral"})
protected static void start(final String mainClass, final String methodName, final String[] args) {
startupStart = System.nanoTime();
startupStart = StartUpMeasurer.start(StartUpMeasurer.Phases.PREPARE_TO_INIT_APP);
Main.setFlags(args);
@@ -68,6 +68,7 @@ public class IdeaApplication {
@SuppressWarnings("SSBasedInspection")
public static void initApplication(String[] args) {
PluginManager.startupStart.end();
StartUpMeasurer.MeasureToken measureToken = StartUpMeasurer.start(StartUpMeasurer.Phases.INIT_APP);
IdeaApplication app = new IdeaApplication(args);
// this invokeLater() call is needed to place the app starting code on a freshly minted IdeEventQueue instance
@@ -346,7 +347,6 @@ public class IdeaApplication {
AppLifecycleListener lifecyclePublisher = app.getMessageBus().syncPublisher(AppLifecycleListener.TOPIC);
lifecyclePublisher.appFrameCreated(args, willOpenProject);
LOG.info("App initialization took " + (System.nanoTime() - PluginManager.startupStart) / 1000000 + " ms");
PluginManagerCore.dumpPluginClassStatistics();
// Temporary check until the jre implementation has been checked and bundled
@@ -379,7 +379,6 @@ public class IdeaApplication {
LifecycleUsageTriggerCollector.onIdeStart();
});
}
}
/**