A little while ago, I published an item on GAS performance, showing that a complex calculation test would take about 100 times as long on GAS as the same thing in regular javascript running locally on a browser, and 10 times as long as the same thing on VBA.
So the question is – is it really running the same thing? To make sure, I showed how to retrieve and run GAS code directly in the browser, bypassing GAS altogether.
As a final comparison, I’ll also show to use HTML service to cajole the GAS code to be run locally in the browser but, this time directed from GAS.
The test code
function testCompareSpeed() { Logger.log(speedTest()); } function speedTest() { useTimer('x','10000 iterations of color comparison').start(); for (var i = 1 ; i <= 10000 ;i++) { compareColors (i, VBCOLORS.vbWhite - i); } useTimer('x').stop(); return useTimer().report(); }
GAS direct
Locally on client, retrieving code from GAS
Locally on client, pushed by HTML service.
HTMLservice code will run clientside, as described here. So I reasoned that if I could publish the code, and cause it to be executed locally I should get results similar to the pure javaScript version – but I was wrong – 15 seconds is better than 26, but nowhere near 0.2.
Firstly, here’s the template you need to do this.
<html> <head> </head> <body> <div> <script> // the source from GAS <?!= getSources(["vEquivalents","usefulColors","hacks","timerStuff"],"mcpher"); ?> // do the test and report it alert (speedTest()); </script> </div> </body> </html>
And the code
I use the same libraries as in Publishing with Google Apps Script to play around with the GAS source, but here’s the specific code for populating the template above with the GAS scripts so that they can be run locally.
function doGet(e) { //---------- var eArgs = {parameter:{template:"runonclient",sandboxmode:"native"}}; // convert source to correct format var result = express(eArgs); // publish as appropriate var output= HtmlService.createHtmlOutput(result); if (eArgs.parameter.sandboxmode=="native") { output.setSandboxMode(HtmlService.SandboxMode.NATIVE); } return output; } /* convert source code to required format * @param {object} e arg to doGet(e) * @return {object} the source expressed according the format */ function express(e) { // evaluate the template try { var template = HtmlService.createTemplateFromFile(e.parameter.template); return template.evaluate().getContent(); } catch (err) { return { error: 'error ' + err + 'reading template' + e.parameter.template}; } } function getSources(modules,library) { var s=""; for (var i=0; i < modules.length;i++) { var e = { parameter: { source: "script", library: library, module: modules[i], type:"javascript", template:""}}; s+= getMySource(e).results.data; } return s; } /** gets the appropriate source for the combination of requested module and requested library * @param {String} content the web content * @return {String} the escaped content */ function getSource() { return getMySource(eArgs); } // -- write a getMySource() to retrieve any modules in THIS script file /* Returns a modules source code * @param {parameters} e the argument to doGet(e). should have module parameter specified * @return {object} The result. */ function getMySource(e) { // probably doesnt need changed, except if you need a custom function // the purpose of all this is to execute the scriptdb/scriptapp in the correct project according to the library selected try { return mcpher.getGeneralSource(e, e.parameter.source == 'script' ? eval(mcpher.addLibraryPrefix(e,"showMyScriptAppResource"))(e.parameter.module) : ( e.parameter.source == 'scriptdb' ? eval( mcpher.addLibraryPrefix(e,"showMyScriptDb"))() : null ) , function (e) { // this is a custom function if you need one return null;} ); } catch (err) { return { error : err + " when trying to get module ", parameters : e.parameter }; } }
You can try it here, or look at it here.
Conclusion
- I am running exactly the same code in all 3 javascript versions, since the code is being served directly from GAS.
- The VBA version is a simple translation
- I notice that the cajoled GAS code has been caja-ized (if that’s a word) with oodles of code wrapped around it.
- If I simplify the Maths, then GAS runs much more quickly – so I figured I’m probably introducing a memory leak that only manifests itself on GAS/Caja – yet the time taken is purely linear – 1000 iterations takes 10 times as long as a 100 – wouldn’t a memory leak be spiky or non-linear. How to debug that when it only appears if wrapped up in caja?
For more stuff like this, see from VBA to Google Apps Script, and for more detail on this post see Serving up javaScript from GAS