仕事であるプログラムを作成する事になりました。
Unityでマイクの音声をずーっと録音し続けてファイルに保存するというプログラムです。
今までだとそういう時は、バッファにずーっとデータを溜めていって、最後にファイル書き込みって処理にしてましたが、今回は下手すると1時間くらい録音する可能性があるそうです。
1時間分のwavファイルは600MBくらいあります。
数百MBだの1GBだのデータを素直にメモリに持ちたくありません。
なので音声データを随時にファイルにチビチビ書き込む事にしました。
しかし私はファイル操作の挙動について疎かったので、一応検証する事にしました。
メモリ
ここからよく分かってなかったのですが、調べたところでは、ファイルをオープンしただけならサイズが小さいファイルだろうがでかいファイルだろうがメモリは食いません。
次にStreamWriterでWriteしまくってるとメモリ消費量が増えるのか?というと、そんな事はありません。
StreamWriterはある程度書き込むデータが溜まってからまとめて書き込むので、そのバッファ分の数kBは消費しますが、それ以上はどんどんファイルに書き込むのでメモリは減りません。
実際ザックリ検証した感じでもWriteを何回やっても使用メモリ量は増えてませんでした。
速度
ファイルサイズが大きくなるにつれてStreamWriter.Writeが遅くなったりとかするのか?
これもわからなかったので検証してみました。
StopWatchクラスで計測しました。検証用コードはすいませんが面倒なので掲載しません。
ちなみに私のPCのディスクはHDDです。
1. ファイルを作成してクローズするだけを1回
平均約1ms
2. ファイルを作成して1万回write(”美樹さやかわ”という12byteデータ)してクローズ
平均約23ms
1回あたりのwriteのコストは0.002msほどでしょうか。ゲームで毎フレームちびちびWriteしてもさして問題なさそうです。
3. ファイルオープン、write、クローズを1万回
12,878ms
オープンクローズだけで1msだったので1万回なら当然1万倍で順当じゃないでしょうか。毎フレームファイルのクローズすべきか?というとコストがあるのでファイルは開きっぱなしの方が良さそうですね。毎フレ1msのコストはゲームとかでは無視できないです。
4. 176kBのファイルをオープンクローズだけ1万回
1,042ms
5. 1.76GBのファイルをオープンクローズだけ1万回
945ms
ファイルのオープンクローズはファイルサイズによって処理時間変わるのか?という検証ですが、変わらないみたいです。
6. 176MBずつファイルにWriteしていくのを10回(最終的に1.76GBになる)
平均約600ms
ファイルサイズによってWriteの処理時間は変わるか?という検証ですが、特に有意に処理時間が増えたりはしませんでした。
7. 1.76GBのファイルを追記(Append)でオープンして1万回Writeしてクローズ
5ms
ファイルサイズが大きくてもWriteの処理速度のペナルティはあまりなさそうです。
8. 1.76GBのファイルを追記オープン、Write、クローズを1万回
33.645ms
これは3のケースに比べると3倍くらい処理速度が増えてます。ファイルサイズに比例するほどのペナルティは無いとはいえ、若干はあるのかも知れません。
まとめ
消費メモリと処理速度の観点から検証しましたが、やはりファイルオープンしっぱなしで毎フレームちょっとずつ音声データをWrite、最後にファイルクローズという手法で問題なさそうです。
今回は書き込みのケースだけで読み込み(StreamReader)については未検証ですが、要領としては同様(ちょっとずつファイルから読み出しがベスト)だと思われます。