Upload
Download free for 30 days
Login
Submit Search
パフォーマンスの良いGASの書き方 Best Practice
Download as PPTX, PDF
20 likes
16,369 views
啓介 大橋
Atmosphere Tokyo 2014 Sandbox Session. gcp ja night × TokyoGAS Day2 GAS Session.
Technology
Read more
1 of 70
Download now
Downloaded 35 times
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Most read
21
22
23
24
25
26
27
28
Most read
29
30
31
32
33
34
Most read
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
More Related Content
PDF
人間と話す: Lean Customer Development (Lean Startup Update 2015)
Takaaki Umada
PDF
スクラムの知られざる勘所
Yoshifumi Tsuda
PDF
資金調達入門“以前” スタートアップが資金調達の前に考えること
Takaaki Umada
PDF
カスタマーサポートのことは嫌いでも、カスタマーサクセスは嫌いにならないでください
Takaaki Umada
PPTX
インセプションデッキ:やらないことリストとトレードオフスライダーをやってる話
Nobuhiro Yoshitake
PDF
ユーザに価値を届けるためのデータプラットフォームの考え方
Rakuten Group, Inc.
PPTX
スマホマーケットの概要と、マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)
Tokoroten Nakayama
PDF
Deep High Resolution Representation Learning for Human Pose Estimation
harmonylab
人間と話す: Lean Customer Development (Lean Startup Update 2015)
Takaaki Umada
スクラムの知られざる勘所
Yoshifumi Tsuda
資金調達入門“以前” スタートアップが資金調達の前に考えること
Takaaki Umada
カスタマーサポートのことは嫌いでも、カスタマーサクセスは嫌いにならないでください
Takaaki Umada
インセプションデッキ:やらないことリストとトレードオフスライダーをやってる話
Nobuhiro Yoshitake
ユーザに価値を届けるためのデータプラットフォームの考え方
Rakuten Group, Inc.
スマホマーケットの概要と、マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)
Tokoroten Nakayama
Deep High Resolution Representation Learning for Human Pose Estimation
harmonylab
What's hot
(20)
PDF
つくらない ものづくり ~明日からできるリーンスタートアップ~
圭 進藤
PDF
WebRTCで動かす“テレイグジスタンス”ロボット
NTT Communications Technology Development
PDF
リーンスタートアップにおける良い仮説、悪い仮説
Takaaki Umada
PDF
君にグロースハックはいらない
Takaaki Umada
PDF
Design Sprint Process / デザインスプリントの実際のプロセスについて
Takaaki Umada
PDF
LEANSTARTUPアンチパターン #devlove #leanstartup
Itsuki Kuroda
PDF
Character level CNN [CNNで自然言語処理]
tdualdir
PPTX
FA技術者のためのFABスペースの検討() .pptx
Tomoya Takahashi
PDF
新規事業・起業を妨げる「ビジネスモデル症候群」とは
Lean Startup Japan LLC
PPTX
講演1 Redmine導入のアンチパターン
Hidehisa Matsutani
PDF
TCP/IPプロトコルスタック自作入門
雅也 山本
PDF
ユーザの「価値」ってなんだろう?
Akihito Nagahama
PPTX
Spring 5に備えるリアクティブプログラミング入門
Takuya Iwatsuka
PDF
ユーザーストーリー駆動開発で行こう。
toshihiro ichitani
PDF
価値探索 -仮説検証の実践-
toshihiro ichitani
PDF
プロダクトオーナーは育成できるのか? - プロダクトオーナー祭り2016
Yusuke Suzuki
PDF
ユーザーストーリーの分割
Arata Fujimura
PDF
AWSで透過プロキシをやってみた
kuro kuro
PDF
チケットを利用したプロダクトの健康確認
kawahira kazuto
PDF
デットファイナンスの理解と実践 -銀行のベンチャー融資の論理を理解する-
Hitoshi Kakizawa
つくらない ものづくり ~明日からできるリーンスタートアップ~
圭 進藤
WebRTCで動かす“テレイグジスタンス”ロボット
NTT Communications Technology Development
リーンスタートアップにおける良い仮説、悪い仮説
Takaaki Umada
君にグロースハックはいらない
Takaaki Umada
Design Sprint Process / デザインスプリントの実際のプロセスについて
Takaaki Umada
LEANSTARTUPアンチパターン #devlove #leanstartup
Itsuki Kuroda
Character level CNN [CNNで自然言語処理]
tdualdir
FA技術者のためのFABスペースの検討() .pptx
Tomoya Takahashi
新規事業・起業を妨げる「ビジネスモデル症候群」とは
Lean Startup Japan LLC
講演1 Redmine導入のアンチパターン
Hidehisa Matsutani
TCP/IPプロトコルスタック自作入門
雅也 山本
ユーザの「価値」ってなんだろう?
Akihito Nagahama
Spring 5に備えるリアクティブプログラミング入門
Takuya Iwatsuka
ユーザーストーリー駆動開発で行こう。
toshihiro ichitani
価値探索 -仮説検証の実践-
toshihiro ichitani
プロダクトオーナーは育成できるのか? - プロダクトオーナー祭り2016
Yusuke Suzuki
ユーザーストーリーの分割
Arata Fujimura
AWSで透過プロキシをやってみた
kuro kuro
チケットを利用したプロダクトの健康確認
kawahira kazuto
デットファイナンスの理解と実践 -銀行のベンチャー融資の論理を理解する-
Hitoshi Kakizawa
Ad
Viewers also liked
(20)
PPTX
Google Apps Scriptとは? Add-onとは?
啓介 大橋
PPTX
Google Apps Script活用事例 Tokyo GAS 2013春
Junya Sato
PDF
Google apps scriptを使って業務改善
dcubeio
PDF
2014-02-20_Tokyo-GAS#5-社内活性化推進にGASを大活用した話
Humangas
PPTX
GCPUG Shonan GAS & GAE
啓介 大橋
PPTX
エンジニアのためのSpread Sheets講座101 - Google Apps Script -
Yuki Katada
PDF
1019 まぁ!簡単!google apps script入門
Tatsuya Kosuge
PDF
Qualité de l'air et hygiène industrielle
Maxime Archaqmbault
PDF
18.3 Каталог решений - Гражданское строительство EKF
Igor Golovin
PPTX
Real estate – real fact 2
Biswajit Das. "Relationship Beyond Advising."
PPTX
Vyklikajte si obyvateľov na mape vo svojom okolí
Peter Fusek
PDF
Campamentos de verano Barbadillo 2017 BURGOS
Veleta3000
PDF
Campamentos de verano Molino de Butrera 2017 Burgos
Veleta3000
PDF
Campamento de Verano Imagina 2017 Bedmar Jaen
Veleta3000
PDF
Campamentos de verano Molino de Butrera inmersion INGLES 2017 BURGOS
Veleta3000
PDF
TIM SA - podsumowanie 2016 roku
TIM SA
PDF
Xero in on your trade clients
Christian Newman (C.A.)
PDF
Checklist om je huwelijk tot in de puntjes te plannen
KBC Bank en Verzekeringen
PPTX
Junta Astorga 2017 03 28
Mauricio Lema
PDF
Campamentos de verano La Data 2017 Segovia
Veleta3000
Google Apps Scriptとは? Add-onとは?
啓介 大橋
Google Apps Script活用事例 Tokyo GAS 2013春
Junya Sato
Google apps scriptを使って業務改善
dcubeio
2014-02-20_Tokyo-GAS#5-社内活性化推進にGASを大活用した話
Humangas
GCPUG Shonan GAS & GAE
啓介 大橋
エンジニアのためのSpread Sheets講座101 - Google Apps Script -
Yuki Katada
1019 まぁ!簡単!google apps script入門
Tatsuya Kosuge
Qualité de l'air et hygiène industrielle
Maxime Archaqmbault
18.3 Каталог решений - Гражданское строительство EKF
Igor Golovin
Real estate – real fact 2
Biswajit Das. "Relationship Beyond Advising."
Vyklikajte si obyvateľov na mape vo svojom okolí
Peter Fusek
Campamentos de verano Barbadillo 2017 BURGOS
Veleta3000
Campamentos de verano Molino de Butrera 2017 Burgos
Veleta3000
Campamento de Verano Imagina 2017 Bedmar Jaen
Veleta3000
Campamentos de verano Molino de Butrera inmersion INGLES 2017 BURGOS
Veleta3000
TIM SA - podsumowanie 2016 roku
TIM SA
Xero in on your trade clients
Christian Newman (C.A.)
Checklist om je huwelijk tot in de puntjes te plannen
KBC Bank en Verzekeringen
Junta Astorga 2017 03 28
Mauricio Lema
Campamentos de verano La Data 2017 Segovia
Veleta3000
Ad
Similar to パフォーマンスの良いGASの書き方 Best Practice
(20)
PPTX
Tokyo r33 beginner
Takashi Minoda
PPTX
SQLチューニング入門 入門編
Miki Shimogai
PDF
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Masahiro Wakame
PDF
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
Yoshiyuki Asaba
PDF
React.jsでクライアントサイドなWebアプリ入門
spring_raining
PDF
GNU awk (gawk) を用いた Apache ログ解析方法
博文 斉藤
KEY
Aizu lt tokyo_luxion
Tomoaki Tamura
PDF
CoffeeScript
Ryo Maruyama
PDF
Favtile ~never write JS again~
hanachin
PDF
リーダブルコード 第二章
Yuto Ogi
PDF
RailsエンジニアのためのSQLチューニング速習会
Nao Minami
PDF
20171103 pg con-jp-lt-plpgsql
Toshi Harada
PDF
pg_bigmを用いた全文検索のしくみ(前編)
NTT DATA OSS Professional Services
PDF
Groovyで学ぶプロセス代数 #jjug
kyon mm
PDF
Enumはデキる子 ~ case .Success(let value): ~
Takaaki Tanaka
KEY
ライブラリにあらず! 〜Google Closure Toolsの事始め〜
Kazuya Hiruma
PDF
フロント作業の効率化
Yuto Yoshinari
PDF
PostgreSQL Unconference #26 No Error on PostgreSQL
Noriyoshi Shinoda
PDF
Chugoku db 17th-postgresql-9.6
Toshi Harada
PDF
Introduction to Spock
Takahiro Sugiura
Tokyo r33 beginner
Takashi Minoda
SQLチューニング入門 入門編
Miki Shimogai
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Masahiro Wakame
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
Yoshiyuki Asaba
React.jsでクライアントサイドなWebアプリ入門
spring_raining
GNU awk (gawk) を用いた Apache ログ解析方法
博文 斉藤
Aizu lt tokyo_luxion
Tomoaki Tamura
CoffeeScript
Ryo Maruyama
Favtile ~never write JS again~
hanachin
リーダブルコード 第二章
Yuto Ogi
RailsエンジニアのためのSQLチューニング速習会
Nao Minami
20171103 pg con-jp-lt-plpgsql
Toshi Harada
pg_bigmを用いた全文検索のしくみ(前編)
NTT DATA OSS Professional Services
Groovyで学ぶプロセス代数 #jjug
kyon mm
Enumはデキる子 ~ case .Success(let value): ~
Takaaki Tanaka
ライブラリにあらず! 〜Google Closure Toolsの事始め〜
Kazuya Hiruma
フロント作業の効率化
Yuto Yoshinari
PostgreSQL Unconference #26 No Error on PostgreSQL
Noriyoshi Shinoda
Chugoku db 17th-postgresql-9.6
Toshi Harada
Introduction to Spock
Takahiro Sugiura
More from 啓介 大橋
(6)
PPTX
App Dojo 2017 12月 - VUI in your app with Dialogflow -
啓介 大橋
PPTX
Dockerハンズオン
啓介 大橋
PPTX
Fusion360 meetup vol2 LT
啓介 大橋
PPTX
gcp ja night #27 Google Cloud Endpoints with Golang
啓介 大橋
PPTX
Tokyo gas #5_whatsnewinappsscript_公開用
啓介 大橋
PPTX
Dart flightschool cloudendpoint with dart
啓介 大橋
App Dojo 2017 12月 - VUI in your app with Dialogflow -
啓介 大橋
Dockerハンズオン
啓介 大橋
Fusion360 meetup vol2 LT
啓介 大橋
gcp ja night #27 Google Cloud Endpoints with Golang
啓介 大橋
Tokyo gas #5_whatsnewinappsscript_公開用
啓介 大橋
Dart flightschool cloudendpoint with dart
啓介 大橋
パフォーマンスの良いGASの書き方 Best Practice
3.
しょっちゅう 「XXXってサイトにある、 このサンプルコードを コピーして使ってるのだけど、 うちの会社のデータ件数だと タイムアウトしちゃうんです。 どうにか助けて下さい」 って言われて、毎回同じ内容で返答していて、 流石に疲れてきたので ちゃんとパフォーマンスの話をするからお前ら聞 いてろ下さい
6.
何やってる?
8.
@soundTricker318 http://goo.gl/ZpUOs
9.
http://www.bfts.co.jp
11.
Contents うそ… 私のスクリプト 遅すぎ? パフォーマンス の良い書き方 まとめ Start End
12.
う そ ・ ・ ・ 私 の ス ク リ プ ト 遅 す ぎ ・ ・ ・ ? http://www.pakutaso.com/
13.
公式ドキュメントにも 有りますが…
14.
• GASは書き方によって非常にパフォーマンスが変 わります。 うそ…私の…
15.
質問
16.
GASを使ったことがある人? 質問
17.
GASでサンプルコードを コピーして 使ったことがある人? 質問
18.
GASでサンプルコードを コピーして 社内のシステムとして 使っている人? 質問
19.
GASでサンプルコードを コピーして 社内のシステムとして 使ってタイムアウトした人? 質問
20.
• 巷のサンプルコードは比較的パフォーマンスが 悪いコードを書いている – 公式ドキュメントに書いてある書き方を守ってな いことが多い •
https://developers.google.com/apps- script/best_practices?hl=ja – 多分読みやすくするためにそうしているのだと思い ます。 サンプルコード…
21.
• パフォーマンスが悪いコードを使うと… –処理が終わらなくてタイムアウトする –なんかGASで作るの嫌になる –GAS遅い…と言いふらすようになる –困る サンプルコード
22.
パ フ ォ ー マ ン ス の 良 いス ク リ プ ト で い い 感 じ に http://www.pakutaso.com/
23.
パフォーマンスの良い スクリプトの書き方
27.
• Spreadsheetに色つける処理 –データは100×100セル –セルに「hoge」と書いてあったら黄色に –ないなら無職 今回の処理
28.
以下のコードをSpreadsheet上のGASで実行すれば作れます。 今回の処理 var arr =
["hoge", "fuga", "foo", "bar" , "bus", "あいうえお", "かきくけこ"]; function make() { var grid = []; var header = []; for (var c = 0; c < 100; c++) { header.push(c + 1); } grid.push(header); for (var r = 1; r < 101; r++) { var row = []; for (var c = 0; c < 100; c++) { row.push(arr[Math.floor(Math.random() * arr.length)]); } grid.push(row); } SpreadsheetApp.getActiveSheet().getRange(1, 1, 101, 100).clear().setValues(grid); }
30.
function badCode() { var
spreadsheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqS ZrCHMCRL-LEEqQK2n4yQO-o/edit#gid=0"); for(var row = 2; row <= 101; row++) { for(var col = 1; col <= 100; col++) { var value = spreadsheet.getSheetByName("シート1").getRange(row, col).getValue(); if (value == "hoge") { spreadsheet.getSheetByName("シート1").getRange(row, col).setBackground("yellow"); } } } } 悪いコード
32.
function goodCode() { var
spreadsheet = SpreadsheetApp.openById("1kzi8pXTZZrABgTGbJFqSZrCHMCRL-LEEqQK2n4yQO-o"); var backgrounds = []; var sheet = spreadsheet.getSheetByName("シート1"); var targetRange = sheet.getRange(2, 1, 100, 100); var values = targetRange.getValues(); for(var rowIndex = 0; rowIndex < values.length; rowIndex++) { var row = values[rowIndex]; var backgroundRow = []; for(var colIndex = 0; colIndex < row.length; colIndex++) { var value = row[colIndex]; if (value == "hoge") { backgroundRow.push("yellow"); } else { backgroundRow.push(""); } } backgrounds.push(backgroundRow); } targetRange.setBackgrounds(backgrounds); } 良いコード
33.
①悪い部分を知る
34.
• 遅い理由を知らないとどこを直してよいかわか りません – 実行トランスクリプトを使ってどこに時間がかかっ ているか確認する ①悪い部分を知る
35.
①悪い部分を知る
36.
②無駄なAPIアクセス を減らす
37.
• GASのService呼び出しは全てネットワーク経由で行 われるため、時間がかかります。 少しでも無駄な呼び出しはしないようにします。 ②減らす ネットワーク経由
38.
function badCode() { var
spreadsheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqS ZrCHMCRL-LEEqQK2n4yQO-o/edit#gid=0"); for(var row = 2; row <= 101; row++) { for(var col = 1; col <= 100; col++) { var value = spreadsheet.getSheetByName("シート1").getRange(row, col).getValue(); if (value == "hoge") { spreadsheet.getSheetByName("シート1").getRange(row, col).setBackground("yellow"); } } } } ②減らす
39.
function badCode() { var
spreadsheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqSZrCHMCRL- LEEqQK2n4yQO-o/edit#gid=0"); var sheet = spreadsheet.getSheetByName("シート1"); for(var row = 2; row <= 101; row++) { for(var col = 1; col <= 100; col++) { var range = sheet.getRange(row, col); var value = range.getValue(); if (value == "hoge") { range.setBackground("yellow"); } } } } ②減らす
40.
③なるべく1度にする
41.
• ②同じ原理でより呼び出し回数を減らすために getValues,setBackgrounds等のBatch Operationを 利用します。 ③1度にする 通常のgetValue() getValue() 1セルで1回アクセス
= 100×100回アクセス
42.
• ②同じ原理でより呼び出し回数を減らすために getValues,setBackgrounds等のBatch Operationを 利用します。 ③1度にする getValues() getValues) 100×100セルを1回アクセス
= 1回アクセス
43.
function badCode() { var
spreadsheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqSZrCHMCRL- LEEqQK2n4yQO-o/edit#gid=0"); var sheet = spreadsheet.getSheetByName("シート1"); for(var row = 2; row <= 101; row++) { for(var col = 1; col <= 100; col++) { var range = sheet.getRange(row, col); var value = range.getValue(); if (value == "hoge") { range.setBackground("yellow"); } } } } ③1度にする
44.
function badCode() { var
spreadsheet = SpreadsheetApp .openByUrl("https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqSZrCHMCRL-LEEqQK2n4yQO-o/edit#gid=0"); var backgrounds = []; var sheet = spreadsheet.getSheetByName("シート1"); var targetRange = sheet.getRange(2, 1, 100, 100); var values = targetRange.getValues(); for(var rowIndex = 0; rowIndex < values.length; rowIndex++) { var row = values[rowIndex]; var backgroundRow = []; for(var colIndex = 0; colIndex < row.length; colIndex++) { var value = range.getValue(); if (value == "hoge") { backgrounds.push("yellow"); } else { backgrounds.push(“"); } } backgrounds.push(backgroundRow); } targetRange.setBackgrounds(backgrounds); } ③1度にする
45.
• 大体のスクリプトはこの②、③を実施すればかなりパ フォーマンスが良くなります。
46.
④ 我に返る
47.
• 今回の処理はGASでやる必要がありません。 Sheetsの標準機能でやれることはそっちでやりましょ う – 今回のはセルの条件付き書式でできます。 –
新しいSpreadsheetはかなり細かい書式が使えるので 確認して下さい。 ④我に返る
49.
openByIdとopenByUrl
50.
• Spreadsheet,Forms自体などを取得する際に利用す るopenByIdとopenByUrlというメソッドが有ります。 • これらは比較的openByIdの方が速い –
IDはURL中のなんかよくわかない文字の部分がだいたいそれ openByIdとUrl https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqSZrCHMCRL-LEEqQK2n4yQO- o/edit#gid=0
51.
UiApp
52.
• UiAppを利用するときはなるべくClientHandler等ク ライアントサイドで動くイベントハンドラを活用する – UiAppのイベントハンドラは上記以外は全てサーバコールに なりおっそい –
適切にClientHandlerを利用するとかなりUXがよくなる UiApp
53.
HtmlService
54.
• HtmlServiceのパフォーマンスを良くする書き方の話も公式 ページに乗っている HtmlService
55.
• 基本的には – データの取得は非同期に行う •
doGet内などHtmlService呼び出し前に行わない – <html>,<head>,<body>タグなどは利用しない • cajaにより自動的に<caja-v-html>に変えられるので意味が無い • 変えられる分時間がかかるので使わない – Javascriptは最後に読み込む • <script>タグはファイルの一番末尾に書いておく • そのほうが画面が表示されてからクライアントサイドのJavascriptが実行される HtmlService
56.
• 大橋の感覚として – 外部のJSやCSSは使わない方が良い •
使う場合は<script src=“xxx”>とはせず、<script>ここにコピペ</script>して、埋 め込んでしまう。 • cajaはGoogle経由で外部JS、CSSを取得するので遅い – 画面遷移はJavascriptを使って一部分だけ切り替える • doGetを毎回すると遅い • SPA(Single Page Application)の様にJSで画面を切り替えたほうが速い • というより画面切り替えはしないほうが良い HtmlService
57.
どうしても遅い
58.
• どうしても遅い時は… – UrlFetchAppを利用してGoogle
APIを直接呼び出す。 – 直接呼び出すと、欲しいデータが1回の操作で取得できる場 合がある • CalendarAppやDriveAppなどでよくある • fieldsパラメータを利用すると不要なデータを取得しない ためネットワーク的にも良い どうしても遅い
59.
• どうしても遅い時は… – 本当にリアルタイム(わざわざ人が待って)でやる必 要があるか考える •
Triggerを利用して遅延実行 & 通知でも良いのではない か? • 朝一回実行すれば大丈夫なんじゃないか? • 実行タイミングは定期的でも良いのじゃないか? どうしても遅い
60.
• どうしても遅い時は… – ちゃんとGASで作って良いのか考える –
金で解決できるのならGAEやGCPを使ったほうが良 い – SpreadsheetをDBとして使っている場合もそう • 大量のデータなら場合によってはFusion Table もっと多いならBigQueryを検討 どうしても遅い
62.
まとめ
63.
GASで 困ったら
64.
#gasja
65.
Google Apps API
Japan http://goo.gl/FcU0C
66.
@soundTricker318 http://goo.gl/ZpUOs
67.
会社: http://goo.gl/CfVPf 個人: http://goo.gl/kVTv3
Editor's Notes
#30:
https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqSZrCHMCRL-LEEqQK2n4yQO-o/edit#gid=0
#32:
https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqSZrCHMCRL-LEEqQK2n4yQO-o/edit#gid=0
#49:
https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqSZrCHMCRL-LEEqQK2n4yQO-o/edit#gid=0
#62:
https://docs.google.com/spreadsheets/d/1kzi8pXTZZrABgTGbJFqSZrCHMCRL-LEEqQK2n4yQO-o/edit#gid=0
Download