2

私のデータ視覚化アプリでは、再描画中に大きなメモリ消費スパイクが発生します (drawRect をトリガーする setNeedsDisplay)。現在、データ プロットを格納するビュー全体を再描画しています。このビューは、デバイスのディスプレイよりもはるかに大きくなっています。

現在の素朴なアプローチではなく、CoreGraphics に各要素を描画するのに十分なメモリを割り当て (各要素はデバイスの表示よりもはるかに小さい小さな長方形のブロックです)、完了したらメモリを解放するように指示する方法はありますか?

前もって感謝します。

-ダグ

更新 12 月 8 日午前 8 時 28 分 EST

関連するコードと説明文を次に示します。ObjectAlloc、Memory Monitor、および Leaks インストゥルメントを実行しているインストゥルメントを実行しています。私が持っている唯一のメモリリークは、NSOperationQueueがメモリを解放していないことに関係しています。これはマイナーであり、関連性はありません。

アーキテクチャ的には、このアプリは、検査するヒトゲノムに沿った興味深い場所のリストを含む tableView で構成されています。テーブルの行が選択されたら、alignmentData というデータを返すデータ収集操作をキューに入れます。このデータは、水平の長方形のスラブとしてプロットされます。

最初に、tableView を起動したときのメモリ フットプリントは 5 MB です。

- (void)viewWillAppear:(BOOL)animated {

    // Initial dimensions for the alignment view are set here. These
    // dimensions were roughed out in IB.

    frame                       = self.alignmentView.frame;
    frame.origin.x              = 0.0;
    frame.origin.y              = 0.0;  
    frame.size.width            = self.scrollView.contentSize.width;    
    frame.size.height           = 2.0 * (self.containerView.frame.size.height);

}

注: viewWillAppear: が呼び出された後、メモリ フットプリントは変化していません。にもかかわらず、alignmentView のサイズはディスプレイのサイズをはるかに超えています。

これは、データ収集操作から呼び出されるメソッドです。

- (void)didFinishRetrievingAlignmentData:(NSDictionary *)results {

        // Data retrieved from the data server via the data gathering operation
    NSMutableData *alignmentData = [[results objectForKey:@"alignmentData"] retain];

    NSMutableArray *alignments = [[NSMutableArray alloc] init];
    while (offset < [alignmentData length]) {

        // ...
        // Ingest alignmentData in alignments array 
        // ...  

    } // while (offset < [alignmentData length])    
    [alignmentData release];

    // Take the array of alignment objects and position them in screen space 
        // so that they pack densely creating horizontal rows of alignment objects 
        // in the process.
    self.alignmentView.packedAlignmentRows = 
    [Alignment packAlignments:alignments basepairStart:self.startBasepairValue basepairEnd:self.endBasepairValue];  
    [alignments release];

    [self.alignmentView setNeedsDisplay];

}

このコード行の後:

self.alignmentView.packedAlignmentRows = ...

メモリ使用量は 13.8 MB

このコード行の後:

[self.alignmentView setNeedsDisplay];

メモリ フットプリントが 21.5 MB に急増し、そこに数秒間留まり、その後、既存の 13.8 MB のレベルに戻ります。

私が探しているソリューションでは、基本的に、整列オブジェクトの 1 行の高さである水平レンダー バッファー ウィンドウを作成できます。そのメモリ レンダーを割り当ててから破棄します。アライメント データの行ごとに、これを何度も繰り返します。

理論的には、このアプローチを使用して無限の量のデータをレンダリングできますが、これはもちろん最も優れた方法です ;-)。

-ダグ

4

5 に答える 5

6

これが、私の記憶の問題に対するあまり明白ではない答えです。Apple dev フォーラムのフォーム Rincewind で学んだので、これを自分に与えます。非常に役立つ Apple エンジニアである BTW です。

大きなビューを N 個の小さな断片にスライスし、それぞれを順番にレンダリングすると、大きなビューのサイズの約 1/N のメモリ スパイクが発生することがわかりました。

したがって、小さなビューごとに、alloc/init、データの一部、setNeedsDisplay をフィードします。N 個の小さなビューすべてについて、すすぎ/繰り返します。

シンプルですね。

これを学ぶ前は、 setNeedsDisplay:myRect が大きなビューに対してこれを行うと誤って考えていました。どうやらそうではありません。

すべての提案ギャングに感謝します。

乾杯、ダグ @dugla

于 2009-12-09T11:42:46.080 に答える
3

「このビューは、デバイスのディスプレイよりもはるかに大きいです。」

ビューを移動してデータ表現をスクロールしているのでしょうか。ビューをディスプレイと同じサイズにし、CGTranslate を使用して drawRect 関数内の描画オフセットを調整することを検討してください。大量のものを描画しているように聞こえますが、CoreGraphics は何が表示され、何が表示されていないかを判断できません。

ビューを小さくし、チェックを挿入してビューの境界外のものを描画しないようにすると、描画のパフォーマンスが大幅に向上します。

于 2009-12-08T02:52:41.723 に答える
1

これは非常に可能です。画面のどのセクションを描画する必要があるかを指定する必要があります。ここsetNeedsDisplayInRectで説明されているように呼び出し、再描画する領域である CGRect を渡す必要があります。

これは、画面全体を再描画するよりもはるかに高速です.1年半前に作成したiPhone描画アプリケーションでこれに問題がありました.

于 2009-12-08T02:30:24.933 に答える
0

このことはご存知かと思いますが、Core Plot フレームワークを使用してデータを視覚化したことはありますか? 最近、グラフのタッチ スクロールを追加し、フレームワーク内のメモリに関しては控えめにしようとしました。特定のケースについて詳しく知らなくても、これを試すことができるかもしれません。

于 2009-12-08T05:28:24.487 に答える
0

ベンの提案に加えて:

データをスクロールしている場合は、スクロールビューに小さなビューをいくつか追加することを検討してください。この方法では、ほとんどの場合、再描画する必要はありませんが、スクロールビューの一部の領域がカバーされなくなった場合に限ります。基本的に、サブビューの 1 つがスクロールして完全に見えなくなった場合は、それを表示領域の反対側に移動し、それに応じて再描画します。

私のアプリでは、水平方向にスクロールするだけで、2 つのサブビューを使用しています。view1 が左側にあり、view2 が右側にあるとします。view2 がスクロールして見えなくなったら、view1 の左側に移動し、それに応じて再描画します。ユーザーが同じ方向にさらにスクロールすると、view1 も見えなくなり、view2 の左に移動します。

水平および垂直にスクロールする必要がある場合は、4 つのビューが必要です。

于 2009-12-08T03:03:50.197 に答える