×

[PR]この広告は3ヶ月以上更新がないため表示されています。
ホームページを更新後24時間以内に表示されなくなります。



>> ユーザーガイド >> Best Practices


Best Practices

このドキュメントでは、スクリプトのパフォーマンスの向上に役立つベストプラクティスを説明します。


WWW GoogleStyle


他サービスへのコールの最小化

スクリプト内でJavaScriptの動作を使用すると、他のサービスを呼び出すよりもかなり高速です。どのようなものでもGoogle.Apps.Script内だけで達成することができれば、他サービス(スプレッドシート、Googleドキュメント、Googleサイト、翻訳、URLFETCHなどへの要求としてGoogleのサーバーまたは外部サーバーからデータをフェッチする)を呼び出すよりもはるかに高速な処理ができます。 これらのサービスのためのスクリプトの呼び出しを最小化する方法を見つけ出せば、スクリプトの実行速度はもっと速くなります。


バッチオペレーションの使用

普通スクリプトは、スプレッドシートのデータを読み取り、計算を実行した後、スプレッドシートへデータの結果を記述する必要があります。 Google.Apps.Scriptは、すでに組み込みの最適化を施しています。即ち、スクリプトが取得しそうなものを予めキャッシングで先読み取得したり、設定される可能性があるものを保存するためにキャッシングを取得して書き込むなどです。

読み書きを最小化することによって、組み込みのキャッシュを最大限に利用したスクリプトを書くことができます。読み取りや書き込みコマンドを交互に実行するのは遅くなる原因です。 スクリプトの実行速度を速くしたいと思うならば、1つのコマンドですべてを配列データを読み込み、配列内のデータに任意の操作を実行し、1つのコマンドでデータを書き出すことです。

ここに例がありますが、これに従ったり、利用はしないでください。
ギャラリー内のスプレッドシート・フラクタル・アートのスクリプトは、100×100スプレッドシートのグリッドに含まれるすべてのセルの背景色を次のコードで設定しています。


// 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 = getColor_(xcoord, ycoord); cell.offset(y, x).setBackgroundColor(c); xcoord += xincrement; } ycoord -= yincrement;
SpreadsheetApp.
flush(); }

スクリプトが非効率的なのです。つまり、100行と100列をループして、10,000セルに連続して書き込んでいます。ここでは、Google.Apps.Scriptのライトバックキャッシュが役立ちます。 ライトバックがすべての行の最後でフラッシュを強制使用してくれるからです。キャッシングがあるので、スプレッドシートへの呼び出しは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] = getColor_(xcoord, ycoord); xcoord += xincrement; } ycoord -= yincrement; } sheet.getRange(
1, 1, 100, 100
).setBackgroundColors(colors);

非効率的なコードでは、約70秒の実行時間ですが、効率的なコードではわずか1秒で実行されます!

もし、スプレッドシートのフラクタル・アートスクリプトを探しているなら、この例を簡単にするためにマイナーな変更を加えたことをご了承ください。 上記のように、公開されているコードではsetBackgroundRGBではなく、setBackgroundColorで呼び出しています。上のgetColor関数は下のように変更されました。


if
(iteration == max_iteration) {
return
'#000000'
; }
else
{
var
c
=
255
- (iteration *
5
);
c
=
Math.min
(
255
,
Math.max
(
0
,
c
));
var
hex =
Number
(
c
).toString(
16
);
while
(hex.length <
2
) hex = '0' + hex;
return
(
'#'
+ hex +
'3280'
"); }


キャッシュ・サービスの使用

スクリプトの実行間にリソースをキャッシュするためのキャッシュ・サービスを使用することができます。 データをキャッシュすることで、データをフェッチしなければならない回数の頻度を数倍以上減らすことができます。フェッチするために20秒かかるexample.comのRSSフィードがあって、平均的なリクエストでアクセスを高速化するシナリオを考えてみましょう。 このデータへのアクセスを高速化するCache.Serviceの利用法を下に示します。


function
getRssFeed() {
var
cache =
CacheService.
getPublicCache();
var
cached = cache.get(
"rss-feed-contents"
);
if
(cached !=
null
) {
return
cached; }
var
result =
UrlFetchApp.
fetch(
"http://example.com/my-slow-rss-feed.xml"
);
// takes 20 seconds to get
var
contents = result.getContentText(); cache.put(
"rss-feed-contents"
, contents,
1500
);
// cache for 25 minutes
return
contents; }

アイテムがキャッシュ内に存在しない場合には20秒待つ必要がありますが、その後のアクセスは、アイテムが25分後に期限切れになるまでの間、非常に高速になることが約束されます。



より敏感なUIのためのクライアント・ハンドラの使用

Google.Apps.ScriptでUIアプリケーションを書いているとき、サーバー側のイベントハンドラを使用せずにブラウザでのイベントをコールバック処理したい時間帯があります。 一例としては、初めてクリックされた後にボタンを無効にする必要のあるフォームです。この場合にはクライアント・ハンドラーを使う必要がありますし、アプリケーションは、Google.Apps.Scriptのサーバーへラウンドトリップを実行することなくブラウザでのイベントに応答できます。 以下のコードは、ユーザーがボタンをクリックした後にラベルが表示されるようにクライアント・ハンドラーを使用する方法を示します。


function
doGet() {
var
app =
UiApp.
createApplication();
var
button = app.createButton(
'Say Hello'
);
// Create a label with the 'Hello World!' text and hide it for now
var
label = app.createLabel(
'Hello World!'
).setVisible(
false
);
// Create a new handler that does not require the server. // We give the handler two actions to perform on different targets. // The first action disables the widget that invokes the handler // and the second displays the label.
var
handler = app.createClientHandler() .forEventSource().setEnabled(
false
) .forTargets(label).setVisible(
true
);
// Add our new handler to be invoked when the button is clicked
button.addClickHandler(handler); app.add(button); app.add(label);
return
app; }

2012-11-12


pageTOP