Profiling the Performance of a Google App Script - google-apps-script

I've written a Google App Script to pull in Google Analytics data into a Google Spreadsheet. It's a fairly long running script making multiple requests to the GA Reporting API, it also uses Google App's ScriptDB.
Is there a good way of profiling each step of the scripts performance so I can figure out what areas are taking the longest, so I can begin optimizing in certain areas?

As a complement to Fred's answer, define a variable start at the top of your script
var start = new Date().getTime();
then in a few Logger.log() placed a strategic points use
Logger.log(new Date().getTime()-start);
and you'll get a pretty good idea of what is going on...

The Execution Transcript is very useful for this kind of thing.
You can also put Logger.log() statements all over the place that measure the time since the last log. That way you can find areas that take longer to execute.
I have a spreadsheet where I copy the log after an execution and then formulas + conditional formatting help me identify areas that are slow.

The basic tools are the execution transcript and Class Logger (mentioned on previous answers)
Nowadays we could use Stackdriver logging and Class Console which includes console.time and console.timeEnd.
And to make things betters, also we could send Stackdriver logging to Google Data Studio through BigQuery, so we could build helpful metrics to track profiling data.
References
Stackdriver Logging for Google Apps Script is now available
Identify and understand errors in Apps Script with Stackdriver

To correct Serge's answer, where call to Date function has a problem, you can use this solution.
function myFunction() {
var start_time = new Date().getTime();
/*
your code goes here
*/
Logger.log('Total execution time is :' + (new Date().getTime()-start_time) + ' ms');
}
you can replace the comment lines with your code. After execution press Ctrl + Enter or Command ⌘ + Enter on Mac to see the logs. You will get something like following:
[17-01-18 12:25:58:932 UTC] Total execution time is :16586 ms
So here total execution time is 16586 ms or in other words 16.586 Seconds.
In addition to above you can add the following snippet in between your code to measure execution time from different parts.
Logger.log('Execution time till checkpoint 1:' + (new Date().getTime()-start_time) + ' ms');

You should probably use the methods console.time(label) and console.timeEnd(label) since you could get negative results when using Date.

Related

Measure my current usage consumption on google app script

I have a google app script that execute the following actions:
Read a incoming webhook, write some information on a google spreadsheet, update a google contact and generates several outbound webhooks.
It takes aproximately 5 seconds to execute the whole script.
I would like to know how much times per day I can execute this script. I have seen the following web page but I am not sure in which feature my actions might fit, since there is no description of what those each feature means.
https://developers.google.com/apps-script/guides/services/quotas
Also I check in the google app script dashboard in hope I could find the current usage of my app script, but I only found that my script is execute 500 times per day for an average of 5 seconds per execution. In the future I am going to need to execute this app script more times, but I will like to know which is limit.
¿Where can I find my current app script consumption and which are the quotas for the features I am currently using?
As mentioned in the comments, Google Apps Script has a quota page that shows execution limits on various services.
Please note that you can get quota exception messages if you go near these limits but not go over them entirely.
Since you mentioned that you may need to execute your script more than 500 times a day, you might want to start optimizing your functions to take less time. You can start searching for resources on how to do this, for example in this post: Tracking total execution time Google apps script for an account

Timeout errors with Google Slides API, and terrible write performance

I'm appending dozens of slides to presentations with a simple app script :
var presentation_to = SlidesApp.openById(presentation_to_id);
var presentation_from = SlidesApp.openById(presentation_from_id);
var slide = presentation_from.getSlideById(slide_id);
var newSlide = presentation_to.appendSlide(slide);
I have an app script API endpoint for that.
I started with one app script that would loop through all the slides IDs, but this had terrible performance and would timeout after 5 minutes. I've split my calls to the API app script to ask for one slide at a time, with parallelization (so I run several request to add a slide to the same presentation at once).
When the slides have big pictures in them, I still end up getting this :
Google::Apis::TransmissionError: execution expired
Is appendSlide() performance so bad what I want to do is not possible, or is there a way for me to make it work without having to wait 1h to generate one 50 slides presentation ?
PS : You'll find attached the logs of the script. Each line is meant to append ONE slide to a presentation (always the same destination). The execution times and error rates are just through the roof. Is performance simply limited by Google or is there a way to bypass this issue ?
Considerations
Using Apps Script SlideApp built-in Class you are basically creating an API call every time you run .appendSlide() method. This will cause big network overhead when your script inserts a lot of slides.
Generally this is solved by using batch requests via Advanced Google Services.
Unfortunately, there is no method to create a Page copy request that you could insert in a batch operation. If this is really important for your workflow you should consider filing a Feature Request
Reference
Slides API

