Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Swift Macroでメソッドの実行時間を計測できるようにしてみた
Search
Ryu-nakayama
October 25, 2024
Programming
240
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Swift Macroでメソッドの実行時間を計測できるようにしてみた
2024/10/25 mobile.stmn #8の登壇資料です
Ryu-nakayama
October 25, 2024
More Decks by Ryu-nakayama
See All by Ryu-nakayama
iOS機能開発のAI環境と起きた変化
ryunakayama
0
230
日本だけで解禁されているアプリ起動の方法
ryunakayama
0
420
iOSアプリでフロントエンドと仲良くする
ryunakayama
0
150
「ジェン文字」使ってますか?
ryunakayama
0
78
Health Kit × Foundation Models でAIコーチを作ってみた
ryunakayama
0
360
iOSの画面の状態のアレコレを調査してみた
ryunakayama
0
100
作文ツール(Writing Tools)をアプリから制御する
ryunakayama
0
64
iOSアプリで測る!名古屋駅までの 方向と距離
ryunakayama
0
310
「ジェン文字」をアプリ内で使ってみよう
ryunakayama
0
210
Other Decks in Programming
See All in Programming
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
0
190
関数型プログラミングのメリットって何だろう?
wanko_it
0
170
OS アップデート対応の取り組み方がもっと共有されてほしい
andpad
0
110
フィードバックで育てるAI開発
kotaminato
1
110
act1-costs.pdf
sumedhbala
0
210
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.4k
吝嗇家のためのAI活用 / AI development for miser - ChatGPT + Issue Driven Development
tooppoo
0
180
トークンをケチるな、設計しろ:GitHub Copilotを賢く使うコンテキスト戦略
ochtum
0
310
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
16
3.3k
JAWS-UG横浜 #102 AWSサ終供養LT会 成仏できない AWS サービスたち 〜本日、三体供養します〜
maroon1st
0
110
技術記事、 専門家としてのプログラマ、 言語化
mizchi
14
7.4k
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.7k
Featured
See All Featured
Paper Plane (Part 1)
katiecoart
PRO
0
9.6k
The untapped power of vector embeddings
frankvandijk
2
1.8k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
WCS-LA-2024
lcolladotor
0
680
Navigating Weather and Climate Data
rabernat
0
320
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
200
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6k
Six Lessons from altMBA
skipperchong
29
4.3k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
560
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
350
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
230
Transcript
Swift Macroでメソッドの実行時間を 計測できるようにしてみた CP本部 iOSアプリ開発部 中山 龍 2024年10月25日 mobile.stmn #8
自己紹介 中山 龍 (なかやま りゅう) • 株式会社kubell ◦ 新卒2年目のiOSエンジニア(22) ◦
「Chatwork」アプリの開発を担当 • 愛知県在住 ◦ 日曜に引っ越しをし、熱田区民 → 中区民に @ryu_develop
今更ながらSwift Macro (Swift Syntax) で遊んでみたのでその内容を紹介します
注意事項 • 本スライドの内容や登場するコードは趣味で作成しているものであり、業 務で扱っているプログラム・プロダクト・開発環境とは一切関係ありません • 「試しに触ってみた」という趣旨の紹介であり、必ずしもベストプラクティス を紹介しているわけではありません • スライド・GitHubに掲載しているコードも完璧な動作を保証するものでは ありません
01 | Swift Macroとは
Swift Macroとは? - Swiftプログラム内でコンパイル時にコードを自動生成したり、変換したりする ための機能 - Swift5.9以降で導入 - @〜〜〜 や
#〜〜〜といった感じで使用する 参考: Swiftマクロの書き方 - WWDC2023 代表的なものだと - Observation (@Observable) - SwiftUIのプレビュー (#Preview) 強力で便利な機能だが、可読性などの観点から乱用しないように注意が必要!
02 | 実行時間を計測するMacroを書いてみた
完成イメージ 8 @(自作のMacro) 型に対して自作のMacroを付ける 型のメソッドを実行した時に、 実行したメソッド と時間 が表示され る
コードが見づらい部分も多いと思うので... https://github.com/Ryu-nakay/measuri ng-method-execution-time-macro.git コードを中心に説明をすると字が小さくて見づらいことが 想定されるので、文字中心で説明します〜!🙏 コードは必要に応じてGitHubをご覧ください → (スライドはイベント終了後に公開するので、その際に照ら し合わせながら見ていただくでも問題なし) 会場の様子を見ながら、必要そうであればライブコーディング風にお見せします
1. 単体のメソッドを計測可能にする
ルール: メソッドの実行時間の計測 メソッドの 処理開始時の時刻 と 処理終了時の時刻 の差を実行時間とする 11 終了時刻 開始時刻
実行時間 10時 20分 40秒 10時 20分 30秒 10秒 ざっくりとしたイメージ
ルール: メソッドの実行時間の計測 メソッドの 処理開始時の時刻 と 処理終了時の時刻 の差を実行時間とする 12 終了時刻 開始時刻
実行時間 10時 20分 40秒 10時 20分 30秒 10秒 ざっくりとしたイメージ メソッドの開始時刻と終了時刻を取得し、その差を 出力すればよさそう!
ルール: メソッドの実行時間の計測 -作成するMacroのイメージ- 13 展開 @自作Macro @自作Macro (今回、defer文などは考慮していません )
ルール: メソッドの実行時間の計測 -計測に使用する便利な型- 14 計測の事前準備として、MeasureTimeLoggerという型を作りました - 初期化時に時刻でプロパティを初期化 - stop呼び出しで実行時間の計算とprint出力
ルール: メソッドの実行時間の計測 -計測に使用する便利な型- 15 展開 BodyMacro を使ってメソッドの中身を書き換えよう!
2. BodyMacroを実装する
実装 -型の準備- BodyMacroに準拠した型を定義し、expansionメソッドを準備します // 実装
実装 -expansionメソッドの中身- 1. Macroが付与されている対象がメソッド構文であることを確認し、そのメソッドの中身の構文を取得する (できなければ何もイジらずに return) 2. メソッドの中身の構文を 1行ずつ取り出し、その行が return構文だった場合には、その前に
`measureTimeLogger.stop()` をくっつける return構文が存在していなかった場合には、メソッドの中身の構文の末尾に `measureTimeLogger.stop()`をくっつ ける 3. メソッドの中身の先頭に `let measureTimeLogger = MeasureTimeLogger()`をくっつける
実装 -expansionメソッドの中身- 1. Macroが付与されている対象がメソッド構文であることを確認し、そのメソッドの中身の構文を取得する (できなければ何もイジらずに return) 2. メソッドの中身の構文を 1行ずつ取り出し、その行が return構文だった場合には、その前に
`measureTimeLogger.stop()` をくっつける return構文が存在していなかった場合には、メソッドの中身の構文の末尾に `measureTimeLogger.stop()`をくっつ ける 3. メソッドの中身の先頭に `let measureTimeLogger = MeasureTimeLogger()`をくっつける 1. Macroが付与されている対象がメソッド構文であることを確認し、そのメソッドの中身の構文を取得する (できなければ何もイジらずに return) - expansionメソッドの引数 declaration が FunctionDeclSyntax型に変換できるかで判定する - FunctionDeclSyntax.body?.statements がメソッドの中身の構文となる
実装 -expansionメソッドの中身- 1. Macroが付与されている対象がメソッド構文であることを確認し、そのメソッドの中身の構文を取得する (できなければ何もイジらずに return) 2. メソッドの中身の構文を 1行ずつ取り出し、その行が return構文だった場合には、その前に
`measureTimeLogger.stop()` をくっつける return構文が存在していなかった場合には、メソッドの中身の構文の末尾に `measureTimeLogger.stop()`をくっつ ける 3. メソッドの中身の先頭に `let measureTimeLogger = MeasureTimeLogger()`をくっつける - 1.で取得した『メソッドの中身の構文』を 1行ずつ取り出し、その型が ReturnStmtSyntaxかどうか でreturn構文を判定することができる - 元の構文 + 処理終了時の構文となったものが出来上がる 2. メソッドの中身の構文を 1行ずつ取り出し、その行が return構文だった場合には、その前に `measureTimeLogger.stop()` を付け加える return構文が存在していなかった場合には、メソッドの中身の構文の末尾に `measureTimeLogger.stop()`を付け加 える
実装 -expansionメソッドの中身- 1. Macroが付与されている対象がメソッド構文であることを確認し、そのメソッドの中身の構文を取得する (できなければ何もイジらずに return) 2. メソッドの中身の構文を 1行ずつ取り出し、その行が return構文だった場合には、その前に
`measureTimeLogger.stop()` をくっつける return構文が存在していなかった場合には、メソッドの中身の構文の末尾に `measureTimeLogger.stop()`をくっつ ける 3. メソッドの中身の先頭に `let measureTimeLogger = MeasureTimeLogger()`をくっつける 3. メソッドの中身の先頭に `let measureTimeLogger = MeasureTimeLogger()`を付け加える - 2.で作成した『元のメソッドの構文 + メソッド終了時の構文』の先頭にメソッド開始時の構文を付け 加えてreturnする
最終的なBodyMacroの実装 https://github.com/Ryu-nakay/measuri ng-method-execution-time-macro.git
実装 あとは、Macroを使えるようにするために各所に記述を追加し ...
実装 無事に時間計測ができるようになりました!
Macro展開時 ↑ Macroを展開すると計測開始・終了の処理が付け加えられ ていることがわかります
一括でつけたい 無事に計測可能になったものの... 毎回メソッドに付与していくの面倒だなぁ... 一括で型のメソッド全てを計測可能にできないかな?
再掲: 完成イメージ 27 @(自作のMacro) 型に対して自作のMacroを付ける 型のメソッドを実行した時に、 実行したメソッド と時間 が表示され る
こうすればいける? 28 @(自作のMacro) Macroを展開 メソッド単体での計測はできるので、型に対してMacroをつけた時に右のように各 メソッドに @MeasureTimeが付与されるようにすればいいのでは?
3. MemberAttributeMacroを実装する
実装 -最終的なMemberAttributeMacroのコード- さっきと比べるとすごくシンプル!
実装 -最終的なMemberAttributeMacroのコード- expansionを実装 memberがメソッドの 構文であるかを判定 メソッドの構文であるものに対して @MeasureTimeを付与
実装 -最終的なMemberAttributeMacroのコード- expansionを実装 memberがメソッドの 構文であるかを判定 メソッドの構文であるものに対して @MeasureTimeを付与 これだけで完成!
実装 あとは、Macroを使えるようにするために各所に記述を追加し ...
使ってみる 34 Macroを展開 型に @TimeMeasureable を付けることで、その型が持つメソッドに @MeasureTimeを付与できました!
まとめ
まとめ・感想 36 まとめ • メソッド単体で計測可能することができる @MeasureTime を実装した ◦ BodyMacro •
型のメソッドに @MeasureTimeを付与できる @TimeMeasureableを実装した ◦ MemberAttributeMacro 感想 • 「Swift Macro / Swift Syntaxって専門知識がないと難しそう」と食わず嫌いしていたが、実際に 触ってみると動くものを作れるぐらいにはできた • Swift AST Explorer が便利すぎた ◦ Syntaxの深い知識を持ち合わせていなくても構造や型を調べられた • 本当は「Swiftのコードから実行された処理のシーケンス図を出力したい」というモチベーションで 始めたので、今後実現できたらと ...
働くをもっと楽しく、創造的に 37