Speeding up platform startup time 07/2507/3
authorjsimomaa <jani.simomaa@gmail.com>
Fri, 30 Nov 2018 12:04:34 +0000 (14:04 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 30 Nov 2018 19:49:48 +0000 (21:49 +0200)
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
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/service/impl/VirtualGraphInitializer.java [deleted file]
bundles/org.simantics.db.services/META-INF/MANIFEST.MF
bundles/org.simantics.db.services/src/org/simantics/db/services/AdaptionServiceInitializer.java
bundles/org.simantics.db.services/src/org/simantics/db/services/GlobalServiceInitializer.java
bundles/org.simantics.project/src/org/simantics/project/impl/Project.java
bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/Activator.java
bundles/org.simantics/src/org/simantics/SimanticsPlatform.java

index 0869450622cb47701e72a4d92461a8b65cac25a9..2e25ff3c323e9eeb81814890d058e6fd756ef87d 100644 (file)
             class="org.simantics.db.layer0.service.impl.ActivationServiceInitializer"
             id="org.simantics.db.layer0.service.ActivationServiceInitializer">
       </service>
-      <service
-            class="org.simantics.db.layer0.service.impl.VirtualGraphInitializer"
-            id="org.simantics.db.layer0.service.VirtualGraphInitializer">
-      </service>
    </extension>
 
    <extension point="org.simantics.scl.reflection.binding">
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 (file)
index ae7e7c8..0000000
+++ /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 <code>.tg</code>
- * files defined in a bundle folder <code>virtualgraphs</code> 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;
-       }
-
-}
index d127cb93d40d240fd685ed1bbfa6822a01fa5c7c..7403f3d7004f475e4de2bd17d7006cef5739d349 100644 (file)
@@ -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
index e5e1259e81b0a81d68520154c4b81679c807d33e..35d62f007ee2053137eb3c58f3b57c63c14085ba 100644 (file)
@@ -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) {
index 84a2d1c6a3a9e380a3fef8b6cb57a53a5cb020a5..c3017023399bee8e17c88fc2218417b28851dfcd 100644 (file)
@@ -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) {
index 7d507bbb2e37970088e14a329ab2f1d3c7267209..1a4e9f6878234a7cbd78661098e4608de6e447fb 100644 (file)
@@ -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();
 
index b629e08d96817dc7d2935259ec8354af7c534edf..4642fb5a40d48922d1b46d8854cac9a6e69a5486 100644 (file)
@@ -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> module = SCLOsgi.MODULE_REPOSITORY.getModule("StandardLibrary");
+            LOGGER.info("StandardLibrary compiled {}", module);
+        });
     }
 
     public void stop(BundleContext bundleContext) throws Exception {
index 1f367dc9abf83d63c8201a95d000145ff8f5d3fe..a4206e7da3e677a947a6b1db5e7033f547f32eaa 100644 (file)
@@ -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<IdentityNode> 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<GraphBundle> 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 <workspace>/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) {