本文档列出了有助于您提升脚本性能的最佳实践。
尽量减少对其他服务的调用
在脚本中使用 JavaScript 操作要比调用其他服务快得多。与需要从 Google 服务器或外部服务器提取数据的调用(例如对 Google 表格、Google 文档、协作平台、Google 翻译、UrlFetch 等的请求)相比,您可以在 Google Apps Script 中完成的任何操作的速度都会快得多。如果您能找到方法来尽量减少脚本对这些服务的调用次数,脚本的运行速度就会更快。
考虑通过共享云端硬盘开展协作
如果您要与其他开发者共同处理脚本项目,可以通过共享云端硬盘协作处理 Apps 脚本项目。共享云端硬盘中的文件归群组所有,而非个人。这样可以更轻松地开发和维护项目。
使用批量操作
脚本通常需要从电子表格中读取数据、执行计算,然后将数据结果写入电子表格。Google Apps 脚本已经提供了一些内置优化功能,例如使用预读缓存来检索脚本可能获取的内容,以及使用写入缓存来保存可能设置的内容。
您可以编写脚本,通过尽量减少读取和写入次数,最大限度地利用内置缓存。交替使用读取和写入命令的速度较慢。如需加快脚本的速度,请使用一条命令将所有数据读取到数组中,对数组中的数据执行任何操作,然后使用一条命令将数据写出。
下面是一个示例,但不应遵循或使用。以下代码会用于设置一个 100 x 100 的电子表格网格中每个单元格的背景颜色。它使用名为 getColorFromCoordinates()
(此处未显示)的函数来确定每个单元格应使用哪种颜色:
// DO NOT USE THIS CODE. It is an example of SLOW, INEFFICIENT code.
// FOR DEMONSTRATION ONLY
var cell = sheet.getRange('a1');
for (var y = 0; y < 100; y++) {
xcoord = xmin;
for (var x = 0; x < 100; x++) {
var c = getColorFromCoordinates(xcoord, ycoord);
cell.offset(y, x).setBackgroundColor(c);
xcoord += xincrement;
}
ycoord -= yincrement;
SpreadsheetApp.flush();
}
该脚本效率不高:它会循环遍历 100 行和 100 列,并连续写入 10,000 个单元格。Google Apps 脚本回写缓存会有所帮助,因为它会在每行末尾使用刷新强制回写。由于缓存,对电子表格的调用次数只有 100 次。
不过,通过批量调用,可以使代码变得更加高效。下面的代码重写会将单元格范围读取到名为“colors”的数组中,对数组中的数据执行颜色分配操作,并将数组中的值写入到电子表格中:
// OKAY TO USE THIS EXAMPLE or code based on it.
var cell = sheet.getRange('a1');
var colors = new Array(100);
for (var y = 0; y < 100; y++) {
xcoord = xmin;
colors[y] = new Array(100);
for (var x = 0; x < 100; x++) {
colors[y][x] = getColorFromCoordinates(xcoord, ycoord);
xcoord += xincrement;
}
ycoord -= yincrement;
}
sheet.getRange(1, 1, 100, 100).setBackgrounds(colors);
低效的代码需要大约 70 秒才能运行完毕。高效代码只需 1 秒即可运行!
避免在界面密集型脚本中使用库
库是一种方便的重复使用代码的方式,但会略微增加启动脚本所需的时间。对于运行时间相对较长的脚本(例如用于清理 Google 云端硬盘文件的实用程序脚本),这种延迟不会明显,但对于会重复进行短时运行的 google.script.run
调用的客户端 HTML 服务界面,延迟会影响每次调用。因此,在插件中应尽量少用库,并且您可能需要避免在执行大量 google.script.run
调用的非插件脚本中使用库。
使用缓存服务
您可以使用缓存服务在脚本执行之间缓存资源。通过缓存数据,您可以减少提取数据的次数或频率。假设您有一个位于 example.com 的 RSS Feed,其提取时间为 20 秒,并且您希望加快平均请求的访问速度。以下示例展示了如何使用缓存服务加快对此类数据的访问速度。
function getRssFeed() {
var cache = CacheService.getScriptCache();
var cached = cache.get("rss-feed-contents");
if (cached != null) {
return cached;
}
// This fetch takes 20 seconds:
var result = UrlFetchApp.fetch("http://example.com/my-slow-rss-feed.xml");
var contents = result.getContentText();
cache.put("rss-feed-contents", contents, 1500); // cache for 25 minutes
return contents;
}
现在,虽然如果项不在缓存中,您仍然需要等待 20 秒,但后续访问将非常快,直到该项在 25 分钟后从缓存中过期。