scripting: Add benchmark to scripting

Change-Id: Iacbc5bbb85ba0796a0a4ce11be2cc238bdaa42f7
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/154902
Tested-by: Trace Compass Bot <tracecompass-bot@eclipse.org>
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.core.tests/.project b/scripting/org.eclipse.tracecompass.incubator.scripting.core.tests/.project
index 12f601d..ae1f77d 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.core.tests/.project
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.core.tests/.project
@@ -6,6 +6,11 @@
 	</projects>
 	<buildSpec>
 		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
 			</arguments>
@@ -24,5 +29,6 @@
 	<natures>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.python.pydev.pythonNature</nature>
 	</natures>
 </projectDescription>
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/internal/scripting/core/ScriptExecutionHelper.java b/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/internal/scripting/core/ScriptExecutionHelper.java
index 2601f7d..bd61c4c 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/internal/scripting/core/ScriptExecutionHelper.java
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/internal/scripting/core/ScriptExecutionHelper.java
@@ -12,6 +12,7 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.List;
 
 import org.eclipse.ease.IScriptEngine;
 import org.eclipse.ease.ScriptResult;
@@ -38,23 +39,32 @@
      *         script did not execute properly
      */
     public static @Nullable Object executeScript(String filePath) {
+        return executeScript(filePath, null, null);
+    }
+
+    /**
+     * Execute the script file pointed to by the path
+     *
+     * @param filePath
+     *            The absolute path of the file containing the script to execute
+     * @param engineID
+     *            The ID of the engine to run this script with. If
+     *            <code>null</code>, the method will try to find the right
+     *            engine.
+     * @param arguments
+     *            The arguments to the script, or <code>null</code> if there are
+     *            no arguments
+     * @return The return value of the script, or <code>null</code> if the
+     *         script did not execute properly
+     */
+    public static @Nullable Object executeScript(String filePath, @Nullable String engineID, @Nullable List<String> arguments) {
         // Does the file exists
         Path path = Paths.get(filePath);
         if (!Files.exists(path)) {
             Activator.getInstance().logWarning(String.format("Script file does not exist %s", filePath)); //$NON-NLS-1$
             return null;
         }
-        EngineDescription engineDescription = null;
-        final IScriptService scriptService = ScriptService.getInstance();
-
-        // locate engine by file extension
-        final ScriptType scriptType = scriptService.getScriptType(filePath);
-        if (scriptType == null) {
-            Activator.getInstance().logWarning(String.format("No script type was found for script %s", filePath)); //$NON-NLS-1$
-            return null;
-        }
-
-        engineDescription = scriptService.getEngine(scriptType.getName());
+        EngineDescription engineDescription = getEngine(filePath, engineID);
         if (engineDescription == null) {
             Activator.getInstance().logWarning(String.format("No engine was found to execute script %s", filePath)); //$NON-NLS-1$
             return null;
@@ -63,9 +73,10 @@
         // create engine
         final IScriptEngine engine = engineDescription.createEngine();
 
-        // TODO Support script arguments
-        // engine.setVariable("argv", ((List)
-        // parameters.get("args")).toArray(new String[0]));
+        // Add the arguments to the script
+        if (arguments != null) {
+            engine.setVariable("argv", arguments.toArray(new String[arguments.size()])); //$NON-NLS-1$
+        }
 
         Object scriptObject = ResourceTools.resolve(filePath);
         if (scriptObject == null) {
@@ -119,4 +130,27 @@
 
     }
 
+    private static @Nullable EngineDescription getEngine(@Nullable String filePath, @Nullable String engineID) {
+        final IScriptService scriptService = ScriptService.getInstance();
+
+        if (engineID != null) {
+            EngineDescription engineDescription = scriptService.getEngineByID(engineID);
+            if (engineDescription == null) {
+                throw new NullPointerException("Script engine not found " + engineID); //$NON-NLS-1$
+            }
+            return engineDescription;
+        }
+
+        // locate engine by file extension
+        final ScriptType scriptType = scriptService.getScriptType(filePath);
+        if (scriptType == null) {
+            Activator.getInstance().logWarning(String.format("No script type was found for script %s", filePath)); //$NON-NLS-1$
+            return null;
+        }
+
+        EngineDescription engineDescription = scriptService.getEngine(scriptType.getName());
+        return engineDescription;
+
+    }
+
 }
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/scripting/core/trace/TraceScriptingModule.java b/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/scripting/core/trace/TraceScriptingModule.java
index b57470a..2b8499b 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/scripting/core/trace/TraceScriptingModule.java
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/scripting/core/trace/TraceScriptingModule.java
@@ -73,6 +73,10 @@
      * view. Typical use is for stand-alone scripts who want to run and export
      * content without interacting with the UI. The trace must have been
      * previously imported in trace compass as it needs to be in a project.
+     * <p>
+     * The trace will not be attached to the workspace, so it is important after
+     * using to dispose of it by calling the {@link ITmfTrace#dispose()} method.
+     * </p>
      *
      * @param projectName
      *            The name of the project
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/scripting/core/utils/UtilsModule.java b/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/scripting/core/utils/UtilsModule.java
index 1e69192..cbf31cc 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/scripting/core/utils/UtilsModule.java
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.core/src/org/eclipse/tracecompass/incubator/scripting/core/utils/UtilsModule.java
@@ -38,4 +38,19 @@
         return new ListWrapper<>();
     }
 
+    /**
+     * Convert a string to an array of string, as some scripting languages do
+     * not easily support arrays (like jython)
+     *
+     * @param string
+     *            The element to add to the array
+     * @return An array of string containing the element in parameter
+     */
+    @WrapToScript
+    public String[] strToArray(String string) {
+        String[] array = new String[1];
+        array[0] = string;
+        return array;
+    }
+
 }
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/.classpath b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/.classpath
index b8d064f..4f6014c 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/.classpath
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/.classpath
@@ -11,5 +11,6 @@
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="perf"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/.project b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/.project
index dc0b8d3..b93bf7a 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/.project
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/.project
@@ -6,6 +6,11 @@
 	</projects>
 	<buildSpec>
 		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
 			</arguments>
