- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- ソース を表示
- PostgreSQL/開発/include/utils/memutils.h へ行く。
- 概要
- 定義
- マクロ
- 列挙型
- 構造体
- 関数
- MemoryContextInit
- MemoryContextReset
- MemoryContextDelete
- MemoryContextResetOnly
- MemoryContextResetChildren
- MemoryContextDeleteChildren
- MemoryContextSetParent
- GetMemoryChunkSpace
- GetMemoryChunkContext
- MemoryContextGetParent
- MemoryContextIsEmpty
- MemoryContextStats
- MemoryContextAllowInCriticalSection
- MemoryContextCheck
- MemoryContextContains
- MemoryContextCreate
- AllocSetContextCreate
- サンプルプログラム
- 参考・関連
- コメント
概要 †
- メモリアロケーションのユーティリティ機能
定義 †
マクロ †
MaxAllocSize, MaxAllocHugeSize †
マクロ名 | 説明 | 値 |
---|---|---|
MaxAllocSize | アロケーションの最大サイズ(1G-1)。 pallocでは,このサイズがリミットである。 | (Size) 0x3fffffff |
MaxAllocHugeSize | アロケーションの最大サイズ(SIZE_MAX/2)。 XXXHogeやXXX_huge系の関数ではこのリミットとなる。 | (Size) -1 >> 1 |
このマクロ定数を直接使うシーンはあまりない。AllocHugeSizeIsValidやAllocSizeIsValidなどのチェックマクロがMemoryAllocXXXX関数で使われている。
AllocSizeIsValid, AllocHugeSizeIsValid †
#define AllocSizeIsValid(size) ((Size) (size) <= MaxAllocSize) #define AllocHugeSizeIsValid(size) ((Size) (size) <= MaxAllocHugeSize)
サイズが最大サイズ以下かチェックする。
STANDARDCHUNKHEADERSIZE †
#define STANDARDCHUNKHEADERSIZE MAXALIGN(sizeof(StandardChunkHeader))
- メモリチャンクのアライメントされたヘッダサイズ
MemoryContextResetAndDeleteChildren †
#define MemoryContextResetAndDeleteChildren(ctx) MemoryContextReset(ctx)
- MemoryContextReset関数を呼ぶ。後方互換のためのマクロ。
ALLOCSET_DEFAULT_XXXX †
定数 | 説明 | 値 |
---|---|---|
ALLOCSET_DEFAULT_MINSIZE | 0 | |
ALLOCSET_DEFAULT_INITSIZE | (8 * 1024) | |
ALLOCSET_DEFAULT_MAXSIZE | (8 * 1024 * 1024) |
アロケーション時に使用する定型サイズのためのマクロ定数。
サンプル
MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "my context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE);
ALLOCSET_SMALL_XXXX †
定数 | 説明 | 値 |
---|---|---|
ALLOCSET_SMALL_MINSIZE | 0 | |
ALLOCSET_SMALL_INITSIZE | (1 * 1024) | |
ALLOCSET_SMALL_MAXSIZE | (8 * 1024) |
アロケーション時に使用する定型サイズのためのマクロ定数で,比較的小さな領域の場合。
ALLOCSET_SEPARATE_THRESHOLD †
列挙型 †
構造体 †
StandardChunkHeader †
番号 | データ型 | フィールド | 説明 |
---|---|---|---|
1 | MemoryContext | context | 所属するコンテキスト |
2 | Size | size | メモリチャンクに割り当てられたサイズ(byte) |
3 | Size | requested_size | リクエストされたサイズ(byte) |
関数 †
MemoryContextInit †
#define ALLOCSET_SEPARATE_THRESHOLD 8192
- メモリコンテスト管理システムの初期化を行なう。
- postmasterのスタートアップ時に呼ばれるので,拡張機能などでこの関数を呼ぶケースはない(すでにメモリコンテキスト管理が利用できる状態になっているため)。
- この処理の中で,TopMemoryContextというメモリコンテキストツリーのトープレベルのメモリコンテキストとErrorContextが作成される。
参考 MemoryContextInit() - on doxygen.postgresql.org
MemoryContextReset †
extern void MemoryContextInit(void);
- 指定されたメモリコンテキスト及び子階層に割り当てられたメモリ領域を解放する。
- 子階層のメモリコンテキストに対しては,MemoryContextDelete()(AllocSetDelete())を再帰的に呼ぶ。
- 対象のメモリコンテキスト(context)については,MemoryContextResetOnly()(AllocSetReset())が呼ばれる。contextの最初のブロック(存在すれば)は残され,メモリチャンクは消去される(freeptrは先頭にポイントされる)。
参考
- AllocSetDelete() - on doxygen.postgresql.org
- AllocSetReset() - on doxygen.postgresql.org
MemoryContextDelete †
// 引数1:対象のメモリコンテキスト extern void MemoryContextReset(MemoryContext context);
- 指定されたメモリコンテキストのメモリ領域を解放する。
- 子階層のメモリコンテキストも再帰的に処理される。
参考 MemoryContextDelete() - on doxygen.postgresql.org
MemoryContextResetOnly †
// 引数1:対象のメモリコンテキスト extern void MemoryContextDelete(MemoryContext context);
- 指定されたメモリコンテキストをリセットする(AllocSetReset()が呼ばれる)。
- 子階層のメモリコンテキストに対しては何もしない。
MemoryContextResetChildren †
// 引数1:対象のメモリコンテキスト extern void MemoryContextResetOnly(MemoryContext context);
- 指定されたメモリコンテキストの子階層のメモリコンテキストに対して,再帰的にMemoryContextResetOnly関数を呼ぶ。
MemoryContextDeleteChildren †
// 引数1:対象のメモリコンテキスト extern void MemoryContextResetChildren(MemoryContext context);
- 指定されたメモリコンテキストの子階層のメモリコンテキストに対して,再帰的にMemoryContextDelete関数を呼ぶ。
サンプル
// 引数1:対象のメモリコンテキスト extern void MemoryContextDeleteChildren(MemoryContext context);
MemoryContextSetParent †
#define BLOCK_SIZE 1024 * 8 void reset_callback(void *arg) { MemoryContext context = (MemoryContext)arg; elog(NOTICE, "%s will be deleted.", context->name); } void sample() { MemoryContext oldcontext = NULL; MemoryContextCallback callback; MemoryContextCallback callback2; // init parent context MemoryContext parent_context = AllocSetContextCreate(CurrentMemoryContext, "parent context", 0, BLOCK_SIZE, BLOCK_SIZE); callback.func = reset_callback; callback.arg = parent_context; MemoryContextRegisterResetCallback(parent_context, &callback); oldcontext = MemoryContextSwitchTo(parent_context); // parent context from here StringInfo strinfo = makeStringInfo(); appendStringInfo(strinfo, "Hello %s", "Duke"); elog(NOTICE, "%s", strinfo->data); // init child context MemoryContext child_context = AllocSetContextCreate(parent_context, "child context", 0, BLOCK_SIZE, BLOCK_SIZE); callback2.func = reset_callback; callback2.arg = child_context; MemoryContextRegisterResetCallback(child_context, &callback2); MemoryContextSwitchTo(child_context); // child context from here StringInfo strinfo2 = makeStringInfo(); appendStringInfo(strinfo2, "Hello %s", "Togo"); elog(NOTICE, "%s", strinfo2->data); // switch back to original context. MemoryContextSwitchTo(oldcontext); // delete parent_context and child_context // // CurrentMemoryContext // |- parent_context <--- delete // |- child_context <--- delete MemoryContextDeleteChildren(CurrentMemoryContext); }
- 指定されたメモリコンテキスト(context)を新しいメモリコンテスト(new_parent)に付け替える。
参考 MemoryContextSetParent() - on doxygen.postgresql.org
GetMemoryChunkSpace †
// 引数1:対象のメモリコンテキスト // 引数2:新しい親となるメモリコンテキスト extern void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent); /* Change a context to belong a new parent. == Before == new_parent current_parent |- context1 |- context <-- move to (o) |- context2 |- next_context == After == new_parent current_parent |- context (o) |- next_context |- context1 |- context2 */
- 指定されたメモリチャンクのサイズを返す(ヘッダサイズ含む)。
サンプル
// 引数1:メモリチャンクのポインタ // 戻り値:メモリチャンクサイズ(ヘッダ含む) extern Size GetMemoryChunkSpace(void *pointer);
GetMemoryChunkContext †
void test_chunk_space() { elog(NOTICE, "STANDARDCHUNKHEADERSIZE = %d", STANDARDCHUNKHEADERSIZE); char *chunk1 = palloc(128); // 128 + STANDARDCHUNKHEADERSIZE elog(NOTICE, "%d", GetMemoryChunkSpace(chunk1)); // NOTICE: 152 char *chunk2 = palloc(256-32); // 256 + STANDARDCHUNKHEADERSIZE elog(NOTICE, "%d", GetMemoryChunkSpace(chunk2)); // NOTICE: 280 }
- 指定されたメモリチャンクの所属するメモリコンテキストを返す。
サンプル
// 引数1:メモリチャンクのポインタ // 戻り値:メモリチャンクが属するメモリコンテキスト extern MemoryContext GetMemoryChunkContext(void *pointer);
MemoryContextGetParent †
void test_chunk() { MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "my context", 0, 1024 * 8, 1024 * 8); MemoryContext oldcontext = MemoryContextSwitchTo(context); StringInfo strinfo = makeStringInfo(); elog(NOTICE, "%s", GetMemoryChunkContext(strinfo)->name); // NOTICE: my contex MemoryContextSwitchTo(oldcontext); MemoryContextDelete(context); }
- 指定されたメモリコンテキストの親のメモリコンテキストを返す。
MemoryContextIsEmpty †
// 引数1:対象のメモリコンテキスト // 戻り値:contextの親のメモリコンテスト extern MemoryContext MemoryContextGetParent(MemoryContext context);
- 対象のメモリコンテストが空であるか否かを返す。
- firstchildを持っていない場合はtrue。
- メモリコンテキストが新しい場合またはリセットされている場合はtrue。
参考
- AllocSetIsEmpty() - on doxygen.postgresql.org
- MemoryContextIsEmpty() - on doxygen.postgresql.org
MemoryContextStats †
// 引数1:対象のメモリコンテキスト // 戻り値:true:空,false:空でない extern bool MemoryContextIsEmpty(MemoryContext context);
- 指定されたメモリコンテキストの統計情報を出力する。
サンプル
// 引数1:対象のメモリコンテキスト extern void MemoryContextStats(MemoryContext context);
参考 MemoryContextStats() - on doxygen.postgresql.org
MemoryContextAllowInCriticalSection †
void test_chunk() { MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "my context", 0, 1024 * 8, 1024 * 8); MemoryContext oldcontext = MemoryContextSwitchTo(context); StringInfo strinfo = makeStringInfo(); elog(NOTICE, "%s", GetMemoryChunkContext(strinfo)->name); // NOTICE: my contex MemoryContextStats(context); // my context: 8192 total in 1 blocks; 7056 free (0 chunks); 1136 used MemoryContextSwitchTo(oldcontext); MemoryContextDelete(context); }
- 指定されたメモリコンテキストで,クリティカルセクション内でのメモリアロケーションの許可/不許可を設定する。
- デバッグ時に有効,一時的に許可など。
参考 palloc() - on doxygen.postgresql.org
実験
// 引数1:対象のメモリコンテキスト // 引数2:クリティカルセクションのメモリアローケーションを許可するか否か // true:許可する,false:許可しない extern void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow);
MemoryContextCheck †
// // Debug, on enable assertion // void test_crit() { MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "my context", 0, 1024 * 8, 1024 * 8); MemoryContextAllowInCriticalSection(context, true); // 許可しない,trueだと下のpallocは成功する // context->allowInCritSection = false; // 許可しない,trueだと下のpallocは成功する MemoryContext oldcontext = MemoryContextSwitchTo(context); START_CRIT_SECTION(); // クリティカルセクション内でのメモリアローケーションは通常許可されない void *chunk = palloc(128); // TRAP: FailedAssertion("!(CritSectionCount == 0 || (CurrentMemoryContext)->allowInCritSection)", File: "mcxt.c", Line: 818) END_CRIT_SECTION(); MemoryContextSwitchTo(oldcontext); MemoryContextDelete(context); }
- デバッグ用の関数。
- ブロックリスト,チャンクを操作し整合性をチェックする。
- AllocSetCheck関数が呼ばれる。
MemoryContextContains †
// 引数1:対象のメモリコンテキスト extern void MemoryContextCheck(MemoryContext context);
- メモリチャンクが指定されたメモリコンテキストに属するかを判定する。
- メモリチャンクのヘッダに登録されているメモリコンテキストが指定されたメモリコンテキストと等しいかチェックする。
参考 MemoryContextContains() - on doxygen.postgresql.org
サンプル
// 引数1:対象のメモリコンテキスト // 引数2:メモリチャンクのポインタ // 戻り値:true:含まれる,false:含まれない extern bool MemoryContextContains(MemoryContext context, void *pointer);
MemoryContextCreate †
void test_chunk_contains() { void *chunk = palloc(128); elog(NOTICE, "%d", MemoryContextContains(CurrentMemoryContext, chunk)); // NOTICE: 1 pfree(chunk); }
- メモリコンテキストタイプ(tag)を指定して,メモリコンテストを作成する。通常のMemoryContextXXX関数は,T_AllocSetContextというタグが使われる。
- 最近のバージョンでは,slab.cという新しいメモリコンテキスト実装が追加されている。
参考
- slab.c - on doxygen.postgresql.org
- aset.c - on doxygen.postgresql.org
- AllocSetContextCreate() - on doxygen.postgresql.org
AllocSetContextCreate †
// 引数1:ノードタグ // 引数2:メモリコンテキストのサイズ(byte) // 引数3:メモリコンテキスト操作で使用される関数群 // 引数4:親のメモリコンテキスト // 引数5:メモリコンテキスト名 // 戻り値:作成されたメモリコンテキスト extern MemoryContext MemoryContextCreate(NodeTag tag, Size size, MemoryContextMethods *methods, MemoryContext parent, const char *name);
- AllocSetContextを作成する。この中でMemoryContextCreate関数が呼ばれている。
サンプル
// 引数1:親のメモリコンテキスト // 引数2:メモリコンテキストの名前 // 引数3:最小のコンテキストサイズ // 引数4:初期ブロックサイズ // 引数5:最大ブロックサイズ // 戻り値:作成されたメモリコンテキスト extern MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize);
サンプルプログラム †
void test_context_create() { MemoryContext context = AllocSetContextCreate(CurrentMemoryContext, "my context", 0, 1024 * 8, 1024 * 8); }
参考・関連 †
- memutils.h - on doxygen.postgresql.org
- aset.c - on doxygen.postgresql.org
- mcxt.c - on doxygen.postgresql.org
- palloc.h
関連