Mesurer les coûts de mémoire pour les processus Postgres

Il s'agit d'une traduction libre d'un article de l' un des développeurs Postgres les plus puissants, Andres Freund. En plus du fait que le développeur est fort, l'article est également assez intéressant et révèle les détails du fonctionnement du système d'exploitation Linux.





Il est assez courant d'entendre des affirmations selon lesquelles les connexions post-grille utilisent trop de mémoire. Ceci est souvent mentionné lors de la comparaison du modèle de processus de gestion des connexions clientes avec un autre modèle, où chaque connexion est servie dans un thread séparé.





Quant à moi, il y a beaucoup de choses à discuter ici. De plus, vous pouvez apporter plusieurs améliorations et réduire l'utilisation de la mémoire.





Je pense que cette préoccupation concernant la surcharge de mémoire est due à une raison commune, à savoir que le moyen le plus simple de mesurer la consommation de mémoire via des utilitaires comme top et ps est assez trompeur.





En effet, il est particulièrement difficile de mesurer l'augmentation de la mémoire utilisée à chaque nouvelle connexion.





Dans cet article, je parlerai de Postgres fonctionnant sous Linux, car c'est dans ce sens que j'ai le plus d'expérience.





Et avant de continuer, je tiens à souligner qu'avec une mesure précise et précise, une connexion a un surcoût inférieur à 2MiB (voir les conclusions à la fin de l'article).





Au premier coup d'œil

, , ( ). (huge pages), . . , Postgres:





andres@awork3:~$ psql
postgres[2003213][1]=# SELECT pg_backend_pid();
┌────────────────┐
│ pg_backend_pid │
├────────────────┤
│        2003213 │
└────────────────┘
(1 row)

andres@awork3:~/src/postgresql$ ps -q 2003213 -eo pid,rss
    PID   RSS
2003213 16944
      
      



16MiB.





!?! ,

. , pgprewarm, (shared buffers):





postgres[2003213][1]=# SHOW shared_buffers ;
┌────────────────┐
│ shared_buffers │
├────────────────┤
│ 16GB           │
└────────────────┘
(1 row)

postgres[2003213][1]=# SELECT SUM(pg_prewarm(oid, 'buffer')) FROM pg_class WHERE relfilenode <> 0;
┌────────┐
│  sum   │
├────────┤
│ 383341 │
└────────┘

andres@awork3:~$ ps -q 2003213 -eo pid,rss
    PID   RSS
2003213 3169144
      
      



3GB. , , . , :





postgres[2003213][1]=# SELECT pg_size_pretty(SUM(pg_relation_size(oid))) FROM pg_class WHERE relfilenode <> 0;
┌────────────────┐
│ pg_size_pretty │
├────────────────┤
│ 2995 MB        │
└────────────────┘
(1 row)
      
      



, , :





postgres[3244960][1]=# SELECT sum(abalance) FROM pgbench_accounts ;
┌─────┐
│ sum │
├─────┤
│   0 │
└─────┘
(1 row)

andres@awork3:~/src/postgresql$ ps -q 3244960 -eo pid,rss
    PID   RSS
3244960 2700372
      
      



, Postgres 3GB 2.7GB . , huge_pages=off, ps (shred - ) , . .





- 4KiB, , 2MiB.





, , . Debian wiki .





huge_pages=on, . , " ":





andres@awork3:~$ ps -q 3245907 -eo pid,rss
    PID   RSS
3245907  7612
      
      



, 7MiB. (page table) , - , 512 (4KiB * 512 = 2MiB).





:





postgres[3245843][1]=# ;SELECT SUM(pg_prewarm(oid, 'buffer')) FROM pg_class WHERE relfilenode <> 0;
postgres[3245851][1]=# SELECT sum(abalance) FROM pgbench_accounts ;

andres@awork3:~$ ps -q 3245907,3245974 -eo pid,rss
    PID   RSS
3245907 12260
3245974  8936
      
      



, 12MiB 9MiB , 3GiB 2.7GiB.





.





, Linux , , : RSS ps top.





4.5, /proc/$pid/status :





  • VmRSS . (VmRSS = RssAnon + RssFile + RssShmem)





  • RssAnon .





  • RssFile .





  • RssShmem ( SysV shm, tmpfs )





andres@awork3:~$ grep -E '^(Rss|HugetlbPages)' /proc/3247901/status
RssAnon:	    2476 kB
RssFile:	    5072 kB
RssShmem:	    8520 kB
HugetlbPages:	       0 kB

