こんにちは。
Sleipnir for Mac 開発担当の宮本です。
Sleipnir for Mac は 1/24 にデザインを刷新したメジャーアップデートをしました。
実はデザイン面の変更だけでなく、実装を大幅に改善しており、体感できるレベルでパフォーマンスが上がっています。
今回は、その Sleipnir for Mac でパフォーマンスを大幅に向上させるために取り組んだことを紹介します。
1. できるだけ別スレッドで
ネットワーク通信のような処理であれば、自然と別スレッドで実行するのですが、ちょっと遅いかもぐらいであればメインスレッドでやってしまいます。もしその処理が0.1秒、0.05秒ぐらいでもかかっていれば、使っていて引っ掛かりを感じてしまいます。
体感速度を上げるには、こういった処理をどれだけ別スレッドに回せるかが大事になってきます。
■ テキストサイズの計算
自前でレイアウトをする場合、テキストサイズの計算が必要になります。1箇所ぐらいであればそれほどでもないのですが、同時に10,20ぐらい計算が走る場合は別スレッドでやるべきです。4,5年 Objective-C で開発をしている経験では、あまり重そうな処理をしていないのに遅いところはだいたいテキストサイズの計算が原因です。
Sleipnir for Mac では Site Updates なんかが別スレッドでテキストサイズを計算してからメインスレッドでレイアウトしてます。
■ Core Data のフェッチやインサート
Core Data でのスレッドの扱いが面倒なので、できればメインスレッドで動かしたいですが、ちょっと値を取り出したい場合のフェッチや、UI に影響を与えないインサートに関しては別スレッドに回すべきです。Sleipnir for Mac であれば履歴の追加などがそれにあたります。
■ イメージのロードとサムネイルの生成
用意できるまではデフォルトの画像を表示しておいて、出来上がりしだいメインスレッドで反映させます。Sleipnir for Mac のタブバーや TiledTab の画像はこの方法で作ってます。
2. 必要になるまで作らない
あるクラスで生成して、dealloc 時に破棄するようなオブジェクトは awakeFromNib や init などで作ってしまいがちです。生成時にほとんど何もしないのであればいいのですが、時間が少しでもかかる場合は、初めて必要になった時に生成も一緒にやってしまうほうがいいです。ViewController の生成であれば、View にアクセスしない限りはロードされないので、作るだけなら問題ありません。
また、TiledTab などのコレクション系の UI を作る場合、簡単に実装するために見えていない View もついつい生成してしまいます。この場合、スクロールするたびに生成するようにして、いくらデータが増えてもほぼ同じパフォーマンスを出せるようにするべきです。
3. 起動時の処理を少なく
iOS でも Mac でも applicationDidFinishLaunching での処理を少なくすることで起動を速くできます。起動中ずっと必要なオブジェクトでも、最初のウインドウを表示するまでに必要ない場合は、生成を遅らせましょう。performSelector:withObject:afterDelay: するか、ウインドウを表示した段階で処理することで実現できます。
4. 呼び出し回数を少なく
一度呼び出すだけでいいところを二度呼び出していれば、2倍速くすることができます。
- ■ Sleipnir のタブバー
開発初期の実装では、タブが追加された時と、タブが切り替わった時にレイアウトしていたので、新規タブされた時に2度レイアウトが走ってました。
そこで、タブが切り替わった時になぜ切り替わったかの情報をのせて、タブが追加された時の切り替わりでは、レイアウトを無視するようにしました。
5. View を少なくする
iOS で言えば、UIView はイベント処理ができる CALayer です。イベント処理が必要でない場合は、その分だけ無駄なわけです。これが Mac の NSView にになると UIView に比べてもっともっと処理が増えます。描画だけが必要なら、drawRect: してしまうか、CALayer を貼るとパフォーマンスを上げられます。
6. 文字列検索は CFStringFind を使う
NSString の rangeOfString: とちょっと書き方が違うぐらいで、ほぼ同じようにつかえます。文字列検索が遅いと思う場合は試してみてください。
7. 定期的にチェック
少しずつパフォーマンスが悪くなっていくアプリを使っていると、遅くなったことに気づきにくいです。気づいた頃にはかなり遅くなっていることも少なくありません。最近は、Instruments の Timer Profiler で定期的にチェックするようにしています。
以上が、Sleipnir for Mac でパフォーマンスを上げるためにしたことです。まだまだ、直せるところはあるので、今後もパフォーマンス改善に努めていきます。