2011-02-02 7 views
3

私はAndroidアプリケーションを作成しています。私が知る限り、デバイスのほとんどのSDカードは〜4Mb/sの書き込み速度を持っています。最悪の場合、私のアプリケーションでは、1秒あたり約0.5回、新しいファイルに〜0.5MBを作成して書き込む必要があります。一般的に、これを実行するとIOは非常に高速ですが、短時間にいくつかのファイルを作成して書き込んだ後、突然の待ち時間が〜2秒になります。ここで 定期的にデータを書き込むときにランダムな長いIOが一時停止する

が自分のアプリケーションからいくつかの統計です(唯一のIO操作が今まで一度に実行されていることに注意してください):IO操作のほとんどはなく、< 0.05sで終了

E = Time IO operation began 
S = Number of Mbs written 
WT = Time taken to write to file 

E  S  WT  
14.546 ~0.41 MB 0.02s 
15.061 ~0.40 MB 0.019s 
15.600 ~0.42 MB 0.073s 
16.054 ~0.41 MB 0.02s 
16.538 ~0.36 MB 0.019s 
17.007 ~0.33 MB 0.018s 
17.475 ~0.32 MB 0.017s 
18.030 ~0.38 MB 0.07s 
19.991 ~0.38 MB 1.542s <-- 
20.124 ~0.34 MB 0.018s 
20.233 ~0.25 MB 0.015s 
20.390 ~0.38 MB 0.021s 
20.624 ~0.36 MB 0.08s 
20.858 ~0.37 MB 0.018s 
21.304 ~0.32 MB 0.018s 
21.796 ~0.33 MB 0.017s 
22.257 ~0.35 MB 0.02s 
22.780 ~0.37 MB 0.07s 
24.366 ~0.27 MB 1.178s <-- 
24.522 ~0.40 MB 0.021s 
24.648 ~0.34 MB 0.019s 
24.866 ~0.38 MB 0.018s 
25.319 ~0.29 MB 0.07s 
25.850 ~0.45 MB 0.021s 
26.288 ~0.39 MB 0.018s 
26.796 ~0.43 MB 0.035s 
27.249 ~0.33 MB 0.069s 
27.671 ~0.41 MB 0.018s 
30.054 ~0.44 MB 1.874s <-- 

お知らせを、約8後〜4Mbのデータが合計で書き込まれている場合、次のIO操作は約1.5秒かかります。なぜこうなった?このパターンはかなり一貫して起こります。

私のファイルは、(私がフラッシュしたり同期していないよ)次のコードで書かれている:

RandomAccessFile fos = new RandomAccessFile(filename, "rw"); 
    FileChannel outChannel = fos.getChannel(); 
    byteBuffer.rewind(); 
    outChannel.write(byteBuffer); 
    fos.close(); 

私は、ファイルIOには専門家だが、私は、高速IO操作時間がhasnデータを示している知っています実際にはまだディスクに書き込まれていません。大きな休止はおそらくバッファがフラッシュされることでしょう。一時停止を避けるにはどうしたらいいですか?私のIO操作が小さくて、まれにこの一時停止を避けることができるはずです。

いくつかのコンテキストでは、私はmementosでコマンドパターンを使用して、ユーザーが実行できる破壊的操作が多いコンテキストでアンドゥ/リドゥを実装しています。私は記憶が足りないので記憶に記憶を保存することができないので、代わりに記憶をディスクに書き込む。これは、上記の一時停止の問題を除いて素晴らしいことです。これは、UIがIOの終了を待つことを余儀なくされ、遅延の1.5秒がユーザーから隠れるには多すぎることを意味します。私は、取り消し/やり直しを実装することが他にもあると知っていますが、すべてのアプローチには欠陥があります。

答えて

3

どうしてですか?

フラッシュへようこそ。

私はファイルIOの専門家ではありませんが、実際にデータが実際にディスクに書き込まれていないことを示しています。大きな休止はバッファがフラッシュされている可能性が高いことを示しています。

おそらくそうではありません。ほとんどのAndroidデバイスはYAFFS2ファイルシステムを使用していますが、私はそれを理解しているので、あまりデータをバッファしません。ただし、パーティションごとの書き込みロックがあるため、一時停止はおそらく他のものがフラッシュに書き込んでいるときです。

多くのAndroid搭載端末(Nexus Sなど)でext4ファイルシステムを実行している場合は、flushing/syncing becomes importantとなります。

また、書き込み速度をフラッシュ心に留め等、試されている特定の細胞上で、このようなファイルシステムがどのようにいっぱいのような他の要因の様々なウェアレベリングの状態を変化させるであろう

Brad Fitzpatrickの2010 Google I|O presentationを「Zippy Android Appsの作成」で視聴したいと思うかもしれません。詳しくはこちらをご覧ください。

一時停止を回避するにはどうすればよいですか?

あなたはありません。おそらくAsyncTaskを介してバックグラウンドスレッドにフラッシュI/Oを移動します。 Android 2.3の新しいStrictModeは、このような「ジャンク」コードのある場所を特定するのに役立ちます。

+0

ああ、残念です。私は私の元に戻す/アプリケーションセッションの間に維持するためにスタックをやり直したいので、これらのスタックをある時点でディスクに保存する必要があります。コマンドオブジェクトはかなりの大きさに成長するので、作成されたときにディスクに書き込むバックグラウンドプロセスが必要になります。しかし、予想外のIO書き込み時間では、アプリケーションが中断された場合にonPauseが呼び出されるまでに、すべてのものをディスクに書き込むようにする方法がわかりません。 .sync()を各ファイルで呼び出す必要がある場合は、状況はさらに悪化します。何かアドバイス? – rbcc

+0

@rebeccamaher:「コマンドオブジェクトはかなり大きなサイズに成長するので、バックグラウンドプロセスを作成してディスクに書き込む必要があります。」 - 背景*糸*してください。 'LinkedBlockingQueue'を使用して、キュー上のメモを受け取ったスレッドが到着したときにフラッシュに書き込むことを検討してください。 「アプリケーションが中断された場合にonPauseが呼び出されるまでに、すべてのものをディスクに書き込むようにする方法を明確にすることはできません」 - バックグラウンドスレッドは 'onPause()'の呼び出しによって影響を受けません。 – CommonsWare

+0

おっと、私はスレッドを意味しました。参照ありがとう!別のアクティビティが前面に来たときにスレッドを実行する際に問題はありませんか?スレッドが殺される可能性はありませんか?ヒントをありがとう、私はこのアイデアを試すことができます。私の唯一の問題は、データをディスクに保存することができない場合、私はあまりにも多くのコマンドを投げ捨てる必要がないように、保存するデータを最小限に抑えることです。 – rbcc

関連する問題