postgres[3247901][1]=# SELECT SUM(pg_prewarm(oid, 'buffer')) FROM pg_class WHERE relfilenode <> 0;

andres@awork3:~$ ps -q 3247901 -eo pid,rss
    PID   RSS
3247901 3167164

andres@awork3:~$ grep -E '^(Rss|HugetlbPages)' /proc/3247901/status
RssAnon:	    3148 kB
RssFile:	    9212 kB
RssShmem:	 3154804 kB
HugetlbPages:	       0 kB
      
      



RssAnon "" , .. . RssFile , postgres. RssShmem .





ps - - .





, huge_pages=on:





andres@awork3:~$ grep -E '^(Rss|HugetlbPages)' /proc/3248101/status
RssAnon:	    2476 kB
RssFile:	    4664 kB
RssShmem:	       0 kB
HugetlbPages:	  778240 kB

postgres[3248101][1]=# SELECT SUM(pg_prewarm(oid, 'buffer')) FROM pg_class WHERE relfilenode <> 0;

andres@awork3:~$ grep -E '^(Rss|HugetlbPages)' /proc/3248101/status
RssAnon:	    3136 kB
RssFile:	    8756 kB
RssShmem:	       0 kB
HugetlbPages:    3846144 kB
      
      



, . :





, RssFile - (Postgres mmap() - ). .





, RssAnon . ps , postgres ( postmaster). Linux ( fork()), Copy-on-Write , .





, . , 4.14 ( ) /proc/$pid/smaps_rollup . Pss " " ( smaps_rollups Pss ). , .





postgres[2004042][1]=# SELECT SUM(pg_prewarm(oid, 'buffer')) FROM pg_class WHERE relfilenode <> 0;
┌────────┐
│  sum   │
├────────┤
│ 383341 │
└────────┘
(1 row)

postgres[2004042][1]=# SHOW huge_pages ;
┌────────────┐
│ huge_pages │
├────────────┤
│ off        │
└────────────┘
(1 row)

andres@awork3:~$ grep ^Pss /proc/2004042/smaps_rollup
Pss:             3113967 kB
Pss_Anon:           2153 kB
Pss_File:           3128 kB
Pss_Shmem:       3108684 kB
      
      



Pss_Anon , Pss_File , Pss_Shmem ( ) .





, . pgbench (scale 1000, -S -M prepared -c 1024) :





postgres[2004042][1]=# SELECT count(*) FROM pg_stat_activity ;
┌───────┐
│ count │
├───────┤
│  1030 │
└───────┘
(1 row)

postgres[2004042][1]=# SELECT pid FROM pg_stat_activity WHERE application_name = 'pgbench' ORDER BY random() LIMIT 1;
┌─────────┐
│   pid   │
├─────────┤
│ 3249913 │
└─────────┘
(1 row)

andres@awork3:~$ grep ^Pss /proc/3249913/smaps_rollup
Pss:                4055 kB
Pss_Anon:           1185 kB
Pss_File:              6 kB
Pss_Shmem:          2863 kB
      
      



huge_pages=on:





andres@awork3:~$ grep ^Pss /proc/2007379/smaps_rollup
Pss:                1179 kB
Pss_Anon:           1173 kB
Pss_File:              6 kB
Pss_Shmem:             0 kB
      
      



Pss , . , . `/proc/$pid/status`.





, , VmPTE ( ) , Vm* , VmStk copy-on-write.





, huge_pages=off:





andres@awork3:~$ grep ^VmPTE /proc/2004042/status
VmPTE:      6480 kB
      
      



huge_pages=on:





VmPTE:	     132 kB
      
      



- , , .





Sur la base de ces mesures, nous pouvons imaginer qu'un processus effectuant un chargement OLTP en lecture seule assez simple a un surcoût d'environ 7,6 Mio avec énorme_pages = off et d'environ 1,3 Mio avec énorme_pages = on incluant Pss_Anon dans VmPTE.





Même si nous imaginons qu'il existe une sorte de surcharge « invisible », et une grande quantité de données dans le tampon, etc., je pense que nous reviendrons à ma déclaration précédente selon laquelle la surcharge de connexion est inférieure à 2 Mio.





Supplément du traducteur. Postgres 14 introduit une nouvelle vue pg_backend_memory_contexts qui montre l'utilisation détaillée de la mémoire par le processus actuel du point de vue de Postgres lui-même.








All Articles