4

何千人もの iOS 開発者の悲痛な内臓がすでに聞こえてきます。

いいえ、私は初心者ではありません。

複数のビューを持つよりも -drawRect の方がUITableViewのパフォーマンスが速いのはなぜですか?

合成操作が GPU で行われることを理解しています。ただし、合成は 1 回限りの操作です。レイヤーがメモリにコミットされると、GPU の観点から見ると、ビュー内外に変換されるキャッシュされたバッファーと何ら変わりはありません。これを drawRect で Core Graphics を使用する場合と比較してください。これは、CPU で不明な量の操作を使用してピクセルを生成し、最終的に CALayers にキャッシュされます。とにかくすべてがキャッシュされてフラット化された場合の違いは何ですか?

また、セルの再利用を適切に処理している場合は、-cellForRowAtIndexPath を呼び出すたびにビューを再生成する必要はありません。実際、状態データ (フォント、フォント サイズ、テキストの色、属性など) を UIView/CALayer オブジェクトによってキャッシュすると、-drawRect 中に常に再作成するよりもパフォーマンスが向上する場合があります。

なぜdrawRectが熱狂するのか? 誰かが私に指針を与えることができますか?

4

3 に答える 3

5

最適化について話すときは、特定の状況と条件および制限を提供する必要があります。最適化はすべてマイクロ管理に関するものだからです。そうでなければ、それは無意味です。

あなたのより速いの基礎は何ですか?どのように測定しましたか?数字は何ですか?

たとえば、no-opまたは非常に単純な-drawRect:方が高速になる可能性がありますが、常にそうなるとは限りません。

CAの内部設計もわかりません。だからここに私の推測があります。

静的コンテンツの場合

あなたの描画コードが絶えず呼び出されているのは奇妙です。描画結果をキャッシュし、メッセージCALayerを送信するまで再度描画しないためです。setNeedsDisplayセルのコンテンツを更新しない場合は、単一のビットマップレイヤーと同じです。合成コストを必要としないため、複数の合成レイヤーよりも高速である必要があります。同時にすべてのプールに存在するのに十分な少数のセルのみを使用している場合は、更新する必要はありません。最近のモデルではRAMが大きくなるため、最近のモデルで発生する可能性が高くなります。

動的コンテンツの場合

常に更新されている場合は、実際に自分で更新していることを意味します。したがって、レイヤー合成バージョンも絶えず更新される可能性があります。これは、フレームごとに再度合成されていることを意味します。複雑で大きいため、速度が低下する可能性があります。複雑で大きく、重複する領域が多い場合は、速度が低下する可能性があります。どの領域を無視してもよいかを判断できない場合、CAはすべてを厳密に描画すると思います。あなたが描くかどうかを選択できるのとは異なります。

実際の描画はCPUで行います

ビューを多くのレイヤーの純粋な構成として構成した場合でも、最終的には各サブレイヤーを描画する必要があります。また、コンテンツの描画はGPUで行われることが保証されていません。たとえばCATextLayer、CPUで自分自身を描画していると思います。(現在のモバイルGPUでポリゴンを使用してテキストを描画することは、パフォーマンスの観点からは意味がないため)また、一部のフィルタリング効果もあります。その場合、全体的なコストは同様になり、さらに合成コストが必要になります。

CPUとGPUの負荷のバランスが取れている場合

レイヤーまたは直接OpenGL描画が多すぎるために、GPUが高負荷で非常にビジー状態の場合、CPUがアイドル状態になっている可能性があります。アイドル状態のCPU時間内にCGの描画を実行できる場合は、GPUにより多くの負荷をかけるよりも高速になる可能性があります。

それらのどれもあなたの場合ではありませんか?

あなたのケースが上記の状況のいずれでもない場合、私は本当にCGコードがCA構成よりも速く描画されることを確認して確認したいと思います。ソースコードを添付してください。

于 2012-09-09T19:44:34.657 に答える
0

ここでは会話の半分しか見ていませんので、誤解している可能性があります。私の最近のCALayerレンダリングの最適化の経験に基づいて、そしてAppleが最適化されると期待するものを最適化する(しない)方法を調査しています...

とにかくすべてがキャッシュされてフラット化された場合の違いは何ですか?

Appleは、レイヤーごとに個別のGPU要素を作成することになります。レイヤーがたくさんある場合は、GPU要素がたくさんあります。drawRectが1つある場合、要素は1つだけです。Appleは、それらが可能である(そしておそらく「すべきである」)場合でも、それらを平坦化しないことがよくあります。

多くの場合、「たくさんの要素」は問題ではありません。しかし、それらが大きくなった場合...または十分な数がある場合...またはOpenGLに適したサイズではない場合...そして(以下を参照)GPUではなくCPUに格納されると、事態は厄介になり始めます。注意:私の経験では:

  • 「十分」:メモリ内で40以上
  • 「大」:100x100ポイント(200x200網膜ピクセル)

GPU要素/バッファ用のAppleのコードは、ほとんどの場所で十分に最適化されていますが、いくつかの場所では非常に不十分に最適化されています。パフォーマンスの低下は、崖から降りるようなものです。

また、セルの再利用を適切に処理している場合は、-cellForRowAtIndexPathを呼び出すたびにビューを再生成する必要はありません。

あなたは「適切に」と言いますが、... IIRC Appleのドキュメントは人々にそうしないように言っています、彼らはより単純なアプローチ(IMHO:弱いドキュメント)を選び、代わりにすべての呼び出しですべてのサブビューを再入力します。どの時点で...どれだけ節約できますか?

ついに:

... UIViewの作成コストが大幅に削減されるiOS6では、このすべてが変更されませんか?(私はまだそれをプロファイリングしていません、ただ他の開発者からそれについて聞いています)

于 2012-08-13T15:21:20.117 に答える
0

GPU と CPU ベースのレンダラーを行ったり来たりすると、プログラムは大量のピクセル データを簡単に移動および変換することになります。

また、多くのレイヤーは大量のメモリを消費する可能性があります。

于 2012-08-10T22:09:31.480 に答える