« スレッドプールに溜まっていたことが判明 | トップページ | PCが熱暴走した? »

2010年10月11日 (月)

センサデータログにはまだ未解決の部分が残っている

先日の日記で、センサデータのログ問題に関して「ほぼ」解決した、と書きました。ほぼ、と書いたのは一抹の不安があったからです。そして、動くことは動くけれど、まだ未解決の問題が残っていることがわかりました。

先日の反省を踏まえて、タイマイベントにより呼び出されるイベントハンドラ処理が(タイマのインターバルとして設定した)100msを超えてしまった場合に備えて、イベントハンドラの先頭と末尾にInterlocked.Exchangeを仕掛けました。これを仕掛けることでイベントハンドラの再入を検出して、再入しているようなら何もしないで処理を抜けさせます。この時、再入を検出した時点でシステムログに再入検出を記録することにしました。

ここからが問題です。まず、開発用PCのHDDでプログラムを実行すると、システムログにイベントハンドラの再入記録が残っていないので問題無いのですが、同じ開発用PCでもSDカード上でプログラムを実行する(すなわち、SDカード上にセンサログが記録される)と、システムログにイベントハンドラの再入検出が記録されてしまいます。ということは、SDカードに対するファイルの書き込みに100ms以上かかっているということなのでしょうか。

ということで、SDカードに書かれるデータのサイズと書き込み速度を見積もってみます。

  • (LRSのデータログ1行当たりのデータサイズ)
  • =((データ1点あたりのバイト数)+(カンマのバイト数))×(データ点数)
  • =((5 × 2) + 2)×1081
  • = 12972 [Byte] = 13 [KB]

これが1秒間に10回書き込まれるとすると、必要な書き込み速度は 130KB/sです。一方、私が使っているSDカードはClass4と書かれているので、書き込み速度は4MB/s。書き込まれるデータが小刻みなのか大きなブロックなのかでFlash ROMの書き込み速度は大きく変わりますが、それにしても桁が違うので書き込み速度には余裕がありそうです。

そこで、実際に書き込み時間がどれくらいかかっているのか測ってみました。その結果、HDDにセンサログデータを書き込んだ場合は1回あたり0~17ms(最頻値は 1ms)で、SDカードの場合は16~776ms(最頻値不明)でした。SDカードの場合、100ms以下の回数が少なく、120~200ms以上かかるケースが大多数でした。この結果からみて、SDカードへの頻繁な書き込みがボトルネックであることは間違いありません。

対策をいくつか考えてみます。

  • A案: RAM上にセンサログデータを貯めて、ログ収集を終了した時点でファイルに落とす。
  • B案: SDカード上でのプログラム実行を止めて、制御用PCのSSD上でプログラムを実行し、センサデータログもそこに落とす。
  • C案: log4netやsqliteなどの既存のコンポーネントにセンサログ収集を任せる。

A案は、処理速度的には速そうですが、仮に1時間分データを貯めるとすると475MBになるのでできれば避けたい。制御用PCのRAMは1GBしかないので、スワップが沢山発生するのもいやですから。

B案は、一番手っ取り早い方法です。元々、プログラムの書き換えやセンサログデータの移動を簡単にするためにSDカード上でプログラムを走らせて、データもそこに落としていました。でも、その手間はクリティカルな問題ではないので、処理速度的にNGなら手間をとったほうがいいかもしれません。なにより、一番確実ですから。

C案は、log4netやsqliteならそこら辺をうまくやってくれるんじゃないかなぁという期待だけで、根拠はありません。なので、やってみても解決しないかもしれません。

ということで、時間が無いので安全確実なB案がよさそうですね。

« スレッドプールに溜まっていたことが判明 | トップページ | PCが熱暴走した? »

コメント

yさん、コメントありがとうございます!
すっかり放置してしまっており、申し訳ありません。

G案の圧縮しながら書き込むというのは、C#なら.NET FrameworkのGZipStreamクラスを使えばできるようです。
http://dobon.net/vb/dotnet/file/compressfile.html
大変勉強になります。

しかし、そもそもURGのログをそんなに大量に集める必要があったのかというほうが問題で、実はもっと時間的に間引きしたデータで十分だったのではないかと考えています。

どうも。はじめまして。
よく読まずに反応してしまいますが、Windowsだとして、

E案:SDカードの設定を変更してローカルディスクに見せ、書き込みキャッシュを有効化する

というのはどうでしょう。昔Netbookを使う人の間で流行ったように思います。
F案:自前でキャッシュ的なものを実装するとしても、(C#でどう書くかわかりませんが)例えばC++だとstd::ostringstreamあたりにどんどん書いておいて、数秒に1回程度書き込む、というくらいでも大丈夫かもしれません。
G案: Unixだとgzipとかをpopenして、そこに出力すれば圧縮もしてくれてうれしいかもしれないですね。Windowsでも同じようなこと出来るんでしたっけ?

かみやんさん、いつもコメントありがとうございます!

WiFiで飛ばしてロギング。これができたらスマートですね。ただし、走行データをとるときは常にノートPCを持ち運ぶことになりそうですが。

URGのセンサデータをログに落としてみたら15GBという途方もないサイズになってしまいました。SSDの容量が32GBしかないのに。

そもそもURGのログを100ms間隔で収集したこと自体が無駄ですね。

D案、ノートPCにWiFiで飛ばしてそっちでロギングとか。
がしかし手間から考えてB案がよさそうですね~。

コメントを書く

コメントは記事投稿者が公開するまで表示されません。

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/167990/49710230

この記事へのトラックバック一覧です: センサデータログにはまだ未解決の部分が残っている:

« スレッドプールに溜まっていたことが判明 | トップページ | PCが熱暴走した? »

最近の写真