Postgresql – Mismatch between size computed from pg_buffercahce Vs shared_buffers in postgresql

postgresqlpsql

I have a rather naive question regarding the size of shared_buffers computed from pg_buffercache and the shared_buffers size mentioned in postgresql.conf. Based on my understanding pg_buffercache shows the state of all the buffers in shared_buffers. Thus, size of shared buffers = Number of entries in pg_buffercache * Size of one page (8192 bytes). When I run this on my system :

    test=# select count(1) from pg_buffercache;
    count 
    -------
    3072
    (1 row)

    test=# show shared_buffers;
    shared_buffers 
    ----------------
    24MB
    (1 row)

Calculated size of shared buffers = 3072 * 8192 ~= 25.17 MB.
Actual size of shared buffers = 24 MB.

Why is there a difference between the computed size of shared buffers and the actual size of shared buffers ? Let me know if my understanding is wrong.

Thanks.

Best Answer

Looks like MB vs MiB, ie decimal SI vs binary megabyte:

regress=> SELECT round(25.17*1000*1000 / (1024*1024),1);
 round 
-------
  24.0
(1 row)

You've done your conversion into megabytes using decimal SI units (MB) not binary megabytes (MiB). Divide by 1024 not by 1000, or use pg_size_pretty:

regress=> select pg_size_pretty( 3072 * 8192::bigint );
 pg_size_pretty 
----------------
 24 MB
(1 row)

Compare:

regress=> select 
          pg_size_pretty( 3072 * 8192::bigint ),
          (3072::real * 8192)/(1024*1024) AS binaryMiB,
          (3072::real * 8192)/(1000*1000) AS decimalMB_SI;
 pg_size_pretty | binarymib | decimalmb_si 
----------------+-----------+--------------
 24 MB          |        24 |    25.165824
(1 row)

The GUC display code uses kiB / MiB / GiB too, but (IMO) mislabels it kB / MB / GB:

regress=> SELECT 24*1024*1024;
 ?column? 
----------
 25165824
(1 row)

regress=> SET work_mem = 25165824;
SET
regress=> SHOW work_mem;
 work_mem 
----------
 24GB
(1 row)

(It's GB because work_mem is measured in kb not bytes; ignore the factor-of-1024 difference).