How to enable Execution Transcript when this script runs?

I am using a script which is found here: https://moz.com/ugc/updated-tool-seomoz-api-data-for-google-docs
I would like to trigger this to run once an hour (as a test, later once a month); to facilitate this I set up a time driven trigger in the script editor UI.
I need to test that the trigger is actually working. The issue is that I do not expect any of the data to change when the script runs (might change once a month max)...
So I looked to the script editor and found View > Execution Transcript. Perfect!
Except that I get this message:
No execution transcripts found. Please run your script and try again.
This doesn't seem to be consistent with the expected behaviour after reading the Google Apps Script documentation page, which says:
Every time you run a script, Google Apps Script records an execution
transcript, which is a record of each call to a Google Apps Script
service that is made while the script runs.
(Nothing in the logs either by the ways, though maybe this is something that needs to be turned on by the script itself; not sure).
So how can I test to see that my time driven trigger works, and that the script is being run each hour?
Final note: The script is executed by calling a function in the spreadsheet, as explained in the link at the top of the question.
If you have not yet run it manually, there may be an issue with it being given the proper permissions. Your first step would be to run the code manually using the play button. Once you know that the code itself will run successfully and has the right permissions, you can move to triggering it automatically.
Your next step is to shorten your trigger time so that it executes more frequently giving you more instances to check the function. Depending on the structure of your code, you can add Logger.log() calls at different steps to make sure that all portions are being called that need to be. You can then check you logs instead of the execution transcript as well.
These Logger.log() calls could include the time at which is was called to be able to verify that it was at the time/ frequency you need.
Ok, I don't know how great this answer is... but:
For me (as per my comment to MasterCrander), running the script by means of using the function inside the spreadsheet didn't actually affect the execution transcript, but when it ran via the time driven trigger it made it into the transcript.
Problem solved.

Google Script Quotas - GmailApp.Search

I've spliced together a script which runs on a 1-minute interval and does a look-up on a Google label:
var mailthreads = GmailApp.search('label:MYLABEL');
Initially, the script ran fine, however within a few days the script began to throw a variety of errors, such as:
Service invoked too many times for one day: gmail
Service using too much computer time for one day
Service invoked too many times in a short time: gmail rateMax. Try Utilities.sleep(1000) between calls.
I have checked Quotas for Google Services with no real explination on what could be causing the script to fail - it ran initially day-to-day without fail, and as the cycle for quotas is 24-hours I would imagine if one 24-hour cycle worked, why didn't the rest?
One theory I have is that the GmailApp.Search query counts each returned item under the label as a single read, and now that the label has grown in size I am reaching a quota limit on reads. Is this how it works, and if not is there anything else I can check?

Getting "Script invoked too many times per second" when running script in Google Spreadsheet

I have this scheduling application I implemented 4 years ago using Google Spreadsheets. It creates a schedule (or passport) for a science fair. Last year, to make it easier to understand, I created a simple script that looked up the room location to add to the activity:
function getRoom(project, map) {
for (var i=0; i < map.length; i++) {
if (map[i][0] == project)
return(map[i][1]);
}
return("Not Found");
}
The Script is invoked close to 300 times on the worksheet as there are close to 40 schedules with 7 activities each. This worked fine till last year, started getting this error as I prepare the schedules for this year's science fair.
What quotas are this?
You haven't posted relevant code nor the actual error so I'll give a generic answer.
1) Read the apps script docs on how to write efficient gas code.
2) optimize often called functions. For example the map you showed could be rebuilt as a hash indexed by project.
2) if that still fails probably means you are running into a time quota since scripts can't run over 6minutes. If so you need to rewrite the code so it can process by parts and remember where it stopped so it can continue from there on next run. Run it manually until it completes all tasks or use a time trigger to run.