- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- ソース を表示
- PostgreSQL/開発/include/utils/palloc.h へ行く。
- 1 (2017-05-16 (火) 21:40:21)
- 2 (2017-05-16 (火) 22:14:41)
- 3 (2017-05-18 (木) 00:00:43)
- 4 (2017-05-18 (木) 22:50:59)
- 5 (2017-05-20 (土) 01:06:24)
- 6 (2017-05-20 (土) 10:21:14)
- 7 (2017-05-20 (土) 23:18:19)
- 8 (2017-05-21 (日) 10:40:03)
- 9 (2017-05-21 (日) 22:20:16)
- 10 (2018-02-04 (日) 22:32:14)
- 11 (2020-01-03 (金) 08:55:02)
概要 †
- メモリ操作のためのAPI
- メモリはチャンクと呼ばれる塊単位で扱われ,コンテキスト(メモリチャンクを管理)に紐づくようになっている。
またメモリチャンクは,ブロックと呼ばれる領域で管理される。(詳細は,参考リンクの資料を参照) - コンテキストは木構造で管理されており,上位のコンテキストを破棄することで,下位のコンテキストの領域もまとめて解放することができる。
定義 †
マクロ †
MemoryContextAllocExtendedのフラグ †
マクロ名 | 説明 |
---|---|
MCXT_ALLOC_HUGE | |
MCXT_ALLOC_NO_OOM | |
MCXT_ALLOC_ZERO |
列挙型 †
構造体 †
MemoryContextCallback †
番号 | データ型 | フィールド | 説明 |
---|---|---|---|
1 | MemoryContextCallbackFunction | func | コールバック関数 |
2 | void* | arg | コールバック関数に渡される引数 |
3 | struct MemoryContextCallback | next | コールバック関数リストの次ノード。 コールバック関数はリスト構造で管理されており複数のコールバック関数を登録できる。 |
MemoryContext †
MemoryContextDataポインタの別名
// 引数1:アロケーションサイズ palloc0fast(sz)
参考 struct MemoryContextData - on doxygen.postgresql.org
関数 †
MemoryContextAlloc †
typedef struct MemoryContextData *MemoryContext;
- アロケーション処理は,AllocSetAlloc関数で行われる。
- 引数で指定されたメモリコンテキストに指定されたサイズのメモリ領域を確保する。
- チャンクリミットを超える場合は,新規にブロックが作成される。そうでない場合は,フリーリストから検索される。
- アクティブなアロケーションブロックにチャンクスペースがあれば,チャンクをブロックに確保しチャンクのポインタを返す。チャンクスペースがなければ,ブロックの残りの領域を整備しチャンクをフリーリストに置く。
- ブロックがなければ,新規にブロックを作成してチャンクのポインタを返す。
- マクロ定数MaxAllocSizeを超えるサイズはエラーになる。
参考 AllocSetAlloc() - on doxygen.postgresql.org
サンプル
// 引数1:アロケーション対象のコンテキスト // 引数2:割当てサイズ(byte) // 戻り値:メモリチャンクのポインタ extern void *MemoryContextAlloc(MemoryContext context, Size size);
MemoryContextAllocZero †
void memory_sample() { // 専用のコンテキストを作成 MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "mycontext", 0, 8 * 1024, 8 * 1024); MemoryContext oldcontext = NULL; // カレントコンテキストのスイッチ oldcontext = MemoryContextSwitchTo(context); // メモリチャンクが返される MyExtensionOptions *opt = (MyExtensionOptions*) MemoryContextAlloc(context, sizeof(MyExtensionOptions)); // pallocは,内部でCurrentMemoryContextを使う // MyExtensionOptions *opt = (MyExtensionOptions*)palloc(sizeof(MyExtensionOptions)); opt->optcontext = ForeignTableRelationId; opt->optname = pstrdup("option1"); MemoryContextSwitchTo(oldcontext); MemoryContextDelete(context); }
- MemoryContextAlloc()と同様にメモリ領域をコンキストに確保する。
- 確保されたチャンクを返す前に0初期化される。
- アライメントされているかがチェックされ,memsetをするかどうかが判定される。
MemoryContextAllocZeroAligned †
// 引数1:アロケーション対象のコンテキスト // 引数2:アロケーションサイズ(byte) // 戻り値:メモリチャンクのポインタ extern void *MemoryContextAllocZero(MemoryContext context, Size size);
- MemoryContextAlloc()と同様にメモリ領域をコンキストに確保する。
- MemoryContextAllocZero()との違いは,アライメントのチェックがない点。
MemoryContextAllocExtended †
// 引数1:アロケーション対象のコンテキスト // 引数2:アロケーションサイズ(byte) // 戻り値:メモリチャンクのポインタ extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
- 基本的には,MemoryContextAlloc()と同様にメモリ領域をコンキストに確保する。
- 違いは,フラグによって細かな動作を指定できる点である。
参考 MemoryContextAllocExtended () - on doxygen.postgresql.org
サンプル
// 引数1:アロケーション対象のコンテキスト // 引数2:アロケーションサイズ(byte) // 引数3:メモリアロケーション動作を決めるフラグ // 戻り値:メモリチャンクのポインタ extern void *MemoryContextAllocExtended(MemoryContext context, Size size, int flags);
palloc †
typedef struct MyExtensionOptions { const char *optname; Oid optcontext; } MyExtensionOptions; void memory_sample() { MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "mycontext", 0, 8 * 1024, 8 * 1024); MemoryContext oldcontext = NULL; oldcontext = MemoryContextSwitchTo(context); // 0クリア and メモリ確保失敗時にエラー報告 MyExtensionOptions *opt = (MyExtensionOptions*) MemoryContextAllocExtended(context, sizeof(MyExtensionOptions), MCXT_ALLOC_ZERO | MCXT_ALLOC_NO_OOM); opt->optcontext = ForeignTableRelationId; opt->optname = pstrdup("option1"); MemoryContextSwitchTo(oldcontext); MemoryContextDelete(context); }
- MemoryContextAlloc()と同様,現在のコンテキスト(CurrentMemoryContext)にメモリ領域を確保する。
- MemoryContextAlloc()は duplicate となっている。
参考 palloc() - on doxygen.postgresql.org
サンプル
// 引数1:アロケーションサイズ(byte) // 戻り値:メモリチャンクのポインタ extern void *palloc(Size size);
palloc0 †
MyExtensionOptions *opt = (MyExtensionOptions*)palloc(sizeof(MyExtensionOptions)); // 以下と同様である // MyExtensionOptions * opt = MemoryContextAlloc(CurrentMemoryContext, sizeof(MyExtensionOptions));
- MemoryContextAllocZero()と同様,メモリ領域を確保し0クリアして返す。
- MemoryContextAllocZero()は duplicates となっている。
palloc_extended †
// 引数1:アロケーションサイズ(byte) // 戻り値:メモリチャンクのポインタ extern void *palloc0(Size size);
- MemoryContextAllocExtended()と同様,メモリ領域を確保し0クリアして返す。
- MemoryContextAllocExtended()は duplicate となっている。
repalloc †
// 引数1:アロケーションサイズ(byte) // 引数2:メモリアロケーション動作を決めるフラグ // 戻り値:メモリチャンクのポインタ extern void *palloc_extended(Size size, int flags);
- reallocの処理のメインは,AllocSetRealloc関数が行なう。
- 既存のメモリチャンクの領域を再割り当てする。
- 既存のメモリチャンクよりsizeが小さい場合は,そのメモリチャンクのrequested_sizeを更新してポインタを返す。
- 既存のメモリチャンクがメモリチャンクリミットより大きかった場合は,チャンクを拡張する。
そうでない場合は,新しくメモリチャンクを確保し,既存のメモリチャンクは破棄する。
参考 AllocSetRealloc() - on doxygen.postgresql.org
サンプル
// 引数1:メモリチャンクのポインタ // 引数2:再割り当てするサイズ(byte) // 戻り値:新しいメモリチャンクのポインタ extern void *repalloc(void *pointer, Size size);
pfree †
char *optname = palloc(1 << 4); strcpy(optname, "hello world"); char *newoptname = repalloc(optname, 1 << 5); strcpy(newoptname, "hello world, hello postgres");
- 処理のメインはAllocSetFree関数で行われる。
- メモリチャンクを解放する。
- メモリチャンクリミットより大きかった場合は,メモリチャンクが属するブロックが解放される。
そうでない場合は,フリーリストに置かれる。
参考 AllocSetFree () - on doxygen.postgresql.org
MemoryContextAllocHuge †
// 引数1:メモリチャンクのポインタ extern void pfree(void *pointer);
- MemoryContextAlloc関数と同様だが,MemoryContextAllocよりも大きな上限sizeを指定できる。
- マクロ定数MaxAllocHugeSizeの値までsizeを指定することができる。
MaxAllocHugeSizeは,「-1 >> 1」( SIZE_MAX / 2)となっている。
repalloc_huge †
// 引数1:アロケーション対象のコンテキスト // 引数2:アロケーションサイズ(byte) // 戻り値:メモリチャンクのポインタ extern void *MemoryContextAllocHuge(MemoryContext context, Size size);
MemoryContextSwitchTo †
// 引数1:メモリチャンクのポインタ // 引数2:再割り当てするサイズ(byte) // 戻り値:新しいメモリチャンクのポインタ extern void *repalloc_huge(void *pointer, Size size);
MemoryContextRegisterResetCallback †
// 引数1:スイッチするメモリコンテキスト // 戻り値:古い(スイッチする前の)メモリコンテキスト MemoryContext MemoryContextSwitchTo(MemoryContext context)
MemoryContextStrdup †
void memory_sample() { MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "mycontext", 0, 8 * 1024, 8 * 1024); MemoryContext oldcontext = MemoryContextSwitchTo(context); StringInfo strinfo = makeStringInfo(); appendStringInfo(strinfo, "%s", "hoge"); elog(NOTICE, "%s", strinfo->data); MemoryContextSwitchTo(oldcontext); MemoryContextDelete(context); }
pstrdup †
// 引数1:対象のメモリコンテキスト // 引数2:reset/delete時に呼ばれるコールバック関数 extern void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb);
pnstrdup †
// callback function void report_context_delete(void *arg) { MemoryContext context = (MemoryContext)arg; elog(NOTICE, "%s will be deleted", context->name); } void memory_sample() { MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "mycontext", 0, 8 * 1024, 8 * 1024); // コールバック関数の宣言と初期化 MemoryContextCallback callback = { report_context_delete, // Function Pointer context, // Argument }; // コールバック関数の登録 MemoryContextRegisterResetCallback(context, &callback); MemoryContext oldcontext = MemoryContextSwitchTo(context); char *optname = palloc(16); strcpy(optname, "hello world"); MemoryContextSwitchTo(oldcontext); // report_context_delete(context) is called MemoryContextDelete(context); }
psprintf †
// 引数1:対象のメモリコンキスト // 引数2:複製するデータ // 戻り値:複製されたデータのポインタ extern char *MemoryContextStrdup(MemoryContext context, const char *string);
pvsnprintf †
// 引数1:複製するデータ // 戻り値:複製されたデータのポインタ extern char *pstrdup(const char *string);
サンプルプログラム †
// 引数1:複製するデータ // 引数2:複製するデータの長さ // 戻り値:複製されたデータのポインタ extern char *pnstrdup(const char *in, Size len);
参考・関連 †
- palloc.h - on doxygen.postgresql.org
- memnodes.h - on doxygen.postgresql.org
- mcxt.c - on doxygen.postgresql.org
- aset.c - on doxygen.postgresql.org
- NTTデータ 井久保さんによる解析資料 ~ メモリ管理 ~ - http://ikubo.x0.com/PostgreSQL/pg_source.htm
関連