@@ -24,5 +29,6 @@
 	<natures>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.python.pydev.pythonNature</nature>
 	</natures>
 </projectDescription>
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/META-INF/MANIFEST.MF b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/META-INF/MANIFEST.MF
index 42087ce..a4c63e0 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/META-INF/MANIFEST.MF
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-Vendor: %Bundle-Vendor
-Bundle-SymbolicName: org.eclipse.tracecompass.incubator.scripting.ui.tests
+Bundle-SymbolicName: org.eclipse.tracecompass.incubator.scripting.ui.tests;singleton:=true
 Bundle-Version: 0.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
@@ -22,8 +22,19 @@
  org.eclipse.ease,
  org.eclipse.ease.lang.javascript.nashorn,
  org.eclipse.ease.lang.python.py4j,
- org.eclipse.ui
-Export-Package: org.eclipse.tracecompass.incubator.scripting.ui.tests
+ org.eclipse.ui,
+ org.eclipse.tracecompass.ctf.core.tests,
+ org.eclipse.tracecompass.lttng2.kernel.core,
+ org.eclipse.tracecompass.tmf.ctf.core,
+ org.eclipse.tracecompass.lttng2.common.core,
+ org.eclipse.tracecompass.analysis.os.linux.core,
+ org.eclipse.tracecompass.tmf.ui,
+ org.eclipse.ui.views,
+ org.eclipse.tracecompass.tmf.ui.tests,
+ org.eclipse.tracecompass.tmf.analysis.xml.core.tests
+Export-Package: org.eclipse.tracecompass.incubator.scripting.core.tests.perf,
+ org.eclipse.tracecompass.incubator.scripting.ui.tests
 Automatic-Module-Name: org.eclipse.tracecompass.incubator.scripting.ui.tests
 Import-Package: com.google.common.collect,
- org.apache.commons.io
+ org.apache.commons.io,
+ org.eclipse.test.performance
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/build.properties b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/build.properties
index b375d46..abdfbf0 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/build.properties
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/build.properties
@@ -7,10 +7,11 @@
 # http://www.eclipse.org/legal/epl-v10.html
 ###############################################################################
 
-source.. = src/
+source.. = src/,\
+           perf/
 output.. = bin/
 bin.includes = META-INF/,\
                .,\
                about.html,\
