Mémoire partagée pour PostgreSQL

En faisant quelques recherches pour mon prochain article dans GLMF, j'ai aperçu un bout de code dans le code du collecteur de statistiques qui m'a beaucoup intéressé. Pour les curieux, c'est dans src/backend/postmaster/pgstat.c :

 /*
  * Initialize the shared status array during postmaster startup.
  */
 void
 CreateSharedBackendStatus(void)
 {
 	Size		size = BackendStatusShmemSize();
 	bool		found;
 
 	/* Create or attach to the shared array */
 	BackendStatusArray = (PgBackendStatus *)
 		ShmemInitStruct("Backend Status Array", size, &found);
 
 	if (!found)
 	{
 		/*
 		 * We're the first - initialize.
 		 */
 		MemSet(BackendStatusArray, 0, size);
 	}
 }

Le collecteur, comme la plupart des processus du serveur PostgreSQL, utilise un bout de mémoire partagée. Apparemment, la fonction d'initialisation s'appelle ShmemInitStruct et lui est fournie une description de l'utilité de la mémoire partagée, et sa taille. J'ai jeté un oeil sur cette fonction (code source src/backend/storage/ipc/shmem.c). Après quelques tests, on voit que le code va allouer la mémoire. Ça se trouve sur la ligne :

 structPtr = ShmemAlloc(size);

J'ai donc ajouté une ligne de code dans l'espoir de tracer toutes les allocations de mémoire partagée :

 ereport(LOG,
   (errmsg("allocate shared memory segment \"%s\", size %d",
     name, (int)size)));

Après compilation et installation, je redémarre le serveur et j'obtiens ceci :

 LOG:  allocate shared memory segment "Control File", size 392
 LOG:  allocate shared memory segment "XLOG Ctl", size 73936
 LOG:  allocate shared memory segment "CLOG Ctl", size 131296
 LOG:  allocate shared memory segment "SUBTRANS Ctl", size 262880
 LOG:  allocate shared memory segment "Prepared Transaction Table", size 3488
 LOG:  allocate shared memory segment "MultiXactOffset Ctl", size 65760
 LOG:  allocate shared memory segment "MultiXactMember Ctl", size 131456
 LOG:  allocate shared memory segment "Shared MultiXact State", size 840
 LOG:  allocate shared memory segment "Buffer Descriptors", size 147456
 LOG:  allocate shared memory segment "Buffer Blocks", size 25165824
 LOG:  allocate shared memory segment "Shared Buffer Lookup Table", size 1088
 LOG:  allocate shared memory segment "Buffer Strategy Status", size 20
 LOG:  allocate shared memory segment "LOCK hash", size 1088
 LOG:  allocate shared memory segment "PROCLOCK hash", size 1088
 LOG:  allocate shared memory segment "Proc Header", size 12
 LOG:  allocate shared memory segment "AuxiliaryProcs", size 1392
 LOG:  allocate shared memory segment "Proc Array", size 440
 LOG:  allocate shared memory segment "Backend Status Array", size 123600
 LOG:  allocate shared memory segment "shmInvalBuffer", size 66384
 LOG:  allocate shared memory segment "Free Space Map Header", size 40
 LOG:  allocate shared memory segment "Free Space Map Hash", size 1088
 LOG:  allocate shared memory segment "PMSignalFlags", size 24
 LOG:  allocate shared memory segment "Background Writer Data", size 49188
 LOG:  allocate shared memory segment "AutoVacuum Data", size 144
 LOG:  allocate shared memory segment "BTree Vacuum State", size 1248
 LOG:  allocate shared memory segment "Sync Scan Locations List", size 488

On se rend compte que shared_buffers n'est évidemment pas la seule mémoire partagée à être allouée. Néanmoins, c'est de loin la plus importante. L'allocation totale est de 26230660 octets (soit 26 Mo), dont 24 Mo pour shared_buffers. Le reste est alloué par le collecteur (« Backend Status Array »), par le bgwriter (« Background Writer Data »), par l'autovacuum (« AutoVacuum Data »), par la structure FSM (« Free Space Map Header » et « Free Space Map Hash »), wal_buffers (« XLOG Ctl »), etc., etc.

Ça démontre bien pourquoi il ne faut pas que la valeur de SHMALL soit strictement identique à shared_buffers. Une valeur un peu supérieure, même pour un serveur dédié à PostgreSQL, est nécessaire.

Ajouter un commentaire

Les commentaires peuvent être formatés en utilisant une syntaxe wiki simplifiée.

Fil des commentaires de ce billet