アプリ版:「スタンプのみでお礼する」機能のリリースについて

QueryPerformanceCounterを使ってそれほど複雑でない関数でのベンチマークを行ったところ

今のところ全ての場合においてメモリマップドファイルのほうが単純なファイルの読み書きより高速でした。
(こんないい機能があったなんて…(笑))
それほど差がない場合もありましたが、場合によっては100倍以上もの差になった時もあります。(実メモリと比較したら全然ではありますが)

メモリに困ることは最近それほどなかったので、、仮想メモリのスワップアウトが起きるとどれくらいの速度で動作することになるのか
全く実感できなかったのですが

1.このメモリマップドファイルは
原理的に、それを明示的に行うようなものとみなして問題ないでしょうか?


2.書き込み可能な属性で作り
CreateFileMappingに指定するサイズがファイルサイズより大きかった場合はファイルが拡張され、それ以下だった場合はそのままのようです。

しかし、実際にそれ未満の数値を指定して、その指定したサイズ以上のアドレスのところへ書き込もうとすると、メモリの場合サクッと不正終了してくれるので逆におかしいところがあることが分かるので安心できるともいえるのですが、こちらはファイルサイズに余裕があれば、指定したサイズを超えた部分へもどうやら書き換えることができてしまうようです。

この場合、もしファイルサイズすら超えた数値へ間違って書き込み命令を出してしまった場合、切り捨てられるのでしょうか?それともどこか別のところが書き換えられてしまう危険があるのでしょうか?


3.また、試したら出来てしまったのですが
別のポインタを使って操作するのは「通常の動作」でしょうか?
それとも未定義の動作でしょうか?

例)





char *a = (char*)MapViewOfFile( hMap, FILE_MAP_WRITE , 0, 0, 0);

wsprintf(a,"aaaaaa");
char *b= a+3;
wsprintf(b,"bbbbbb");
b+=3;
wsprintf(b,"ccc");

UnmapViewOfFile( a );






結果:
aaabbbccc

A 回答 (3件)

えーと、質問ではMapViewOfFileでマッピングサイズに0を指定していますが、この場合はマッピングオブジェクト全体がアドレス空間にマップされます。

CreateFileMappingとファイルもサイズ0だとエラーになりますので、マッピングオブジェクトはある程度の大きさを持っているはずです。質問の例は意図せずファイル範囲内になっている可能性があります。

あとマップサイズがページサイズ(4KB)の倍数でない場合、端数分は範囲を超えてもアクセス例外は出ないでしょう。また範囲を超えたらアクセス例外が起きることに期待するのは間違いです。そのアドレスにたまたま何か有効な変数に割り当てられているとアクセス例外にはなりませんから。
マップした範囲内なら反映までにある程度の遅延はあるにしてもファイルに反映されます。範囲外だとアクセス例外が出るか、何も出ずに書き込めてしまうかは分かりません。書き込めてもファイルには反映されないと思いますが、無関係な変数を壊している可能性はあります。

4.通常の動作としてはファイルを指定していればそのファイルをマップするのでスワップファイルへのマップはないと思いますが、仕様に明記されていないので保証はできません。
    • good
    • 0
この回答へのお礼

ありがとうございます。
MapViewOfFileについては、上記コードは不正終了しなかった一例として書いただけですので、実際には色々と実験していました。

…が、4KBの倍数にしてはいませんでした。
実際に4KBにしてそれを超えたところへ書き込もうとしてみると、見事に「不正終了」してくれました!
また

>範囲を超えたらアクセス例外が起きることに期待するのは間違い

というのを確認できれば十分です。
一見必要そうな状況があった場合に、そのために変数を用意する必要が本当にあるかどうかが一番の気がかりだったわけですが

通常のメモリと同じように書き込み範囲のサイズを保存しておく方が万全ならば、その変数を「別の場所でも活用した」処理をさせることを考えられれば、パフォーマンス上も全然十分だと思います。

4についても、イメージ通りのようで、安心しました。

これで安心して先に進めそうです。

お礼日時:2010/03/12 22:52

#1さんの1.→FlushViewOfFileかと。

    • good
    • 0
この回答へのお礼

ありがとうございます。
リモートコンピュータではFlushViewOfFileを普通に呼んでも同期が保証されないようですが
私の目的はローカルコンピュータなのでそれで同期が保証されるようですね。

もちろん

>CreateFile 関数を使ってファイルを開く際に FILE_FLAG_WRITE_THROUGH フラグを指定すると、物理的な書き込みが完了した後で FlushViewOfFile が制御を返すようになります。


とMSDNに書いてあるので、リモートでやりたいならそうすればOKですね。

お礼日時:2010/03/12 16:02

1. メモリマップドファイルは、プロセスのアドレス範囲を利用できるようにする機能です。

同時にそのアドレス範囲のスワップアウト先を指定ファイルにすることができます。
なお、マップしたメモリへの書き込みは必ずしも即座にファイルに反映されるわけではないので注意してください。ファイルでもフラッシュが必要なように、同期APIの呼び出しが必要です。
# 同期APIの名称を思い出せない。アンマップ時しか同期できないかも

2. 書き込み可能マップを作ると、書き込みの有無に関わらずファイルはそのサイズまで拡大されます。逆にマップ作成時に指定したサイズを超えてのアクセスはアクセス例外になります。

3. メモリマップドファイルは、プロセスの指定アドレス範囲を利用可能にします。プロセスで利用可能なアドレス空間をプロセス内のどのポインタでアクセスしても有効です。
    • good
    • 0
この回答へのお礼

ありがとうございます。
やはり明示的に同期させなければ同期が保証されないという点以外は、メモリと同じような扱い方が出来るようですね。

しかし、2のアクセス例外というのは、OSが勝手に握りつぶしてくれる(ファイルのサイズ内なら普通どおりやり、その外だとやめてくれる…?)
のでしょうか?
上記のとおりファイル範囲外に代入したようなコードでも不正終了など全く起こらないばかりか、GetLastErrorとか使っても何も捕捉できません。

使用を控えていた try catch で念のため実験(catchは(...)で)してみても、やはり何も例外を受け取りません。

すみません(汗
もうひとつ重大なことを忘れていました。

4.0xFFFFFFFFを指定するとページングファイルを使うことになり
それ以外なら普通のファイルを使うことになり、ページングファイルは全く使用しないことが保証されるのでしょうか?

お礼日時:2010/03/12 15:57

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!