• ベストアンサー
  • 困ってます

メモリマップドファイルを可変長メモリプールとして

だいぶ製作中のアプリケーションも、自作ファイル形式も かなり大きい(よほどの場合により数百MBとか)ファイルを扱う可能性が生じてきたので 必ず全部メモリに読み込むのは推奨できない、という状況になりました。 そこで 既存のファイルからは読み取り専用で メモリマップドファイルとして開き、普通のメモリ上に読み込まずともポインタ操作できるようにし 操作したい場合は読み書きできるメモリマップドファイルを、自分のアプリの指定フォルダに作業領域として作ったところから使用中だと判断出来るようにしておいて確保し アドレスはオフセット等で管理し、ポインタを移し替えたりする、という手を使い また、うまく処理を切り分けてやることにより 重要な個所についてはメモリ上に確保し、そこにデータにフィルタ演算するついでに移し替えたりするなど さまざまな手によって かなりの速度も実現出来ることが確認できました。 これはつまり、メモリではなくメモリマップドファイルを 可変長メモリプールとして使うという形になっています。 ただ、昨日思いつきで作って、とりあえず十分快適に動作は出来るけども、最適解かどうかは手探り状態、ともいえるので よりよい方法が考えらるならぜひ知っておきたいです。 と…書いてる途中で 今は「使用中」「未使用」のフラグとそのサイズを持たせたリストを、一方向にnextポインタでつなぐのみ、となっていますが 空きリストのみ(も?)収集して…という方法の概念を思い出しました。 あまり複雑になるとバグが出る危険性はありますが、試す価値はありそうです。 ただ ・まず、メモリマップドファイル自体については、作った後はそのファイル自体は固定サイズ、ってことで良いでしょうか? ・可変長メモリプールなどのアルゴリズムについて、把握するのに何日もかかりそうなあまり巨大なコードになりすぎない範囲で、考察したりオープンソースで作ったりしているサイトなどがあれば教えていただきたいです。

共感・応援の気持ちを伝えよう!

  • 回答数1
  • 閲覧数751
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.1
  • Tacosan
  • ベストアンサー率23% (3656/15482)

メモリマップドファイルは標準には含まれない (はず) なので, その実装などは使っているシステムに依存すると思います. 例えば, Windows なのか FreeBSD なのか Linux なのかによって違うかもしれませんよ.

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ご回答ありがとうございます♪ それは重要な情報ですね。 考えてみれば、OSと密接に関係してそうですからね。 将来的な移植の可能性を考えると、あまり長すぎるコードを組むのも得策ではないかもしれません。 とりあえずは、WindowsのXP以降を対象と考えたいところです。 ちょっと確認してみたら、現在は宣言と定義で占めて550行程度でした。 アプリケーションの総合的なパフォーマンスを考えると これはかなり重要な部分ではあるので 逆に、内容にもよりますが、1000行くらいまでなら移植するのもそれほどきつくはないかな、と思っています。

質問者からの補足

(12/27) 久しぶりに見てみたら メモリマップドファイルではなくメモリ上での可変長プールで、単独での解放手順がないバージョンはEfficient C++に載っていました。 やはり単独での解放手順があるのとないのとでは結構必要事項の量が変わってきますが (その他の色々なサイトなども含め)少なくとも、現状かなりいい線いってることは確かなはずと感じたことと システム依存という情報が得られたこと(この情報があるだけでかなり色々なことが考えられますので)を踏まえ 今回の質問は締め切りとさせていただきます。 ども、ありがとうございました。

