Я пытаюсь оптимизировать операции QScriptEngine в одной из моих функций.
Функция названа executeCustomJSOperation
и он выполняет тот же код JS в нескольких файлах. Однако каждый файл должен изменить глобальную переменную с именем $xmlData
, Функция в основном загружает файл XML в память, используя $xmlData
переменная, а затем всегда применять один и тот же код JavaScript (jsString
) для редактирования этого XML-файла с использованием JavaScript. В конце концов $xmlData
переменная снова обновляется с отредактированным XML.
У меня ускорение 2.5 с использованием только OpenMP parallel for
через цикл for, который обрабатывает каждый файл XML. Но сейчас я не знаю, как дальше улучшать эту функцию.
Код следующий:
// allows user to echo js variables to check them in terminal using cout
QScriptValue echo(QScriptContext *context, QScriptEngine *engine)
{
std::cout << context->argument(0).toString().toUtf8().constData() << std::endl;
return "";
}
void executeCustomJSOperation(const QString &jsString, const QStringList &filesToProcess){
QString rexmlString, jsxmlString;
QFile rexmlfile(":/resources/libs/rexml.js"); // load javascript libraries as strings to memory
QFile jsxmlfile(":/resources/libs/jsxml.js");
rexmlfile.open(QFile::ReadOnly | QFile::Text);
jsxmlfile.open(QFile::ReadOnly | QFile::Text);
rexmlString=QTextStream(&rexmlfile).readAll();
jsxmlString=QTextStream(&jsxmlfile).readAll();
// Process all XmlFiles
#pragma omp parallel for // 2.5 speedup in my pc
for(int i=0; i<filesToProcess.size(); i++){
QString currXmlFileString;
QScriptEngine engine;
QScriptValue engineResult;
// Add echo function so user can debug the code
QScriptValue echoFunction = engine.newFunction(echo);
engine.globalObject().setProperty("echo", echoFunction);
engine.evaluate(rexmlString); // load js libraries in js engine
engine.evaluate(jsxmlString);
QFile currXmlFile(filesToProcess[i]);
currXmlFileString=QTextStream(&currXmlFile).readAll();
currXmlFile.close(); // close reading
engine.globalObject().setProperty("$xmlData",currXmlFileString);
engine.evaluate("main(); function main() {"+jsString+"}"); // main function allows to use return to exit prematurely from user code
engineResult=engine.globalObject().property("$xmlData");
QTextStream(&currXmlFile) << engineResult.toString(); // retreive the modified xml by javascript and save it to the file
}
}
Как вы думаете, можно ли оптимизировать этот код дальше? Если у вас есть какие-либо сомнения, пожалуйста, спросите.
Почему вы создаете / инициализируете отдельный QScriptEngine для каждой итерации? Я бы предложил перенести все на вашу линию
engine.evaluate(jsxmlString);
за пределами for()-loop
,
Правда, это усложнит многопоточность WRT. По сути, вам придется настроить N рабочие потоки, и создайте один обработчик сценариев для каждого потока (не для файла). Для начала, простая однопоточная версия должна дать вам первое представление о том, какое ускорение ожидать, и стоит ли оно того.
Конечно, если ваш код JS действительно только для одноразового использования, QScriptProgram
ваша единственная надежда на оптимизацию. Опять же, вы должны настроить ограниченное количество рабочих потоков, каждый со своим QScriptProgram
(и один QScriptEngine
за итерацию, как в вашем текущем коде).
Вы можете построить QScriptProgram
вставьте в него весь код JS и оцените его, используя QScriptEngine::evaluate
, Это может ускорить выполнение, потому что анализ JS-кода будет выполняться только один раз. Тем не мение, QScriptProgram
не задокументирован как реентерабельный или поточно-ориентированный, поэтому вы не можете быть уверены, что он будет работать правильно в нескольких потоках, даже если каждый поток использует свой собственный QScriptProgram
объект.