From 6667a65141692bc359087d8f1c9c8561636f1c59 Mon Sep 17 00:00:00 2001 From: jsimomaa Date: Fri, 30 Nov 2018 14:04:34 +0200 Subject: [PATCH] Speeding up platform startup time Shaved ~1.5seconds off by starting SCL compiler priming at the beginning of platform startup on the background before the LifeCycleProcesses project feature needs the compiler. Also removed seemingly unused VirtualGraphInitializer that installed virtualgraphs/*.tg files into random memory-persistent virtual graphs during platform startup. It simply piles on some startup overhead and does nothing. gitlab #221 Change-Id: I1ebbc4e292957755cd88f2941cd02730ae8605c8 --- bundles/org.simantics.db.layer0/plugin.xml | 4 - .../service/impl/VirtualGraphInitializer.java | 86 ------------------- .../META-INF/MANIFEST.MF | 3 +- .../services/AdaptionServiceInitializer.java | 6 ++ .../db/services/GlobalServiceInitializer.java | 7 +- .../org/simantics/project/impl/Project.java | 5 ++ .../scl/osgi/internal/Activator.java | 14 +++ .../src/org/simantics/SimanticsPlatform.java | 72 ++++++++++------ 8 files changed, 80 insertions(+), 117 deletions(-) delete mode 100644 bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/service/impl/VirtualGraphInitializer.java diff --git a/bundles/org.simantics.db.layer0/plugin.xml b/bundles/org.simantics.db.layer0/plugin.xml index 086945062..2e25ff3c3 100644 --- a/bundles/org.simantics.db.layer0/plugin.xml +++ b/bundles/org.simantics.db.layer0/plugin.xml @@ -19,10 +19,6 @@ class="org.simantics.db.layer0.service.impl.ActivationServiceInitializer" id="org.simantics.db.layer0.service.ActivationServiceInitializer"> - - diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/service/impl/VirtualGraphInitializer.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/service/impl/VirtualGraphInitializer.java deleted file mode 100644 index ae7e7c8c5..000000000 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/service/impl/VirtualGraphInitializer.java +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.db.layer0.service.impl; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Enumeration; -import java.util.UUID; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; -import org.eclipse.core.runtime.Status; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.simantics.databoard.Bindings; -import org.simantics.databoard.Datatypes; -import org.simantics.databoard.serialization.Serializer; -import org.simantics.databoard.type.Datatype; -import org.simantics.db.Session; -import org.simantics.db.VirtualGraph; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.internal.Activator; -import org.simantics.db.service.VirtualGraphSupport; -import org.simantics.db.services.ServiceInitializer; -import org.simantics.graph.db.ImportAdvisor; -import org.simantics.graph.db.TransferableGraphs; -import org.simantics.graph.representation.TransferableGraph1; - -/** - * A database client service initializer which ensures that any .tg - * files defined in a bundle folder virtualgraphs are imported into - * randomly named in-memory virtualgraphs for the initialized session. - * - * @author Antti Villberg - */ -public class VirtualGraphInitializer implements ServiceInitializer { - - @Override - public IStatus initialize(Session s) { - MultiStatus result = new MultiStatus(Activator.PLUGIN_ID, 0, "VirtualGraphInitialize errors:", null); - BundleContext context = Activator.getInstance().getContext(); - Serializer datatypeSerializer = Bindings.getSerializerUnchecked( Datatype.class ); - Datatype tgType = Datatypes.getDatatypeUnchecked(TransferableGraph1.class); - Serializer tgSerializer = Bindings.getSerializerUnchecked( TransferableGraph1.class ); - for (final Bundle b : context.getBundles()) { - Enumeration graphs = b.getEntryPaths("virtualgraphs"); - while(graphs != null && graphs.hasMoreElements()) { - String element = (String)graphs.nextElement(); - if(!element.endsWith(".tg")) - continue; - URL url = b.getEntry(element); - try { - InputStream stream = url.openStream(); - Datatype dt = (Datatype) datatypeSerializer.deserialize( stream ); - if(dt.equals(tgType)) { - VirtualGraphSupport support = s.getService(VirtualGraphSupport.class); - VirtualGraph vg = support.getMemoryPersistent(UUID.randomUUID().toString()); - TransferableGraph1 tg = (TransferableGraph1) tgSerializer.deserialize(stream); - TransferableGraphs.importVirtualGraph(s, vg, tg, - new ImportAdvisor()); - } - stream.close(); - } catch (IOException e) { - IStatus status = new Status(IStatus.ERROR, context.getBundle().getSymbolicName(), "VirtualGraphInitializer transferable graph initialization failed for '" + url.toString() + "', see exception for details.", e); - result.add(status); - } catch (DatabaseException e) { - IStatus status = new Status(IStatus.ERROR, context.getBundle().getSymbolicName(), "VirtualGraphInitializer transferable graph initialization failed for '" + url.toString() + "', see exception for details.", e); - result.add(status); - } - } - } - if (!result.isOK()) return result; - return Status.OK_STATUS; - } - -} diff --git a/bundles/org.simantics.db.services/META-INF/MANIFEST.MF b/bundles/org.simantics.db.services/META-INF/MANIFEST.MF index d127cb93d..7403f3d70 100644 --- a/bundles/org.simantics.db.services/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.db.services/META-INF/MANIFEST.MF @@ -7,7 +7,8 @@ Bundle-Vendor: VTT Technical Research Centre of Finland Require-Bundle: org.eclipse.core.runtime, gnu.trove3, org.simantics.layer0.utils;bundle-version="1.1.0", - org.simantics.layer0x.ontology;bundle-version="1.0.0" + org.simantics.layer0x.ontology;bundle-version="1.0.0", + org.slf4j.api;bundle-version="1.7.25" Export-Package: org.simantics.db.services, org.simantics.db.services.activation, org.simantics.db.services.adaption diff --git a/bundles/org.simantics.db.services/src/org/simantics/db/services/AdaptionServiceInitializer.java b/bundles/org.simantics.db.services/src/org/simantics/db/services/AdaptionServiceInitializer.java index e5e1259e8..35d62f007 100644 --- a/bundles/org.simantics.db.services/src/org/simantics/db/services/AdaptionServiceInitializer.java +++ b/bundles/org.simantics.db.services/src/org/simantics/db/services/AdaptionServiceInitializer.java @@ -19,18 +19,24 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.services.adaption.AdapterRegistry2; import org.simantics.db.services.adaption.AdaptionService2; import org.simantics.db.services.internal.Activator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Tuukka Lehtonen */ public class AdaptionServiceInitializer implements ServiceInitializer { + private static final Logger LOGGER = LoggerFactory.getLogger(AdaptionServiceInitializer.class); + public IStatus initialize(final Session s) { + LOGGER.info("Initializing"); AdaptionService2 service = new AdaptionService2(); s.registerService(AdaptionService.class, service); try { AdapterRegistry2 registry = new AdapterRegistry2(); registry.initialize(Activator.getDefault().getContext()); + LOGGER.info("Updating"); registry.updateAdaptionService(s, service); return Status.OK_STATUS; } catch (DatabaseException e) { diff --git a/bundles/org.simantics.db.services/src/org/simantics/db/services/GlobalServiceInitializer.java b/bundles/org.simantics.db.services/src/org/simantics/db/services/GlobalServiceInitializer.java index 84a2d1c6a..c30170233 100644 --- a/bundles/org.simantics.db.services/src/org/simantics/db/services/GlobalServiceInitializer.java +++ b/bundles/org.simantics.db.services/src/org/simantics/db/services/GlobalServiceInitializer.java @@ -20,12 +20,16 @@ import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.simantics.db.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Tuukka Lehtonen */ public class GlobalServiceInitializer implements ServiceInitializer { + private static final Logger LOGGER = LoggerFactory.getLogger(GlobalServiceInitializer.class); + private static final String PLUGIN_ID = "org.simantics.db.services"; private static final String SERVICE_INITIALIZER = "serviceInitializer"; @@ -36,6 +40,7 @@ public class GlobalServiceInitializer implements ServiceInitializer { public IStatus initialize(final Session s) { MultiStatus problems = new MultiStatus(PLUGIN_ID, INITIALIZER_ERROR, "ServiceInitializer errors:", null); + LOGGER.info("Initializing.."); // Initialize adaption service merge(problems, new AdaptionServiceInitializer().initialize(s)); @@ -48,7 +53,7 @@ public class GlobalServiceInitializer implements ServiceInitializer { if (ep != null) { for (IConfigurationElement conf : ep.getConfigurationElements()) { try { -// System.out.println("initialize: " + conf.getAttribute("class") + " (id=" + conf.getAttribute("id") + ")"); + LOGGER.info("initialize: " + conf.getAttribute("class") + " (id=" + conf.getAttribute("id") + ")"); ServiceInitializer initializer = (ServiceInitializer) conf.createExecutableExtension("class"); merge(problems, initializer.initialize(s)); } catch (CoreException e) { diff --git a/bundles/org.simantics.project/src/org/simantics/project/impl/Project.java b/bundles/org.simantics.project/src/org/simantics/project/impl/Project.java index 7d507bbb2..1a4e9f687 100644 --- a/bundles/org.simantics.project/src/org/simantics/project/impl/Project.java +++ b/bundles/org.simantics.project/src/org/simantics/project/impl/Project.java @@ -34,6 +34,8 @@ import org.simantics.utils.datastructures.disposable.IDisposeListener; import org.simantics.utils.datastructures.hints.HintContext; import org.simantics.utils.threads.IThreadWorkQueue; import org.simantics.utils.threads.SyncListenerList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** @@ -41,6 +43,8 @@ import org.simantics.utils.threads.SyncListenerList; */ public class Project extends HintContext implements IProject { + private static final Logger LOGGER = LoggerFactory.getLogger(Project.class); + private static IProjectFeature[] NONE = {}; //private static final String TAG_PROJECTS = "projects"; @@ -120,6 +124,7 @@ public class Project extends HintContext implements IProject { IProjectFeature feature = inactiveFeatures.getFirst(); boolean success = false; try { + LOGGER.info("Configuring project feature {}", feature); feature.setProjectElement(this); feature.configure(); diff --git a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/Activator.java b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/Activator.java index b629e08d9..4642fb5a4 100644 --- a/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/Activator.java +++ b/bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/Activator.java @@ -1,18 +1,25 @@ package org.simantics.scl.osgi.internal; import java.util.Hashtable; +import java.util.concurrent.ForkJoinPool; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; +import org.simantics.scl.compiler.errors.Failable; +import org.simantics.scl.compiler.module.Module; import org.simantics.scl.compiler.module.repository.ModuleRepository; import org.simantics.scl.compiler.module.repository.UpdateListener; import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; import org.simantics.scl.compiler.source.repository.ProceduralModuleSourceRepository; import org.simantics.scl.compiler.source.repository.SourceRepositories; import org.simantics.scl.osgi.SCLOsgi; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Activator implements BundleActivator { + private static final Logger LOGGER = LoggerFactory.getLogger(Activator.class); + public static final String PLUGIN_ID = "org.simantics.scl.osgi"; private static BundleContext context; @@ -37,6 +44,13 @@ public class Activator implements BundleActivator { } }, properties); + // Let's try to compile StandardLibrary asynchronously to speed up + // the compilation when we actually need it the first time + LOGGER.info("Warming up SCL-compiler with StandardLibrary"); + ForkJoinPool.commonPool().submit(() -> { + Failable module = SCLOsgi.MODULE_REPOSITORY.getModule("StandardLibrary"); + LOGGER.info("StandardLibrary compiled {}", module); + }); } public void stop(BundleContext bundleContext) throws Exception { diff --git a/bundles/org.simantics/src/org/simantics/SimanticsPlatform.java b/bundles/org.simantics/src/org/simantics/SimanticsPlatform.java index 1f367dc9a..a4206e7da 100644 --- a/bundles/org.simantics/src/org/simantics/SimanticsPlatform.java +++ b/bundles/org.simantics/src/org/simantics/SimanticsPlatform.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * Copyright (c) 2007, 2018 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -110,9 +110,10 @@ import org.simantics.project.management.PlatformUtil; import org.simantics.project.management.ServerManager; import org.simantics.project.management.ServerManagerFactory; import org.simantics.project.management.WorkspaceUtil; +import org.simantics.scl.compiler.module.repository.ModuleRepository; +import org.simantics.scl.osgi.SCLOsgi; import org.simantics.utils.FileUtils; import org.simantics.utils.datastructures.Pair; -import org.simantics.utils.logging.TimeLogger; import org.simantics.utils.strings.EString; import org.simantics.utils.threads.ExecutorWorker; import org.simantics.utils.threads.ThreadUtils; @@ -397,8 +398,7 @@ public class SimanticsPlatform implements LifecycleListener { sb.append("Conflict with "+problem.first+" and "+problem.second+".\n"); } throw new PlatformException(sb.toString()); - } - else if(!session.syncRequest( analyzer.queryExternalDependenciesSatisfied )) { + } else if(!session.syncRequest( analyzer.queryExternalDependenciesSatisfied )) { Collection unsatisfiedDependencies = analyzer.getUnsatisfiedDependencies(); StringBuilder sb = new StringBuilder(); for (IdentityNode dep: unsatisfiedDependencies) { @@ -410,6 +410,10 @@ public class SimanticsPlatform implements LifecycleListener { throw new PlatformException(sb.toString()); } + message = "Analyzed graph bundles"; + monitor.subTask(message); + LOGGER.info(message); + List sortedBundles = analyzer.getSortedGraphs(); if(!sortedBundles.isEmpty()) { @@ -488,6 +492,9 @@ public class SimanticsPlatform implements LifecycleListener { } session.getService(XSupport.class).setServiceMode(false, false); } + message = "Ontologies synchronized"; + monitor.subTask(message); + LOGGER.info(message); monitor.worked(100); } catch (IOException e) { throw new PlatformException(e); @@ -784,8 +791,6 @@ public class SimanticsPlatform implements LifecycleListener { { assert(!running); - TimeLogger.log("Beginning of SimanticsPlatform.startUp"); - LOGGER.info("Beginning of SimanticsPlatform.startUp"); SubMonitor monitor = SubMonitor.convert(progressMonitor, 1000); @@ -797,15 +802,19 @@ public class SimanticsPlatform implements LifecycleListener { // 0. Consult all startup extensions before doing anything with the workspace. StartupExtensions.consultStartupExtensions(); - TimeLogger.log("Consulted platform pre-startup extensions"); + LOGGER.info("Consulted platform pre-startup extensions"); // 0.1. Clear all temporary files Simantics.clearTemporaryDirectory(); - TimeLogger.log("Cleared temporary directory"); + LOGGER.info("Cleared temporary directory"); // 0.2 Clear VariableRepository.repository static map which holds references to SessionImplDb VariableRepository.clear(); + // 0.2.1 Activate org.simantics.scl.osgi to prime the SCL compiler early. + @SuppressWarnings("unused") + ModuleRepository modRepo = SCLOsgi.MODULE_REPOSITORY; + // 0.3 Handle baseline database before opening db @SuppressWarnings("unused") boolean usingBaseline = handleBaselineDatabase(); @@ -813,8 +822,8 @@ public class SimanticsPlatform implements LifecycleListener { // 1. Assert there is a database at /db SessionDescriptor sessionDescriptor = setupDatabase(databaseDriverId, monitor.newChild(200, SubMonitor.SUPPRESS_NONE), workspacePolicy, userAgent); session = sessionDescriptor.getSession(); - TimeLogger.log("Database setup complete"); - + LOGGER.info("Database setup complete"); + // 2. Delete all indexes if we cannot be certain they are up-to-date // A full index rebuild will be done later, before project activation. XSupport support = session.getService(XSupport.class); @@ -828,7 +837,6 @@ public class SimanticsPlatform implements LifecycleListener { // 3. Assert all graphs, and correct versions, are installed to the database synchronizeOntologies(monitor.newChild(400, SubMonitor.SUPPRESS_NONE), ontologyPolicy, requireSynchronize); - TimeLogger.log("Synchronized ontologies"); // 4. Assert simantics.cfg exists boolean installProject = assertConfiguration(monitor.newChild(25, SubMonitor.SUPPRESS_NONE),workspacePolicy); @@ -838,7 +846,7 @@ public class SimanticsPlatform implements LifecycleListener { // 6. Install all features into project, if in debug mode updateInstalledGroups(monitor.newChild(25), true); //installProject); - TimeLogger.log("Installed all features into project"); + LOGGER.info("Installed all features into project"); // 7. Assert L0.Session in database for this session assertSessionModel(monitor.newChild(25, SubMonitor.SUPPRESS_NONE)); @@ -846,19 +854,21 @@ public class SimanticsPlatform implements LifecycleListener { session.getService(XSupport.class).setServiceMode(false, false); try { - monitor.setTaskName("Flush query cache"); + String message = "Flush query cache"; + monitor.setTaskName(message); + LOGGER.info(message); session.syncRequest((Write) graph -> { QueryControl qc = graph.getService(QueryControl.class); qc.flush(graph); }); - TimeLogger.log("Flushed queries"); } catch (DatabaseException e) { LOGGER.error("Flushing queries failed.", e); } boolean loadProject = true; try { - - monitor.setTaskName("Open database session"); + String message = "Open database session"; + monitor.setTaskName(message); + LOGGER.info(message); sessionContext = SimanticsPlatform.INSTANCE.createSessionContext(true); // This must be before setSessionContext since some listeners might query this sessionContext.setHint(SimanticsKeys.KEY_PROJECT, SimanticsPlatform.INSTANCE.projectResource); @@ -866,6 +876,8 @@ public class SimanticsPlatform implements LifecycleListener { Simantics.setSessionContext(sessionContext); // 1. Put ResourceBinding that throws an exception to General Bindings + message = "Put ResourceBinding that throws an exception to General Bindings"; + LOGGER.info(message); simanticsBindings = new SimanticsBindings(); Bindings.classBindingFactory.addFactory( simanticsBindings ); @@ -873,11 +885,15 @@ public class SimanticsPlatform implements LifecycleListener { session.registerService(Databoard.class, Bindings.databoard); // Register datatype bindings + message = "Register datatype bindings"; + LOGGER.info(message); Bindings.defaultBindingFactory.getRepository().put(RGB.Integer.BINDING.type(), RGB.Integer.BINDING); Bindings.defaultBindingFactory.getRepository().put(Font.BINDING.type(), Font.BINDING); if (support.rolledback() || sessionDescriptor.isFreshDatabase()) { - monitor.setTaskName("Rebuilding all indexes"); + message = "Rebuilding all indexes"; + LOGGER.info(message); + monitor.setTaskName(message); try { session.getService(IndexedRelations.class).fullRebuild(monitor.newChild(100), session); } catch (IndexException e) { @@ -888,17 +904,21 @@ public class SimanticsPlatform implements LifecycleListener { } if(loadProject) { - TimeLogger.log("Load project"); - monitor.setTaskName("Load project"); + message = "Load project"; + monitor.setTaskName(message); + LOGGER.info(message); project = Projects.loadProject(sessionContext.getSession(), SimanticsPlatform.INSTANCE.projectResource); sessionContext.setHint(ProjectKeys.KEY_PROJECT, project); monitor.worked(100); - TimeLogger.log("Loading projects complete"); + message = "Loading projects complete"; + LOGGER.info(message); - monitor.setTaskName("Activate project"); + message = "Activate project"; + monitor.setTaskName(message); + LOGGER.info(message); project.activate(); monitor.worked(100); - TimeLogger.log("Project activated"); + LOGGER.info("Project activated"); } } catch (DatabaseException e) { @@ -920,7 +940,7 @@ public class SimanticsPlatform implements LifecycleListener { // the user from undoing any initialization operations performed // by the platform startup. SimanticsPlatform.INSTANCE.discardSessionUndoHistory(); - TimeLogger.log("Discarded session undo history"); + LOGGER.info("Discarded session undo history"); return sessionContext; @@ -930,10 +950,12 @@ public class SimanticsPlatform implements LifecycleListener { try { // Construct and initialize SessionContext from Session. SessionContext sessionContext = SessionContext.create(session, init); - TimeLogger.log("Session context created"); + String message = "Session context created"; + LOGGER.info(message); if (init) { sessionContext.registerServices(); - TimeLogger.log("Session services registered"); + message = "Session services registered"; + LOGGER.info(message); } return sessionContext; } catch (DatabaseException e) { -- 2.47.1