関連するQ&A

  • メモリマップドファイルを使って高速化できるか

    現在、テキストファイルの読込みを関数(fopen(),fgets(),fclose()) を使って処理しています。 今回、処理を高速するためメモリマップドファイルの使用を検討しています。 そこで質問なのですが、 メモリマップドファイルを使うと劇的な高速化が期待できるのですか? 高速化する場合、どういったタイプのファイルに有効なのですか? 自分で調べろと言われそうですが、ご勘弁ください。 使ったことのある方、また、実際に比較してみたことのある方が いましたら教えて下さい。

  • メモリマップドファイルは動作原理的に…

    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

  • C言語のメモリ領域確保

    ポインタ変数ををmain関数で宣言し、関数test()にて必要分だけ領域確保してそのアドレスをmain関数のポインタ変数に渡して利用することは可能でしょうか。 (サイズのわからないテキストデータを、十分に大きな配列に入れるのではなく、関数でメモリを動的確保して無駄の無い配列に入れたい等) C言語ではやはり無理で、構造体のリストにするのが一番でしょうか。 初歩的なことで申し訳ありませんがどなたかお願いいたします。

  • reallocでメモリを再確保するには?

    こんにちわ, 今, 「すでに動的確保しているメモリをその型分1サイズだけ増やす」というプログラムを考えています。 具体的には, char* str_p; a=calloc(str_p, sizeof(char)); /*ここから問題のプログラム(実際はずっと動くので無理です*/ while(1) { a=realloc(str_p, sizeof(str_p)+sizeof(char)); } ・・・・・・ これだと,私的にはsizeof(str_p)で今のサイズを調べ,それにsizeof(char)を加えることで次々に1サイズ大きいメモリを再確保できると思ったのですが,ポインタのサイズを指していてそれにchar型のサイズをたしていていつも固定サイズになるみたいでうまくいきません。 どうすれば,char*などポインタ型の変数の大きさを調べられるのでしょうか。 また,どうすれば,1サイズずつ大きくできるのでしょうか。 よろしくおねがいします。

  • c言語 可変長配列

    下は可変長配列のプログラムである.提供される可変長配列に文字列を格納するにはどのようにすればよいのでしょう.使い方の例を示していただけると助かります. #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* 可変長配列の初期サイズ */ #define INIT_SIZE 5 typedef struct vector Vector; typedef Vector *VectorPtr; /* 可変長型配列の構造体 */ struct vector { char **elems; /* 要素(文字列)の配列(固定長)*/ int size; /* 可変長配列のサイズ */ int capacity; /* 可変長配列の最大容量 */ }; /* 可変長配列を生成する */ VectorPtr create_vector(void) { VectorPtr v = NULL; v = malloc(sizeof(Vector)); if (v == NULL) { fprintf(stderr, "Couldn't allocate memory for a vector\n"); exit(EXIT_FAILURE); } v->elems = malloc(sizeof(char *) * INIT_SIZE); v->size = 0; /* 初期使用サイズは 0 */ v->capacity = INIT_SIZE; return v; } /* 可変長配列の実質的な解放作業を行う. * (次々と free() するので free() 後の NULL 代入は省略) */ void delete_vector0(VectorPtr v) { int i; /* free() と同様,NULLポインタに対しては何も行わない */ if (v == NULL) { return; } /* 各要素(文字列)の領域を解放 */ for (i = 0; i < v->size; i++) { free(v->elems[i]); } free(v->elems); /* 内部配列の領域を解放 */ free(v); /* 外側の枠も解放 */ } /* 可変長配列 v を初期化する(未使用状態にするだけで領域は解放しない).*/ void clear_vector(VectorPtr v) { int i; assert(v); /* 要素の各文字列を解放 */ for (i = 0; i < v->size; i++) { free(v->elems[i]); v->elems[i] = NULL; } /* 使用サイズを0にする */ v->size = 0; } /* 可変長配列 v を拡大する */ void expand_vector(VectorPtr v) { assert(v); /* 最大容量を2倍に増やす */ v->capacity *= 2; /* 新しい最大容量を持つ領域を確保 */ v->elems = realloc(v->elems, sizeof(char *) * v->capacity); /* サイズを変更できなかった場合のエラー処理 */ if (v->elems == NULL) { fprintf(stderr, "Couldn't re-allocate memory for a vector\n"); exit(EXIT_FAILURE); } } /* 可変長配列 v の最後に文字列 s を追加 */ void append(VectorPtr v, char *s) { assert(s); /* 容量が一杯になったら容量を拡大する */ if (v->size == v->capacity) { expand_vector(v); } v->elems[v->size] = _strdup(s); /* 最後に要素を追加 */ v->size++; /* 使用部分のサイズを1つ増やす */ } /* 可変長配列の(使用部分の)サイズを返す.*/ int get_vector_size(VectorPtr v) { assert(v); return v->size; } /* 可変長配列 v における添え字 index の要素(文字列)を取得 */ char *get_elem(VectorPtr v, int index) { assert(v); /* 配列添え字の範囲をチェック */ if (index < 0 || index >= v->size) { fprintf(stderr, "Index out of bounds"); exit(EXIT_FAILURE); } /* 指定された添え字の値を返す */ return v->elems[index]; } /* 可変長配列の内容を横に並べて表示する.*/ void print_vector(VectorPtr v) { int i; assert(v); if (v->size == 0) { printf("(empty)\n"); return; } for (i = 0; i < v->size; i++) { printf(">>%s", v->elems[i]); } printf("\n"); } int main(void) { return 0; }

  • 可変長文字列で困ってます

    宿題出で全くわかりません。 ここを実装っていうところがわかりません。 よろしくお願いします。 /* 単方向リストプログラム */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <crtdbg.h> /********************* リスト処理部 *********************/ /* リストセル 構造体定義 */ typedef struct cell { char *string; struct cell *next; } CELL, *PCELL; /* PCELL ListInsert(PCELL pos, const char *string) 指定されたセルの次に,新しいセルの挿入する PCELL pos : 挿入位置のセルを指すポインタ char *string : 新セルに含める文字列 戻り値: 新しく確保したセルのアドレス メモリ確保に失敗した場合にはNULL */ PCELL ListInsert(PCELL pos, const char *string) { PCELL pNewCell; pNewCell = calloc(1, sizeof(CELL)); if (pNewCell != NULL) { // ここを実装する } return pNewCell; } /* void ListDelete(PCELL pos) セルの削除.pos の指すセルの次のセルを削除する. PCELL pos : 削除するセルの直前のセルを指すポインタ */ void ListDelete(PCELL pos) { // ここを実装 } /* void ListDestory(PCELL header) リスト全体の削除 PCELL header : ヘッダセルへのポインタ */ void ListDestroy(PCELL header) { // ここを実装 }

  • リストや木についての質問

    リストや木等のデータ構造(?)は ポインタのつなぎ方みたいな物なのでしょうか?? それとも、それには何か特別な関数(メモリー確保を除く)が必要なのでしょうか??

  • mallocで確保したメモリをfree解放する必要

    当方、C言語を勉強中です。 mallocで確保しておいたメモリをfreeで必ず解放するようにと教わりました。 freeで開放しないことをひどく野蛮な言葉で例えられたのですが、それほどまでに必要である実感が実はあまりありません。 ファイルポインタでファイルを開いているときに、プログラムが終了すると開いているファイルを自動的に閉じるように、プログラムが終了すると自動的に解放されるものと思っていたのですが、やはりこちらはプログラム終了後も確保されたままになってしまうのでしょうか。 また、解放しないことによるデメリットで、メモリを圧迫する以外にはなにがあるのでしょうか。 ご教授おねがいします。

  • メモリーの確保について

    皆さんはプログラムをするときに入力に応じて配列の大きさが変わるような場合には下記の方法のどれでプログラムしますか?こうすべきなのがベストだ!みないなお考えを聞かせてください。 (1)char str[100]のように大きなサイズを前もって用意しておく。これだとあとからデバック時に100って何か意味があるのかとか悩んでしまったりすると思います。 (2)malloc()とfree()関数を使って動的にメモリーを確保する (3)ポインタ配列を使う。char *strとか。 (4)その他 ご教授をよろしくお願いいたします。

  • ファイルアップロード時のメモリサイズを超えたときのエラーについて

    PHPでアップロードする画面を作ったのですが、PHPのメモリサイズでは8Mまでの領域しか確保できないため、8Mを超えるファイルをアップロードしようとしたときに、エラーを返したいのですが、Web側でエラーを返すまでもなページを表示できませんというエラーになってしまいます。 こちらをメモリの領域を確保する前にサイズを測る方法などはあるのでしょうか??

    • ベストアンサー
    • PHP