-               plugin.properties
-
+               plugin.properties,\
+               plugin.xml
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/perf/org/eclipse/tracecompass/incubator/scripting/core/tests/perf/ScriptingBenchmark.java b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/perf/org/eclipse/tracecompass/incubator/scripting/core/tests/perf/ScriptingBenchmark.java
new file mode 100644
index 0000000..3b7883b
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/perf/org/eclipse/tracecompass/incubator/scripting/core/tests/perf/ScriptingBenchmark.java
@@ -0,0 +1,542 @@
+/*******************************************************************************
+ * Copyright (c) 2020 École Polytechnique de Montréal
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.incubator.scripting.core.tests.perf;
+
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.io.FileUtils;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.test.performance.Dimension;
+import org.eclipse.test.performance.Performance;
+import org.eclipse.test.performance.PerformanceMeter;
+import org.eclipse.tracecompass.analysis.os.linux.core.tid.TidAnalysisModule;
+import org.eclipse.tracecompass.ctf.core.tests.shared.CtfBenchmarkTrace;
+import org.eclipse.tracecompass.incubator.internal.scripting.core.ScriptExecutionHelper;
+import org.eclipse.tracecompass.incubator.scripting.core.trace.TraceScriptingModule;
+import org.eclipse.tracecompass.incubator.scripting.ui.tests.ActivatorTest;
+import org.eclipse.tracecompass.incubator.scripting.ui.tests.TestModule;
+import org.eclipse.tracecompass.internal.tmf.ui.project.model.TmfImportHelper;
+import org.eclipse.tracecompass.lttng2.kernel.core.trace.LttngKernelTrace;
+import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.common.TmfXmlTestUtils;
+import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
+import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
+import org.eclipse.tracecompass.tmf.core.tests.shared.TmfTestHelper;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ctf.core.event.CtfTmfEvent;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.tracecompass.tmf.ui.tests.shared.ProjectModelTestData;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Benchmarks EASE Scripting in native java, javascript (Nashorn and Rhino) and
+ * python (Jython and Py4j)
+ *
+ * @author Geneviève Bastien
+ */
+@RunWith(Parameterized.class)
+public class ScriptingBenchmark {
+
+    /**
+     * Initial value for which to compute the Collatz sequence
+     */
+    public static final int INITIAL_VALUE = 10;
+    /**
+     * Last value for which to compute the Collatz sequence
+     */
+    public static final int LIMIT = 300000;
+
+    private static final String JAVASCRIPT_EXTENSION = ".js";
+    private static final String PYTHON_EXTENSION = ".py";
+    private static final String XML_EXTENSION = ".xml";
+
+    private static final String JAVA_PREFIX = "Java: ";
+    private static final String RHINO_PREFIX = "JS Rhino: ";
+    private static final String NASHORN_PREFIX = "JS Nashorn: ";
+    private static final String PY4J_PREFIX = "Py4j: ";
+    private static final String JYTHON_PREFIX = "Jython: ";
+    private static final String XML_PREFIX = "XML: ";
+
+    private static final int LOOP_COUNT = 25;
+    private static final int LOOP_COUNT_SMALL = 5;
+
+    private static final String DEFAULT_PROJECT = "Tracing";
+
+    private static final String JAVASCRIPT_PATH = "scripts/perf/javascript/";
+    private static final String PYTHON_PATH = "scripts/perf/python/";
+    private static final String XML_PATH = "scripts/perf/xml/";
+
+    private static final String RHINO_ENGINE = "org.eclipse.ease.javascript.rhino";
+    private static final String NASHORN_ENGINE = "org.eclipse.ease.javascript.nashorn";
+    private static final String JYTHON_ENGINE = "org.eclipse.ease.python.jython";
+    private static final String PY4J_ENGINE = "org.eclipse.ease.lang.python.py4j.engine";
+    private static final String XML_ANALYSIS_ID = "tracecompass.script.benchmark";
+
+    private static final CtfTestTrace SMALL_TRACE = CtfTestTrace.SYNC_DEST;
+    private static final CtfBenchmarkTrace LARGE_TRACE = CtfBenchmarkTrace.ALL_OS_ANALYSES;
+    private static TmfProjectElement sfProject;
+
+    /**
+     * @return The arrays of parameters
+     * @throws IOException
+     *             Exception thrown initializing the traces
+     */
+    @Parameters(name = "{index}: {0}")
+    public static Iterable<Object[]> getParameters() throws IOException {
+        return Arrays.asList(new Object[][] {
+                { "Empty Script", EMPTY, "empty", null, LOOP_COUNT },
+                { "Simple Computation", SIMPLE_COMPUTATION, "simpleComputation", null, LOOP_COUNT },
+                { "Computation Through Java", JAVA_COMPUTATION, "computationJava", null, LOOP_COUNT },
+                { "Computation Through Callback", CALLBACK_COMPUTATION, "computationCallback", null, LOOP_COUNT / 2 },
+                { "Compute Values in Java", COMPUTE_EACH_VALUE, "computationEachValue", null, LOOP_COUNT_SMALL },
+                { "Read trace events for os-events", READ_LARGE_TRACE, "readTrace", ImmutableList.of(String.valueOf(LARGE_TRACE.getTracePath().getFileName())), LOOP_COUNT_SMALL },
+                { "Read trace events for small trace", READ_SMALL_TRACE, "readTrace", ImmutableList.of(String.valueOf(FileUtils.toFile(FileLocator.toFileURL(SMALL_TRACE.getTraceURL())).getName())), LOOP_COUNT },
+                { "TID analysis for Os-events", TID_ANALYSIS_LARGE_TRACE, "tidAnalysis", ImmutableList.of(String.valueOf(LARGE_TRACE.getTracePath().getFileName())), LOOP_COUNT_SMALL },
+                { "TID analysis for small trace", TID_ANALYSIS_SMALL_TRACE, "tidAnalysis", ImmutableList.of(String.valueOf(FileUtils.toFile(FileLocator.toFileURL(SMALL_TRACE.getTraceURL())).getName())), LOOP_COUNT },
+
+        });
+    }
+
+    private static final Runnable EMPTY = () -> {
+        // Do nothing much, to benchmark script initialization
+        int i = 0;
+        System.out.println(i);
+    };
+
+    private static final Runnable SIMPLE_COMPUTATION = () -> {
+        // Compute the Collatz Conjecture sequence for integers between INITIAL_VALUE and LIMIT
+        int base = INITIAL_VALUE;
+        long value = base;
+        while (base < LIMIT) {
+            if (value == 1) {
+                value = base++;
+            }
+            if (value % 2 == 0) {
+                value = value / 2;
+            } else {
+                value = 3 * value + 1;
+            }
+        }
+    };
+
+    private static final Runnable JAVA_COMPUTATION = () -> {
+        TestModule testModule = new TestModule();
+        testModule.doJavaLoop();
+    };
+
+    private static final Runnable CALLBACK_COMPUTATION = () -> {
+        TestModule testModule = new TestModule();
+        testModule.doLoopWithCallback(value -> {
+            if (value % 2 == 0) {
+                return value / 2;
+            }
+            return 3 * value + 1;
+        });
+    };
+
+    private static final Runnable COMPUTE_EACH_VALUE = () -> {
+        // Compute the Collatz Conjecture sequence for integers between INITIAL_VALUE and LIMIT
+        TestModule testModule = new TestModule();
+        testModule.doJavaLoop();
+        int base = INITIAL_VALUE;
+        long value = base;
+        while (base < 100000) {
+            if (value == 1) {
+                value = base++;
+            }
+            value = testModule.compute(value);
+        }
+    };
+
+    private static void readTrace(String absolutePathToTrace) {
+        LttngKernelTrace trace = new LttngKernelTrace();
+        try {
+            trace.initTrace(null, absolutePathToTrace, CtfTmfEvent.class);
+            TraceScriptingModule module = new TraceScriptingModule();
+            Iterator<@NonNull ITmfEvent> eventIterator = module.getEventIterator(trace);
+            int schedSwitchCnt = 0;
+            while (eventIterator.hasNext()) {
+                ITmfEvent event = eventIterator.next();
+                if (event.getName().equals("sched_switch")) {
+                    schedSwitchCnt++;
+                }
+            }
+            System.out.println("Count sched switch: " + schedSwitchCnt);
+        } catch (TmfTraceException e) {
+            fail(e.getMessage());
+        } finally {
+            trace.dispose();
+        }
+    }
+
+    private static final Runnable READ_LARGE_TRACE = () -> {
+        readTrace(LARGE_TRACE.getTracePath().toString());
+    };
+
+    private static final Runnable READ_SMALL_TRACE = () -> {
+        try {
+            readTrace(FileUtils.toFile(FileLocator.toFileURL(SMALL_TRACE.getTraceURL())).getAbsolutePath());
+        } catch (IOException e) {
+            fail(e.getMessage());
+        }
+    };
+
+    private static void deleteSupplementaryFiles(@NonNull ITmfTrace trace) {
+        /*
+         * Delete the supplementary files at the end of the benchmarks
+         */
+        File suppDir = new File(TmfTraceManager.getSupplementaryFileDir(trace));
+        for (File file : suppDir.listFiles()) {
+            file.delete();
+        }
+    }
+
+    private static void runTidAnalysis(String absolutePathtoFile) {
+        LttngKernelTrace trace = new LttngKernelTrace();
+        TidAnalysisModule analysisModule = null;
+        try {
+
+            trace.initTrace(null, absolutePathtoFile, CtfTmfEvent.class);
+
+            analysisModule = new TidAnalysisModule();
+            analysisModule.setTrace(trace);
+
+            TmfTestHelper.executeAnalysis(analysisModule);
+
+        } catch (TmfTraceException | TmfAnalysisException e) {
+            fail(e.getMessage());
+        } finally {
+            deleteSupplementaryFiles(trace);
+            if (analysisModule != null) {
+                analysisModule.dispose();
+            }
+            trace.dispose();
+        }
+    }
+
+    private static final Runnable TID_ANALYSIS_SMALL_TRACE = () -> {
+        try {
+            runTidAnalysis(FileUtils.toFile(FileLocator.toFileURL(SMALL_TRACE.getTraceURL())).getAbsolutePath());
+        } catch (IOException e) {
+            fail(e.getMessage());
+        }
+    };
+
+    private static final Runnable TID_ANALYSIS_LARGE_TRACE = () -> {
+        runTidAnalysis(LARGE_TRACE.getTracePath().toString());
+    };
+
+    private final String fName;
+    private final Runnable fJavaMethod;
+    private final String fScript;
+    private final @Nullable List<@NonNull String> fArguments;
+    private final int fLoopCount;
+
+    /**
+     * Constructor
+     *
+     * @param name
+     *            The name of the test
+     * @param javaMethod
+     *            The java runnable method to benchmark the java part
+     * @param script
+     *            The name of the files for this test. Language-specific
+     *            extension will be appended
+     * @param arguments
+     *            The list of arguments to pass to the script
+     * @param loopCount
+     *            The number of times the benchmark should run
+     */
+    public ScriptingBenchmark(String name, Runnable javaMethod, String script, @Nullable List<@NonNull String> arguments, int loopCount) {
+        fName = name;
+        fJavaMethod = javaMethod;
+        fScript = script;
+        fArguments = arguments;
+        fLoopCount = loopCount;
+    }
+
+    /**
+     * Prepare the workspace by preloading the required traces
+     *
+     * @throws CoreException
+     *             Exception preparing the traces
+     * @throws IOException
+     *             Exception preparing the traces
+     */
+    @BeforeClass
+    public static void prepareWorkspace() throws CoreException, IOException {
+        IProject project = TmfProjectRegistry.createProject(DEFAULT_PROJECT, null, null);
+        final TmfProjectElement projectElement = TmfProjectRegistry.getProject(project, true);
+        TmfTraceFolder tracesFolder = projectElement.getTracesFolder();
+        if (tracesFolder != null) {
+            IFolder traceFolder = tracesFolder.getResource();
+
+            /* Add the all os events trace from benchmark */
+            Path tracePath = LARGE_TRACE.getTracePath();
+            IPath pathString = new org.eclipse.core.runtime.Path(tracePath.toString());
+            IResource linkedTrace = TmfImportHelper.createLink(traceFolder, pathString, pathString.lastSegment());
+            if (!(linkedTrace != null && linkedTrace.exists())) {
+                throw new NullPointerException("Trace cannot be created");
+            }
+            linkedTrace.setPersistentProperty(TmfCommonConstants.TRACETYPE,
+                    "org.eclipse.linuxtools.lttng2.kernel.tracetype");
+
+            /* Add the django test trace */
+            String absolutePath = FileUtils.toFile(FileLocator.toFileURL(SMALL_TRACE.getTraceURL())).getAbsolutePath();
+            pathString = new org.eclipse.core.runtime.Path(absolutePath);
+            linkedTrace = TmfImportHelper.createLink(traceFolder, pathString, pathString.lastSegment());
+            if (!(linkedTrace != null && linkedTrace.exists())) {
+                throw new NullPointerException("Trace cannot be created");
+            }
+            linkedTrace.setPersistentProperty(TmfCommonConstants.TRACETYPE,
+                    "org.eclipse.linuxtools.lttng2.kernel.tracetype");
+
+            // Refresh the project model
+            tracesFolder.refresh();
+
+            for (TmfTraceElement traceElement : tracesFolder.getTraces()) {
+                traceElement.refreshTraceType();
+            }
+        }
+        projectElement.refresh();
+        sfProject = projectElement;
+    }
+
+    /**
+     * Delete project and traces at the end
+     */
+    @AfterClass
+    public static void deleteProject() {
+        TmfProjectElement project = sfProject;
+        if (project != null) {
+            Display.getDefault().syncExec(() -> ProjectModelTestData.deleteProject(project));
+        }
+    }
+
+    /**
+     * Benchmark the java runnable
+     */
+    @Test
+    public void javaTest() {
+
+        Performance perf = Performance.getDefault();
+        PerformanceMeter pmJava = perf.createPerformanceMeter(JAVA_PREFIX + fName);
+        perf.tagAsSummary(pmJava, JAVA_PREFIX + fName, Dimension.CPU_TIME);
+
+        for (int i = 0; i < fLoopCount; i++) {
+            pmJava.start();
+            fJavaMethod.run();
+            pmJava.stop();
+        }
+        pmJava.commit();
+
+    }
+
+    /**
+     * Benchmark the javascript rhino engine
+     */
+    @Test
+    public void javaScriptRhinoTest() {
+
+        IPath absoluteFilePath = ActivatorTest.getAbsoluteFilePath(JAVASCRIPT_PATH + fScript + JAVASCRIPT_EXTENSION);
+
+        Performance perf = Performance.getDefault();
+        PerformanceMeter pmJavaScript = perf.createPerformanceMeter(RHINO_PREFIX + fName);
+        perf.tagAsSummary(pmJavaScript, RHINO_PREFIX + fName, Dimension.CPU_TIME);
+
+        for (int i = 0; i < fLoopCount; i++) {
+            pmJavaScript.start();
+            ScriptExecutionHelper.executeScript(Objects.requireNonNull(absoluteFilePath.toOSString()), RHINO_ENGINE, fArguments);
+            pmJavaScript.stop();
+        }
+        pmJavaScript.commit();
+    }
+
+    /**
+     * Benchmark the javascript nashorn engine
+     */
+    @Test
+    public void javaScriptNashornTest() {
+        IPath absoluteFilePath = ActivatorTest.getAbsoluteFilePath(JAVASCRIPT_PATH + fScript + JAVASCRIPT_EXTENSION);
+
+        Performance perf = Performance.getDefault();
+        PerformanceMeter pmJavaScript = perf.createPerformanceMeter(NASHORN_PREFIX + fName);
+        perf.tagAsSummary(pmJavaScript, NASHORN_PREFIX + fName, Dimension.CPU_TIME);
+
+        for (int i = 0; i < fLoopCount; i++) {
+            pmJavaScript.start();
+            ScriptExecutionHelper.executeScript(Objects.requireNonNull(absoluteFilePath.toOSString()), NASHORN_ENGINE, fArguments);
+            pmJavaScript.stop();
+        }
+        pmJavaScript.commit();
+    }
+
+    /**
+     * Benchmark the python py4j engine
+     */
+    @Test
+    public void py4jTest() {
+        // See if a specific file for py4j exists, otherwise, use the python
+        // script
+        IPath absoluteFilePath;
+        try {
+            absoluteFilePath = ActivatorTest.getAbsoluteFilePath(PYTHON_PATH + "py4j_" + fScript + PYTHON_EXTENSION);
+        } catch (NullPointerException e) {
+            absoluteFilePath = ActivatorTest.getAbsoluteFilePath(PYTHON_PATH + fScript + PYTHON_EXTENSION);
+        }
+
+        Performance perf = Performance.getDefault();
+        PerformanceMeter pmPython = perf.createPerformanceMeter(PY4J_PREFIX + fName);
+        perf.tagAsSummary(pmPython, PY4J_PREFIX + fName, Dimension.CPU_TIME);
+
+        for (int i = 0; i < fLoopCount; i++) {
+            pmPython.start();
+            ScriptExecutionHelper.executeScript(Objects.requireNonNull(absoluteFilePath.toOSString()), PY4J_ENGINE, fArguments);
+            pmPython.stop();
+        }
+        pmPython.commit();
+    }
+
+    /**
+     * Benchmark the python jython engine
+     */
+    @Test
+    public void jythonTest() {
+        // See if a specific file for py4j exists, otherwise, use the python
+        // script
+        IPath absoluteFilePath;
+        try {
+            absoluteFilePath = ActivatorTest.getAbsoluteFilePath(PYTHON_PATH + "jython_" + fScript + PYTHON_EXTENSION);
+        } catch (NullPointerException e) {
+            absoluteFilePath = ActivatorTest.getAbsoluteFilePath(PYTHON_PATH + fScript + PYTHON_EXTENSION);
+        }
+
+        Performance perf = Performance.getDefault();
+        PerformanceMeter pmPython = perf.createPerformanceMeter(JYTHON_PREFIX + fName);
+        perf.tagAsSummary(pmPython, JYTHON_PREFIX + fName, Dimension.CPU_TIME);
+
+        for (int i = 0; i < fLoopCount; i++) {
+            pmPython.start();
+            ScriptExecutionHelper.executeScript(Objects.requireNonNull(absoluteFilePath.toOSString()), JYTHON_ENGINE, fArguments);
+            pmPython.stop();
+        }
+        pmPython.commit();
+    }
+
+    private static @NonNull ITmfTrace getTraceForXml(String traceName) {
+        String tracePath = null;
+        try {
+            if (String.valueOf(LARGE_TRACE.getTracePath().getFileName()).equals(traceName)) {
+                tracePath = LARGE_TRACE.getTracePath().toString();
+            } else if (String.valueOf(FileUtils.toFile(FileLocator.toFileURL(SMALL_TRACE.getTraceURL())).getName()).equals(traceName)) {
+                tracePath = FileUtils.toFile(FileLocator.toFileURL(SMALL_TRACE.getTraceURL())).getAbsolutePath();
+            }
+        } catch (IOException e1) {
+            throw new NullPointerException("Cannot initialize trace: " + e1.getMessage());
+        }
+        if (tracePath == null) {
+            throw new NullPointerException("Cannot find trace: " + traceName);
+        }
+
+        // The trace is one of the 2 traces small or large
+        LttngKernelTrace trace = new LttngKernelTrace();
+        try {
+            trace.initTrace(null, tracePath, CtfTmfEvent.class);
+        } catch (TmfTraceException e) {
+            trace.dispose();
+            throw new NullPointerException("can't open the trace: " + e.getMessage());
+        }
+        return trace;
+    }
+
+    /**
+     * Benchmark the xml analysis that does the same
+     *
+     * @throws TmfAnalysisException
+     *             Exceptions thrown by setting the trace to the module
+     */
+    @Test
+    public void xmlTest() throws TmfAnalysisException {
+        // See if an XML file exists for this script
+        IPath absoluteFilePath;
+        try {
+            absoluteFilePath = ActivatorTest.getAbsoluteFilePath(XML_PATH + fScript + XML_EXTENSION);
+        } catch (NullPointerException e) {
+            // There was no file, don't fail the test.
+            return;
+        }
+
+        Performance perf = Performance.getDefault();
+        PerformanceMeter pmXmlcript = perf.createPerformanceMeter(XML_PREFIX + fName);
+        perf.tagAsSummary(pmXmlcript, XML_PREFIX + fName, Dimension.CPU_TIME);
+
+        List<@NonNull String> arguments = fArguments;
+        if (arguments == null || arguments.isEmpty()) {
+            throw new NullPointerException("XML analysis set to run, but the arguments do not contain the path to the trace");
+        }
+
+        String tracePath = arguments.get(0);
+
+        ITmfTrace trace = getTraceForXml(tracePath);
+        try {
+            for (int i = 0; i < fLoopCount; i++) {
+                TmfAbstractAnalysisModule module = null;
+                try {
+                    module = TmfXmlTestUtils.getModuleInFile(Objects.requireNonNull(absoluteFilePath.toOSString()), XML_ANALYSIS_ID);
+                    module.setTrace(trace);
+                    pmXmlcript.start();
+                    TmfTestHelper.executeAnalysis(module);
+                    pmXmlcript.stop();
+                } finally {
+                    if (module != null) {
+                        module.dispose();
+                    }
+                }
+                deleteSupplementaryFiles(trace);
+            }
+            pmXmlcript.commit();
+        } finally {
+            deleteSupplementaryFiles(trace);
+            trace.dispose();
+        }
+
+    }
+
+}
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/perf/org/eclipse/tracecompass/incubator/scripting/core/tests/perf/package-info.java b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/perf/org/eclipse/tracecompass/incubator/scripting/core/tests/perf/package-info.java
new file mode 100644
index 0000000..00d44dd
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/perf/org/eclipse/tracecompass/incubator/scripting/core/tests/perf/package-info.java
@@ -0,0 +1,10 @@
+/*******************************************************************************
+ * Copyright (c) 2020 École Polytechnique de Montréal
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.incubator.scripting.core.tests.perf;
\ No newline at end of file
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/plugin.xml b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/plugin.xml
new file mode 100644
index 0000000..95ceed0
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/plugin.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         point="org.eclipse.ease.modules">
+      <module
+            category="org.eclipse.tracecompass.incubator.scripting.ui.tests.category"
+            class="org.eclipse.tracecompass.incubator.scripting.ui.tests.TestModule"
+            id="org.eclipse.tracecompass.incubator.scripting.ui.tests"
+            name="Test"
+            visible="true">
+      </module>
+      <category
+            id="org.eclipse.tracecompass.incubator.scripting.ui.tests.category"
+            name="TraceCompassTest">
+      </category>
+   </extension>
+
+</plugin>
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationCallback.js b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationCallback.js
new file mode 100644
index 0000000..ebe33cf
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationCallback.js
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Geneviève Bastien
+ * 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
+ *******************************************************************************/
+
+loadModule("/TraceCompassTest/Test")
+
+function compute(value) {
+    if (value % 2 == 0) {
+        return value / 2;
+    }
+    return 3 * value + 1;
+}
+
+doLoopWithCallback(compute)
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationEachValue.js b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationEachValue.js
new file mode 100644
index 0000000..52c2d82
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationEachValue.js
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Geneviève Bastien
+ * 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
+ *******************************************************************************/
+
+loadModule("/TraceCompassTest/Test")
+
+base = 10;
+limit = 100000
+value = base;
+while (base < limit) {
+    if (value == 1) {
+        base = base + 1
+        value = base;
+    }
+    value = compute(value)
+}
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationJava.js b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationJava.js
new file mode 100644
index 0000000..d7ceff1
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/computationJava.js
@@ -0,0 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Geneviève Bastien
+ * 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
+ *******************************************************************************/
+
+loadModule("/TraceCompassTest/Test")
+
+doJavaLoop()
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/empty.js b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/empty.js
new file mode 100644
index 0000000..b4b8cfd
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/empty.js
@@ -0,0 +1,10 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Geneviève Bastien
+ * 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
+ *******************************************************************************/
+
+i = 0;
+
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/readTrace.js b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/readTrace.js
new file mode 100644
index 0000000..a6b5b6f
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/readTrace.js
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Geneviève Bastien
+ * 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
+ *******************************************************************************/
+
+loadModule("/TraceCompass/Trace")
+
+var trace = openMinimalTrace("Tracing", argv[0])
+
+eventIterator = getEventIterator(trace);
+schedSwitchCnt = 0;
+while (eventIterator.hasNext()) {
+    event = eventIterator.next();
+    if (event.getName().equals("sched_switch")) {
+        schedSwitchCnt = schedSwitchCnt + 1
+    }
+}
+print("Sched switch " + schedSwitchCnt)
+trace.dispose()
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/simpleComputation.js b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/simpleComputation.js
new file mode 100644
index 0000000..a70e7b0
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/simpleComputation.js
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Geneviève Bastien
+ * 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
+ *******************************************************************************/
+
+base = 10;
+limit = 300000
+value = base;
+while (base < limit) {
+    if (value == 1) {
+        base = base + 1
+        value = base;
+    }
+    if (value % 2 == 0) {
+        value = value / 2;
+    } else {
+        value = 3 * value + 1;
+    }
+}
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/tidAnalysis.js b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/tidAnalysis.js
new file mode 100644
index 0000000..3b70871
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/javascript/tidAnalysis.js
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Geneviève Bastien
+ * 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
+ *******************************************************************************/
+
+// load Trace Compass modules
+loadModule('/TraceCompass/Analysis');
+loadModule('/TraceCompass/Trace');
+loadModule('/TraceCompass/TraceUI');
+
+trace = openTrace("Tracing", argv[0])
+
+// Create an analysis for this script
+analysis = createScriptedAnalysis(trace, "activetid_python.js")
+
+if (analysis == null) {
+	print("Trace is null");
+	exit();
+}
+
+// Get the analysis's state system so we can fill it, false indicates to create a new state system even if one already exists, true would re-use an existing state system
+var ss = analysis.getStateSystem(false);
+
+// The analysis itself is in this function
+function runAnalysis() {
+	// Get the event iterator for the trace
+	var iter = analysis.getEventIterator();
+
+	var event = null;
+	// Parse all events
+	while (iter.hasNext()) {
+
+		event = iter.next();
+
+		// Do something when the event is a sched_switch
+		if (event.getName() == "sched_switch") {
+			// This function is a wrapper to get the value of field CPU in the event, or return null if the field is not present
+			cpu = getEventFieldValue(event, "CPU");
+			tid = getEventFieldValue(event, "next_tid");
+			if ((cpu != null) && (tid != null)) {
+				// Write the tid to the state system, for the attribute corresponding to the cpu
+				quark = ss.getQuarkAbsoluteAndAdd(cpu);
+				// modify the value, tid is a long, so "" + tid make sure it's a string for display purposes
+				ss.modifyAttribute(event.getTimestamp().toNanos(), "" + tid, quark);
+			}
+		}
+	}
+	// Done parsing the events, close the state system at the time of the last event, it needs to be done manually otherwise the state system will still be waiting for values and will not be considered finished building
+	if (event != null) {
+		ss.closeHistory(event.getTimestamp().toNanos());
+	}
+}
+
+runAnalysis();
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationCallback.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationCallback.py
new file mode 100644
index 0000000..bb9ad6e
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationCallback.py
@@ -0,0 +1,21 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+loadModule("/TraceCompassTest/Test")
+
+from java.util.function import Function
+
+class CallbackFunction(Function):
+    def apply(self, value):
+        if value % 2 == 0:
+            return value / 2
+        return 3 * value + 1
+
+callbackFunction = CallbackFunction()
+
+doLoopWithCallback(callbackFunction)
\ No newline at end of file
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationEachValue.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationEachValue.py
new file mode 100644
index 0000000..4f9a7ef
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationEachValue.py
@@ -0,0 +1,19 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+loadModule("/TraceCompassTest/Test")
+
+base = 10
+limit = 100000
+value = base;
+while base < limit:
+    if value == 1:
+        base = base + 1
+        value = base
+
+    value = compute(value)
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationJava.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationJava.py
new file mode 100644
index 0000000..e82299e
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/computationJava.py
@@ -0,0 +1,11 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+loadModule("/TraceCompassTest/Test")
+
+doJavaLoop()
\ No newline at end of file
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/empty.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/empty.py
new file mode 100644
index 0000000..16e0331
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/empty.py
@@ -0,0 +1,9 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+i = 0
\ No newline at end of file
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_computationCallback.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_computationCallback.py
new file mode 100644
index 0000000..eb3be99
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_computationCallback.py
@@ -0,0 +1,22 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+loadModule("/TraceCompassTest/Test")
+
+class CallbackFunction(object):
+    def apply(self, value):
+        if value % 2 == 0:
+            return value / 2
+        return 3 * value + 1
+
+    class Java:
+        implements = ['java.util.function.Function']
+
+callbackFunction = CallbackFunction()
+
+doLoopWithCallback(callbackFunction)
\ No newline at end of file
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_readTrace.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_readTrace.py
new file mode 100644
index 0000000..063caaa
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_readTrace.py
@@ -0,0 +1,24 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+loadModule("/TraceCompass/Trace")
+
+from py4j.java_gateway import JavaClass
+
+trace = openMinimalTrace("Tracing", argv[0])
+
+eventIterator = getEventIterator(trace)
+schedSwitchCnt = 0;
+while eventIterator.hasNext():
+    event = eventIterator.next()
+    if event.getName() == "sched_switch":
+        schedSwitchCnt = schedSwitchCnt + 1
+    gateway.detach(event)
+
+print(schedSwitchCnt)
+trace.dispose()
\ No newline at end of file
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_tidAnalysis.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_tidAnalysis.py
new file mode 100644
index 0000000..955f23c
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/py4j_tidAnalysis.py
@@ -0,0 +1,58 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+# load proper Trace Compass modules
+loadModule('/TraceCompass/Analysis');
+loadModule('/TraceCompass/Trace')
+loadModule('/TraceCompass/TraceUI');
+loadModule('/TraceCompass/Utils');
+
+from py4j.java_gateway import JavaClass
+
+trace = openTrace("Tracing", argv[0])
+
+# Create an analysis for this script
+analysis = createScriptedAnalysis(trace, "activetid_python.py")
+
+if analysis is None:
+    print("Trace is null")
+    exit()
+
+# Get the analysis's state system so we can fill it, true indicates to re-use an existing state system, false would create a new state system even if one already exists
+ss = analysis.getStateSystem(False)
+
+# The analysis itself is in this function
+def runAnalysis():
+    # Get the event iterator for the trace
+    iter = analysis.getEventIterator()
+
+    # Parse all events
+    event = None
+    while iter.hasNext():
+        # The python java gateway keeps a reference to the Java objects it sends to python. To avoid OutOfMemoryException, they need to be explicitly detached from the gateway when not needed anymore
+        if not(event is None):
+            gateway.detach(event)
+
+        event = iter.next();
+
+        # Do something when the event is a sched_switch
+        if event.getName() == "sched_switch":
+            # This function is a wrapper to get the value of field CPU in the event, or return null if the field is not present
+            cpu = getEventFieldValue(event, "CPU")
+            tid = getEventFieldValue(event, "next_tid")
+            if (not(cpu is None) and not(tid is None)):
+                # Write the tid to the state system, for the attribute corresponding to the cpu
+                quark = ss.getQuarkAbsoluteAndAdd(strToArray(str(cpu)))
+                # modify the value, tid is a long, so "" + tid make sure it's a string for display purposes
+                ss.modifyAttribute(event.getTimestamp().toNanos(), str(tid), quark)
+
+    # Done parsing the events, close the state system at the time of the last event, it needs to be done manually otherwise the state system will still be waiting for values and will not be considered finished building
+    if not(event is None):
+        ss.closeHistory(event.getTimestamp().toNanos())
+
+runAnalysis()
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/readTrace.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/readTrace.py
new file mode 100644
index 0000000..1c45bda
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/readTrace.py
@@ -0,0 +1,21 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+loadModule("/TraceCompass/Trace")
+
+trace = openMinimalTrace("Tracing", argv[0])
+
+eventIterator = getEventIterator(trace)
+schedSwitchCnt = 0;
+while eventIterator.hasNext():
+    event = eventIterator.next()
+    if event.getName() == "sched_switch":
+        schedSwitchCnt = schedSwitchCnt + 1
+
+print(schedSwitchCnt)
+trace.dispose()
\ No newline at end of file
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/simpleComputation.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/simpleComputation.py
new file mode 100644
index 0000000..45cbd4a
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/simpleComputation.py
@@ -0,0 +1,20 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+base = 10
+limit = 300000
+value = base;
+while base < limit:
+    if value == 1:
+        base = base + 1
+        value = base
+
+    if value % 2 == 0:
+        value = value / 2
+    else:
+        value = 3 * value + 1
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/tidAnalysis.py b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/tidAnalysis.py
new file mode 100644
index 0000000..588f946
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/python/tidAnalysis.py
@@ -0,0 +1,53 @@
+################################################################################
+# Copyright (c) 2020 Geneviève Bastien
+# 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
+################################################################################
+
+# load proper Trace Compass modules
+loadModule('/TraceCompass/Analysis')
+loadModule('/TraceCompass/Trace')
+loadModule('/TraceCompass/TraceUI')
+loadModule('/TraceCompass/Utils')
+
+trace = openTrace("Tracing", argv[0])
+
+# Create an analysis for this script
+analysis = createScriptedAnalysis(trace, "activetid_python.py")
+
+if analysis is None:
+    print("Trace is null")
+    exit()
+
+# Get the analysis's state system so we can fill it, true indicates to re-use an existing state system, false would create a new state system even if one already exists
+ss = analysis.getStateSystem(False)
+
+# The analysis itself is in this function
+def runAnalysis():
+    # Get the event iterator for the trace
+    iter = analysis.getEventIterator()
+
+    # Parse all events
+    event = None
+    while iter.hasNext():
+        
+        event = iter.next();
+
+        # Do something when the event is a sched_switch
+        if event.getName() == "sched_switch":
+            # This function is a wrapper to get the value of field CPU in the event, or return null if the field is not present
+            cpu = getEventFieldValue(event, "CPU")
+            tid = getEventFieldValue(event, "next_tid")
+            if (not(cpu is None) and not(tid is None)):
+                # Write the tid to the state system, for the attribute corresponding to the cpu
+                quark = ss.getQuarkAbsoluteAndAdd(str(cpu))
+                # modify the value, tid is a long, so "" + tid make sure it's a string for display purposes
+                ss.modifyAttribute(event.getTimestamp().toNanos(), str(tid), quark)
+       
+    # Done parsing the events, close the state system at the time of the last event, it needs to be done manually otherwise the state system will still be waiting for values and will not be considered finished building
+    if not(event is None):
+        ss.closeHistory(event.getTimestamp().toNanos())
+
+runAnalysis()
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/xml/tidAnalysis.xml b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/xml/tidAnalysis.xml
new file mode 100644
index 0000000..c0830c2
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/scripts/perf/xml/tidAnalysis.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ***************************************************************************
+* Copyright (c) 2020 École Polytechnique de Montréal
+*
+* 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
+*************************************************************************** -->
+<tmfxml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:noNamespaceSchemaLocation="xmlDefinition.xsd">
+
+	<stateProvider id="tracecompass.script.benchmark" version="1">
+		<head>
+			<traceType id="org.eclipse.linuxtools.lttng2.kernel.tracetype" />
+			<label value="XML TID analysis" />
+		</head>
+
+		<!-- case 1 : exit_syscall : Fields: int64 ret -->
+		<eventHandler eventName="sched_switch">
+			<stateChange>
+				<stateAttribute type="eventField" value="CPU" />
+				<stateValue type="eventField" value="next_tid" />
+			</stateChange>
+		</eventHandler>
+	</stateProvider>
+</tmfxml>
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/src/org/eclipse/tracecompass/incubator/scripting/ui/tests/TestModule.java b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/src/org/eclipse/tracecompass/incubator/scripting/ui/tests/TestModule.java
new file mode 100644
index 0000000..2a197b2
--- /dev/null
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui.tests/src/org/eclipse/tracecompass/incubator/scripting/ui/tests/TestModule.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2020 École Polytechnique de Montréal
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.incubator.scripting.ui.tests;
+
+import java.util.function.Function;
+
+import org.eclipse.ease.modules.WrapToScript;
+import org.eclipse.tracecompass.incubator.scripting.core.tests.perf.ScriptingBenchmark;
+
+/**
+ * EASE module for scripting purposes
+ *
+ * @author Geneviève Bastien
+ */
+public class TestModule {
+
+    /**
+     * Execute a simple computation of java instructions
+     */
+    @WrapToScript
+    public void doJavaLoop() {
+        int base = ScriptingBenchmark.INITIAL_VALUE;
+        long value = base;
+        while (base < ScriptingBenchmark.LIMIT) {
+            if (value == 1) {
+                value = base++;
+            }
+            if (value % 2 == 0) {
+                value = value / 2;
+            } else {
+                value = 3 * value + 1;
+            }
+        }
+    }
+
+    /**
+     * Execute a simple computation, but each loop calls a callback received in
+     * parameters to update the value
+     *
+     * @param function
+     *            The function callback to execute
+     */
+    @WrapToScript
+    public void doLoopWithCallback(Function<Long, Number> function) {
+        int base = ScriptingBenchmark.INITIAL_VALUE;
+        long value = base;
+        while (base < 20000) {
+            if (value == 1) {
+                value = base++;
+            }
+            value = function.apply(value).longValue();
+        }
+    }
+
+    /**
+     * Compute one value of the sequence
+     *
+     * @param value
+     *            The value to use to compute
+     * @return The result of the computation
+     */
+    @WrapToScript
+    public long compute(Long value) {
+        if (value % 2 == 0) {
+            return value / 2;
+        }
+        return 3 * value + 1;
+    }
+
+}
diff --git a/scripting/org.eclipse.tracecompass.incubator.scripting.ui/src/org/eclipse/tracecompass/incubator/scripting/ui/trace/TraceScriptingUI.java b/scripting/org.eclipse.tracecompass.incubator.scripting.ui/src/org/eclipse/tracecompass/incubator/scripting/ui/trace/TraceScriptingUI.java
index d579855..cdc31db 100644
--- a/scripting/org.eclipse.tracecompass.incubator.scripting.ui/src/org/eclipse/tracecompass/incubator/scripting/ui/trace/TraceScriptingUI.java
+++ b/scripting/org.eclipse.tracecompass.incubator.scripting.ui/src/org/eclipse/tracecompass/incubator/scripting/ui/trace/TraceScriptingUI.java
@@ -84,7 +84,7 @@
 
         ITmfTrace trace = projectElement.getTrace();
         Integer tryCounter = 0;
-        final Integer numberOfTry = 10;
+        final Integer numberOfTry = 20;
         /*
          * Need to wait until the job inside openTraceFromElement is done and
          * the trace is open. Otherwise there will be a race condition.