データベースを使ってなんでも処理するというのは最近のトレンドなのかもしれないけど、ある場合には、ファイルベースで全然間に合うんじゃないか?とかファイルベースの方が速いんじゃないか?ということで、今回はMemoryMappedFileで構造体を読み込むというのをやってみた。
(C#で構造体読み込みなんてあまりやらないことなのかもしれないけど)
ひとまずソースコードはこんな感じになった。
構造体Historyを定義して、MemoryMappedFile.CreateFromFileからファイルを作成。CreateViewAccessorでランダム アクセス ビューを作成して、構造体を書き込み・読み込みする流れ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
{ struct History { public long FileTime; public long Price; public long Amount; } class Program { static void Main(string[] args) { using (var mmf = MemoryMappedFile.CreateFromFile("history.dat",FileMode.Create,null,256)) using (var va = mmf.CreateViewAccessor()) { var history = new History(); history.FileTime = -2; history.Price = -2; history.Amount = -2; va.Write(Marshal.SizeOf(history), ref history); history = new History(); va.Read(Marshal.SizeOf(history), out history); } } } |
注意点は、構造体にstringなどオブジェクトは含めることはできないということ。型のサイズがよくわからなくなるからかな?(いやそのそもバイナリレベルでそんなのイジっちゃいけないよね普通…)
あと、構造体のサイズはMarshal.SizeOfを使って取得。sizeofってのが普通に使えそうだけど、構造体には使えないっぽい。Marshalってのがマーシャリングに関するものらしく、Marshal.SizeOfでマーシャリング後のサイズが取れるとのこと。
そもそもマーシャリングってなんだと思ったら、「【保存版】構造体のマーシャリングのまとめ – 鷲ノ巣」によると
呼び出し側のデータのコピーを作って、それを相手側にとって都合のいい形式に変換してから渡します。
とのこと。なるほど、、、結局C#とCのデータ表現の違いを吸収する話だったか。
ということで実際できたバイナリはこんな感じ。ちゃんと書き込めている。
読み込みも当然うまく言ってる。