9

私はいくつかのリアルタイムデータをグラフ化しようとしています。ここでの「リアルタイム」とは、10ミリ秒未満のデータ、理想的には可能な限り低いデータを意味します。私はAndroidにこれほど高速にデータをフェッチして処理させることができましたが、ACEはリアルタイムでの使用を念頭に置いて設計されていないように見えます。最初の症状は、ガベージコレクターが明日がないように起動し、アプリを完全に強制終了することです。私は「スライディングウィンドウ」方式でデータを視覚化しているので、ACEがリアルタイムで数十万のポイントをプロットすることを期待しているわけではありません。私はそれを見てみましたが、onDraw for XYChartは、便利でコードがはるかに読みやすくなるが実際には必要ないように見える場合に、確かに非常に多く割り当てられます。これは以前よりもさらに悪い可能性があるため、まだ気づいていない可能性があります。

return mXY.subMap(start, stop);

にとって:

return new TreeMap<Double, Double>(mXY.subMap(start, stop));

これにより、同時実行の問題を回避するために、onDrawの実行中に更新をキューに入れ、後でアトミック更新またはその行の何かで更新を処理する方がよい場合に、膨大な割り当てが作成されます(ただし元のサブマップに支えられています)。

ここでの本当に残念なことは、ACEが私が必要とするものに対して確かに十分に速いということです。それは私のハードウェアで必要なことを完璧に行うことができますが、再描画に非常に多くを割り当てるため、AndroidはGCに夢中になります。GCの実行中にすぐに割り当てが開始されるため、待機する必要があり、アプリはストップモーションムービーのように見え始めます。

ただし、本当の問題は、ACEを使用して4または6のラインチャート(タブレットアプリ)をリアルタイム(200ミリ秒未満のリフレッシュレート)で再描画できると期待するのは合理的ですか、それともそのような悪用に備えていないだけですか?答えがノーの場合。そこにあなたがお勧めしたい他のオプションはありますか?

編集20130109: リビジョン471は、小さなデータセットの場合にかなり改善されます。2.000ポイント/4チャート/100ミリ秒のリフレッシュレートは実行可能でスムーズです。ログには、クレイジー(約10 /秒)のように「GC_CONCURRENTが解放されました」と表示されますが、アプリをストップモーションのようにするショートッパーである「WAIT_FOR_CONCURRENT_GCblocked」は表示されません。3.000ポイント/1チャート/100ミリ秒では、明らかに滑らかではありません。logcatと吃音アプリで「WAIT_FOR_CONCURRENT_GCblocked」のなだれが再び発生します。ここでも、速度の問題はなく、メモリ管理の問題だけがあるようです。

ACEに魔法をかけるように頼んでいるように見えるかもしれませんが、テレメトリデータを1KHzで取得して保存するためにすべてのコードをリファクタリングした後、この壁にぶつかりました。ついに、アプリがGCをまったくトリガーせずにリアルタイムですべてを取得して保存するのを確認したら、グラフ化しようとしたときにACEで髪を引っ張りました:)

4

3 に答える 3

2

まず第一に、素晴らしい質問とあなたが提起した点に感謝します。この方法で行われた膨大なメモリ割り当てについては、間違いなく正しかったでしょうonDraw()。私はそれを修正し、SVNのコードをチェックインしました。また、再描画中にデータセットに新しいデータを追加するときにonDraw()スローされないように、メソッド内に同期ブロックを追加しました。ConcurrentModificationException

新しいAChartEnginejarファイルを作成してアプリケーションに埋め込むには、SVNからコードをチェックアウトし、antdistを実行してください。こちらの手順をご覧ください。

あなたの質問に答えるために:AChartEngineは間違いなく動的チャート作成の準備ができています。あなたが報告した問題はショーストッパーでしたが、今すぐ修正する必要があります。私はそれを使ってダイナミックチャートを書きました。ただし、データセットに100000のデータ値を追加しないようにする必要があります。パフォーマンスを向上させるために、データセットから古いデータを削除できます。

1000ポイントまでの折れ線グラフが数個ある場合は、5つほどの折れ線グラフを描くことは間違いなく合理的です。

于 2013-01-08T11:23:37.720 に答える
0

私のアプリで他のすべてを最適化するために多大な努力をした後でも、私が理解していることを「リアルタイム」でプロットすることはできません。ライブラリは素晴らしく、非常に高速ですが、すべてのonDrawがメモリを割り当てる方法は、必然的にガベージコレクションの雪崩を引き起こし、それが独自の割り当てと衝突するため、Androidはアプリを一時的にフリーズさせ、「リアルタイム」グラフとは完全に互換性のないスタッターを引き起こします。ここでの「スタッター」は50〜250ミリ秒(はいミリ秒)の範囲ですが、リアルタイムアプリを強制終了するには十分です。

AChartengineを使用すると、「リアルタイム」(10フレーム/秒(<100msのリフレッシュレート)または「スムーズ」と呼ばれるもの)である必要がない限り、「動的」グラフを作成できます。

ここでコアの問題に関する詳細情報が必要な場合、またはライブラリは十分に高速であるが、メモリ割り当てパターンがパフォーマンスの問題を引き起こすと言っている理由は、Google I /O2009-Android用のリアルタイムゲームの作成をご覧ください。

于 2013-01-16T22:18:36.870 に答える
0

さて、しばらくして別のグラフ作成ライブラリを探した後、十分なものは何も見つかりませんでした:)それで、ACEをもう一度調べて、理想からはほど遠いものの、「使用可能」にする小さなパッチを作成することになりました。

XYSeries.javaで、新しいメソッドを追加しました。

/**
* Removes the first value from the series.
* Useful for sliding, realtime graphs where a standard remove takes up too much time.
* It assumes data is sorted on the key value (X component).
*/
public synchronized void removeFirst() {
  mXY.removeByIndex(0);
  mMinX = mXY.getXByIndex(0);
}    

メモリの問題に加えて、高速フレームレートでも実際の速度の問題があることがわかりました。スクロールして見えなくなったポイントを削除するときに、削除機能に約90%の時間を費やしていました。その理由は、min | maxポイントを削除すると、ACEがInitRangeを呼び出し、すべてのポイントを繰り返して、内部で使用する最小/最大ポイントを再計算するためです。1秒あたり1000のテレメトリフレームを処理していて、ビューポートが小さいため(ACEメモリ割り当て戦略によって強制されます)、削除機能で最小/最大ポイントを頻繁にヒットします。シリーズの最初のポイントを削除するために使用する新しいメソッドを作成しました。これは、通常、ポイントを追加するとすぐに呼び出され、ビューポートからスクロールアウトします。ポイントがキー値(クラシックdateTimeシリーズ)で並べ替えられている場合は、mMinXを調整して、ビューポートの見栄えを良くし、非常に高速に実行できます。現在のACE実装ではminYまたはmaxYを高速に更新することはできませんが(私が調べたわけではありません)、適切な初期範囲を設定した場合、それは必要ない場合があります。実際、私は自分が何をプロットしているか、そしてさまざまな時点での通常の範囲が何であるかを知っているので、私が持っている追加情報を使用して時々手動で範囲を調整します。

したがって、これは他の誰かにとっては十分かもしれませんが、深刻なリアルタイムグラフ作成のために、ACEではメモリ割り当てのリファクタリングが依然として必要であると私は主張します。

于 2013-01-24T12:52:48.383 に答える