Skip to content

Instantly share code, notes, and snippets.

@niwatako
Created June 19, 2018 12:18
Show Gist options
  • Select an option

  • Save niwatako/201e21a14289864fc1c43de2e4c2c78a to your computer and use it in GitHub Desktop.

Select an option

Save niwatako/201e21a14289864fc1c43de2e4c2c78a to your computer and use it in GitHub Desktop.
UIKitによるパフォーマンス向上方針 #roppongiswift #CodePiece
### @stzn3 UIKitによるパフォーマンス向上方針
大きく分けて3つあったが、最初とかぶったのでそこは端折ります。
都内某所の受託開発会社勤務、本名は珍しいので秘密です。
Swift, Android(kotlin), JS, C#, Java, PHP。。。など
Session 202/219/220/407 より
Scrolling、Memory, Autolayout のパソーマンスが改善されている
#### Scrolling
Scrollingは何もしなくても改善されている。スクロールで画面がかくつくフレーム落ちがある。CellForRowAtやLayoutSubviewsで重い処理をしているとそこで引っかかる。iOS10でPrefetchが導入されて、セルを表示するより前にデータを取ることで、CPUのスパイク、一時的使用の急増を防いでいる
書いたから呼んでね
【Swift】この時期だから見直すiOS10の新機能 UITableView UICollectionViewの改善とPre-Fetching API
https://qiita.com/shiz/items/66ae7e772d315dadf7d4
Prefetchがかぶるとスパイクが結局起きてしまっていた
iOS12では、Prefetdhがかぶらないようにスケジューリングが可能になった
でもまだある。何もしていないときに急にフレームが落ちる事がある。何もしていなかったからこその、消炎絵モードからのCPUの立ち上がりに時間がかかってしまうのが問題。
その改善のためにramp up の改善が行われた。CPUの立ち上がりの指示を事前にControllerに支持することで必要なCPU料を推測して立ち上げに備える。それでCPU使用にまに合うようになった。
#### Memory
Memory Buffer:連続したメモリ領域
ImageBufferというのがある。
ある画像を表現したBufferで各要素が1ピクセルを表す。画像のデータと同じサイズになる。
FrameBuffer
Image Bufferの一種でViewのレンダリング結果を保持している。フレームレートに合わせて更新している。
DataBuuffer
画像データのメタデータ画像を保持している。画像サイズや圧縮形式を保持。
Backing Store: デコードしたImageBufferを内部に保持する。保持する分メモリを消費する。iOS12から画像に使われている色などからサイズを自動計算するようになった。
白黒でもカラーでも同じだけ確保されていたが、iOS12からは、たとえば色付きで2.2MBのやつも白黒は275kbで済むようになりました。
UIImage、UIImageViewは何をしているのか。
UIImageが画像をロードしてImageBufferにデコードしている。
デコードにはCPUを使う。デコードしたらImageBufferになるので、永続的にメモリアロケーションを要する。
保持するデータを少なくするには?
Bufferに保持されるデータサイズを事前に小さくしてメモリ圧迫を防ぐ。DownSampling。
キャッシュするデータのリュを、Decodeと同時に保存するのではなくて、保存するタイミングをずらすことで、小さくしたデータを保存するようにしている。
サンプルで、ImageViewをひたすら読み込むアプリの例、492MB使いました。
これをdownSamplingします。50.1MBに減りました。
画像が重くて困ったら思い出してください。
発表資料に出てきていますのでそちらからご確認ください。
#### 画像リソース
ImageAssetsを使うのが推奨、名前が検索に最適化され、キャッシュが最小、インストールデバイスに合わせてサイズが最適化される、Vector Artwork が活用される
#### CustomUIViewは使うべきか
drawメソッドを上書きするようなカスタムViewはやめたほうがいい
UIView.drawはBackingStoreを自動で利用する。ViewのPixcelサイズがBackingStoreの大きさ
iOS12からWideColorがデフォルトでtrue
CALayer.ContentsFormatでWide ColorをOffにしていた場合、iOS12ではこれを使うといろいろうまく動かないので注意
drawをつかわない: backgroundColorは直接Frame Bufferに書き込める
UIImageViewで代用できないか、他にもBackingStore使わない方法を考える
MaskingView
(筆記おいつかない)
UIImageはモノクロの画像をカラーにできる、tintColorを使う。FrameBufferに直接書き込まれるのでメモリ節約。Image SetでTempleteImageを選ぶやつ。
UILあべlではなるべくモノクロカラーをリユする。
UIImageViewは最適化されているので使うことでUIViewよりメモリを抑えることができる
UIGraphicsImageRendererを使う
ImageBufferの最適化
WideColor自動サポート、prefer.....←depricatedになってて謎
Autolayoutのパフォーマンスが改善されました
11.4と12.0で試したら、まぁ若干改善されたかなという感じではあったけど、大幅かというと疑問。
WindowにインナーオブジェクトといてEnginが入っている。View追加されたりすると、Viewは計算前の制約Equationを作る。Acriveになったらこの方程式のような状態のものをEnginに渡す。
そこで相対値や、最低値、最大値などを計算する。
計算されたものは、Variableという計算結果変数に入れられる。
ViewはVariableを参照してEnginに対して変更があるか聞いて、変更があればViewはsuperView.setNeedsLayoutを呼ぶ。
変更を受けた親は、Layoutを親から子に伝播する。LayoutSubviewsの中では、Viewが値なんだっけとEnginに確認、返された値を下にSubviewsに位置大きさを指示する。
updateconstraintsで制約を変えるとこれを繰り返し行うことになる。
`Enginはキャッシュであり制約関係の追跡者である。` 何度も設定しなくてもいいということかな?
必要なものにだけ必要な制約をつけましょう。
削除して追加の繰り返し離し、intrinsicConstentsizeがいらない場合はオーバーライドして UIView.noIntrinsicMetricを使うと処理を省略できる。
UIKitは見えないところで進化しています。意識すると改善できる、間違えると悪化する可能性もある。
用法用量を守って正しく使いましょう。
@niwatako
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment