7. 7
Создание процесса
PostgresMain()
InitProcess() //инициализировать структуру PGPROC для процесса
InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL);
InitProcessPhase2(); //добавить запись PGPROC в ProcArray
ProcSignalInit(MyBackendId); //добавить запись в ProcSignal
RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
IdleInTransactionSessionTimeoutHandler);
RelationCacheInitialize(); //хэш-таблица RelationIdCache
InitCatalogCache(); //массив CatCache *SysCache[SysCacheSize]
InitPlanCache(); //регистрация callback-функций
RelationCacheInitializePhase2(); //кэшировать записи основных глобальных
//таблиц каталога
...
8. 8
Чтение данных каталога в кэш
RelationCacheInitializePhase2()
RelationMapInitializePhase2() //загрузить данные из pg_filenode.map
if (!load_relcache_init_file(true)) //пытаемся прочитать pg_internal.init
{
formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
true, Natts_pg_database, Desc_pg_database);
formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
true, Natts_pg_authid, Desc_pg_authid);
formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
false, Natts_pg_auth_members, Desc_pg_auth_members);
formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
false, Natts_pg_shseclabel, Desc_pg_shseclabel);
}
9. 9
Чтение данных каталога в кэш
load_relcache_init_file() //пытаемся прочитать pg_internal.init
for (relno = 0; relno < num_rels; relno++)
{
//вставить запись в хэш-таблицу RelationIdCache
RelationCacheInsert(rels[relno], false);
}
formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
true, Natts_pg_database, Desc_pg_database);
//Создать новый дескриптор relation
//инициализировать без обращения к каталогу
//вставить запись в хэш-таблицу RelationIdCache
RelationCacheInsert(relation, false);
11. 11
Создание процесса
(продолжение)
PostgresMain()
InitProcess() //инициализировать структуру PGPROC для процесса
InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL);
...
RelationCacheInitializePhase2(); //кэшировать основные глобальные
//таблицы каталога
PerformAuthentication(); //выполнить аутентификацию клиента
MyProc->databaseId = MyDatabaseId; //Подключиться к базе
SetDatabasePath(fullpath);
RelationCacheInitializePhase3(); //кэшировать таблицы и индексы каталога
12. 12
Чтение данных каталога в кэш
RelationCacheInitializePhase3()
if(!load_relcache_init_file(false)) //пытаемся прочитать pg_internal.init
{
formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
true, Natts_pg_class, Desc_pg_class);
formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
false, Natts_pg_attribute, Desc_pg_attribute);
formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
true, Natts_pg_proc, Desc_pg_proc);
formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
true, Natts_pg_type, Desc_pg_type);
}
load_critical_index() //загружаем критические индексы
//обновляем и дополняем все записи RelationIdCache
InitCatalogCachePhase2(); //завершаем инициализацию массива SysCache
CatalogCacheInitializeCache()
13. 13
SysCache
src/backend/utils/cache/lsyscache.c
char *get_attname(Oid relid, AttrNumber attnum);
Oid get_atttype(Oid relid, AttrNumber attnum);
Oid get_commutator(Oid opno);
Oid get_negator(Oid opno);
char *get_func_name(Oid funcid);
Oid get_func_rettype(Oid funcid);
bool func_strict(Oid funcid);
char func_volatile(Oid funcid);
16. 16
Prepared statements
PREPARE usrrptplan (int) AS
SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid
AND l.date = $2;
EXECUTE usrrptplan(1, current_date);
select * from pg_prepared_statements;
name | usrrptplan
statement | PREPARE usrrptplan (int) AS +
| SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid+
| AND l.date = $2;
prepare_time | 2016-04-28 13:42:57.3563+03
parameter_types | {integer,"time without time zone"}
from_sql | t
24. 24
Переключение контекстов
src/backend/utils/mmgr/mcxt.c
MemoryContext tempContext = AllocSetContextCreate(….);
MemoryContext saveContext = MemoryContextSwitchTo(tempContext);
/* делаем что-то в новом контексте */
char * x = palloc(128);
char * y = palloc(256);
. . . . . . . . . . . . . . . . . .
MemoryContextSwitchTo(saveContext);
MemoryContextDelete(tempContext);
25. 25
AllocSetContext
src/backend/utils/mmgr/aset.c
typedef struct AllocSetContext
{
MemoryContextData header; /* Standard memory-context fields */
AllocBlock blocks; /* head of list of blocks in this set */
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
Size initBlockSize;
Size maxBlockSize;
Size nextBlockSize; /* next block size to allocate */
Size allocChunkLimit;
AllocBlock keeper;
} AllocSetContext;
26. 26
AllocBlock
src/backend/utils/mmgr/aset.c
typedef struct AllocBlockData
{
AllocSet aset; /* aset that owns this block */
AllocBlock next; /* next block in aset's blocks list */
char *freeptr; /* start of free space in this block */
char *endptr; /* end of space in this block */
} AllocBlockData;
MemoryContext AllocSetContextCreate(MemoryContext parent,
const char *name,
Size minContextSize,
Size initBlockSize,
Size maxBlockSize);
28. 28
AllocChunk
src/backend/utils/mmgr/aset.c
typedef struct AllocChunkData
{
/* aset is the owning aset if allocated, or the freelist link if free */
void *aset;
/* size is always the size of the usable space in the chunk */
Size size;
#ifdef MEMORY_CONTEXT_CHECKING
/* when debugging memory usage, also store actual requested size */
Size requested_size;
#endif
} AllocChunkData;
33. 33
Источники потерь
●
Выделение множества мелких кусочков памяти
– сопоставимых с заголовком чанка (16 байт)
●
Выделение кусочков размера 2N
+ o
●
Создание множества контекстов под мелкие запросы
●
Увеличение размера выделенной памяти (repalloc)