[education/rkward] rkward: Add (disable) code for performance testing the plugin script backend.

Thomas Friedrichsmeier null at kde.org
Fri Apr 15 21:57:57 BST 2022


Git commit c518e9374d2beff20a87f98af142b36a415d64b4 by Thomas Friedrichsmeier.
Committed on 15/04/2022 at 20:57.
Pushed by tfry into branch 'master'.

Add (disable) code for performance testing the plugin script backend.

Results:
- QJSEngine takes twice as long as QScriptBackend to initialize, probably mostly for not being able to use a pre-compiled common.js.
- It is still _very_ fast, with initialization and parsing common.js taking around 1.5ms on a moderately age notebook.
- Considering we only need to create a handful of threads, and only on direct user interaction, that seems good enough.

Should performance become more of a concern, QJSEngines could be re-used, with common.js inserted as a module.

M  +1    -1    rkward/misc/rkmessagecatalog.h
M  +3    -0    rkward/plugin/rkstandardcomponent.cpp
M  +25   -0    rkward/scriptbackends/qtscriptbackend.cpp
M  +6    -0    rkward/scriptbackends/qtscriptbackend.h

https://invent.kde.org/education/rkward/commit/c518e9374d2beff20a87f98af142b36a415d64b4

diff --git a/rkward/misc/rkmessagecatalog.h b/rkward/misc/rkmessagecatalog.h
index 376d2146..02d5980f 100644
--- a/rkward/misc/rkmessagecatalog.h
+++ b/rkward/misc/rkmessagecatalog.h
@@ -28,7 +28,7 @@ public:
 /** Get the catalog identified by name. This could be an already open catalog, or a new one. In the latter case, the catalog is expected at pathhint. In the former case, pathhint is ignored. This function is guaranteed to return a non-null RKMessageCatalog, although that does not imply the catalog could actually be loaded. */
 	static RKMessageCatalog *getCatalog (const QString &name, const QString &pathhint);
 /** Returns a dummy null-catalog */
-       static RKMessageCatalog *nullCatalog ();
+	static RKMessageCatalog *nullCatalog ();
 /** Switch language to use for any coming translations */
 	static void switchLanguage (const QString &new_language_code);
 private:
diff --git a/rkward/plugin/rkstandardcomponent.cpp b/rkward/plugin/rkstandardcomponent.cpp
index 9db294f9..d958b218 100644
--- a/rkward/plugin/rkstandardcomponent.cpp
+++ b/rkward/plugin/rkstandardcomponent.cpp
@@ -157,6 +157,9 @@ RKStandardComponent::RKStandardComponent (RKComponent *parent_component, QWidget
 		}
 		buildAndInitialize (doc_element, gui_element, parent_widget, build_wizard);
 	}
+#ifdef JSBACKEND_PERFORMANCE_TEST
+	QtScriptBackend::_performanceTest();
+#endif
 }
 
 RKStandardComponent::~RKStandardComponent () {
diff --git a/rkward/scriptbackends/qtscriptbackend.cpp b/rkward/scriptbackends/qtscriptbackend.cpp
index f30aa906..e034aeff 100644
--- a/rkward/scriptbackends/qtscriptbackend.cpp
+++ b/rkward/scriptbackends/qtscriptbackend.cpp
@@ -34,6 +34,31 @@ QtScriptBackend::~QtScriptBackend () {
 	if (script_thread && script_thread->isRunning ()) script_thread->terminate ();
 }
 
+#ifdef JSBACKEND_PERFORMANCE_TEST
+#include <QElapsedTimer>
+#include <QApplication>
+#include <QObjectCleanupHandler>
+#include "../misc/rkmessagecatalog.h"
+void QtScriptBackend::_performanceTest() {
+	RK_DEBUG(PHP, DL_WARNING, "Starting QtScriptBackend performance test");
+	QElapsedTimer t;
+	QObjectCleanupHandler h;
+	t.start();
+	for (int i = 0; i < 1000; ++i) {
+		auto b = new QtScriptBackend(QString(), RKMessageCatalog::nullCatalog());
+		b->dead = true; // so it doesn't try to show an error message
+		h.add(b);
+		b->initialize(nullptr, false);
+		connect(b->script_thread, &QtScriptBackendThread::error, b, &QObject::deleteLater);  // thread will throw an error, when trying to include non-existent script file
+	}
+	while (!h.isEmpty()) {
+		qApp->processEvents();
+	}
+	RK_DEBUG(PHP, DL_WARNING, "Time to init 100 backends: %d", t.elapsed());
+	RK_DEBUG(PHP, DL_WARNING, "QtScriptBackend performance test end");
+}
+#endif
+
 bool QtScriptBackend::initialize (RKComponentPropertyCode *code_property, bool add_headings) {
 	RK_TRACE (PHP);
 
diff --git a/rkward/scriptbackends/qtscriptbackend.h b/rkward/scriptbackends/qtscriptbackend.h
index eb2aa396..276dc0f0 100644
--- a/rkward/scriptbackends/qtscriptbackend.h
+++ b/rkward/scriptbackends/qtscriptbackend.h
@@ -13,6 +13,8 @@ SPDX-License-Identifier: GPL-2.0-or-later
 class QtScriptBackendThread;
 class RKMessageCatalog;
 
+//#define JSBACKEND_PERFORMANCE_TEST
+
 /** This class allows to use QtScript as a scripting backend in RKWard.
 
 The script itself is run in a separate thread to ensure good performance even for complex scripts. This is especially important for spinboxes, where the value is changes many times in quick succession. Note that this is also the reason not to use Kross, which appears to be not thread safe.
@@ -33,6 +35,9 @@ public:
 	void printout (int flags) override { callFunction ("do_printout ();\n", flags, Printout); };
 	void preview (int flags) override { callFunction ("do_preview ();\n", flags, Preview); };
 	void writeData (const QVariant &data) override;
+#ifdef JSBACKEND_PERFORMANCE_TEST
+	static void _performanceTest();
+#endif
 public slots:
 	void threadError (const QString &message);
 	void commandDone (const QString &result);
@@ -50,6 +55,7 @@ private:
 #include <QThread>
 #include <QMutex>
 
+//#define USE_QJSENGINE
 #ifdef USE_QJSENGINE
 #include <QtQml/QJSEngine>
 #define RKJSEngine QJSEngine


More information about the rkward-tracker mailing list