Thread
Commits
-
Rework handling of pending data for backend statistics
- 4feba03d8b92 18.0 landed
-
Rename some pgstats callbacks related to flush of entries
- 28de66cee5f4 18.0 landed
-
Relax regression test for fsync check of backend-level stats
- 546371599e76 18.0 landed
-
Add backend-level statistics to pgstats
- 9aea73fc61d4 18.0 landed
-
Extract logic filling pg_stat_get_io()'s tuplestore into its own routine
- ff7c40d7fd6a 18.0 landed
-
Tweak some comments related to variable-numbered stats in pgstat.c
- fee2b3ea2ecd 18.0 landed
-
per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-02T14:55:52Z
Hi hackers, Please find attached a patch to implement $SUBJECT. While pg_stat_io provides cluster-wide I/O statistics, this patch adds a new pg_my_stat_io view to display "my" backend I/O statistics and a new pg_stat_get_backend_io() function to retrieve the I/O statistics for a given backend pid. By having the per backend level of granularity, one could for example identify which running backend is responsible for most of the reads, most of the extends and so on... The pg_my_stat_io view could also be useful to check the impact on the I/O made by some operations, queries,... in the current session. Some remarks: - it is split in 2 sub patches: 0001 introducing the necessary changes to provide the pg_my_stat_io view and 0002 to add the pg_stat_get_backend_io() function. - the idea of having per backend I/O statistics has already been mentioned in [1] by Andres. Some implementation choices: - The KIND_IO stats are still "fixed amount" ones as the maximum number of backend is fixed. - The statistics snapshot is made for the global stats (the aggregated ones) and for my backend stats. The snapshot is not build for all the backend stats (that could be memory expensive depending on the number of max connections and given the fact that PgStat_IO is 16KB long). - The above point means that pg_stat_get_backend_io() behaves as if stats_fetch_consistency is set to none (each execution re-fetches counters from shared memory). - The above 2 points are also the reasons why the pg_my_stat_io view has been added (as its results takes care of the stats_fetch_consistency setting). I think that makes sense to rely on it in that case, while I'm not sure that would make a lot of sense to retrieve other's backend I/O stats and taking care of stats_fetch_consistency. [1]: https://www.postgresql.org/message-id/20230309003438.rectf7xo7pw5t5cj%40awork3.anarazel.de Looking forward to your feedback, Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Kyotaro Horiguchi <horikyota.ntt@gmail.com> — 2024-09-03T06:37:49Z
At Mon, 2 Sep 2024 14:55:52 +0000, Bertrand Drouvot <bertranddrouvot.pg@gmail.com> wrote in > Hi hackers, > > Please find attached a patch to implement $SUBJECT. > > While pg_stat_io provides cluster-wide I/O statistics, this patch adds a new > pg_my_stat_io view to display "my" backend I/O statistics and a new > pg_stat_get_backend_io() function to retrieve the I/O statistics for a given > backend pid. > > By having the per backend level of granularity, one could for example identify > which running backend is responsible for most of the reads, most of the extends > and so on... The pg_my_stat_io view could also be useful to check the > impact on the I/O made by some operations, queries,... in the current session. > > Some remarks: > > - it is split in 2 sub patches: 0001 introducing the necessary changes to provide > the pg_my_stat_io view and 0002 to add the pg_stat_get_backend_io() function. > - the idea of having per backend I/O statistics has already been mentioned in > [1] by Andres. > > Some implementation choices: > > - The KIND_IO stats are still "fixed amount" ones as the maximum number of > backend is fixed. > - The statistics snapshot is made for the global stats (the aggregated ones) and > for my backend stats. The snapshot is not build for all the backend stats (that > could be memory expensive depending on the number of max connections and given > the fact that PgStat_IO is 16KB long). > - The above point means that pg_stat_get_backend_io() behaves as if > stats_fetch_consistency is set to none (each execution re-fetches counters > from shared memory). > - The above 2 points are also the reasons why the pg_my_stat_io view has been > added (as its results takes care of the stats_fetch_consistency setting). I think > that makes sense to rely on it in that case, while I'm not sure that would make > a lot of sense to retrieve other's backend I/O stats and taking care of > stats_fetch_consistency. > > > [1]: https://www.postgresql.org/message-id/20230309003438.rectf7xo7pw5t5cj%40awork3.anarazel.de I'm not sure about the usefulness of having the stats only available from the current session. Since they are stored in shared memory, shouldn't we make them accessible to all backends? However, this would introduce permission considerations and could become complex. When I first looked at this patch, my initial thought was whether we should let these stats stay "fixed." The reason why the current PGSTAT_KIND_IO is fixed is that there is only one global statistics storage for the entire database. If we have stats for a flexible number of backends, it would need to be non-fixed, perhaps with the entry for INVALID_PROC_NUMBER storing the global I/O stats, I suppose. However, one concern with that approach would be the impact on performance due to the frequent creation and deletion of stats entries caused by high turnover of backends. Just to be clear, the above comments are not meant to oppose the current implementation approach. They are purely for the sake of discussing comparisons with other possible approaches. regards. -- Kyotaro Horiguchi NTT Open Source Software Center
-
Re: per backend I/O statistics
Kyotaro Horiguchi <horikyota.ntt@gmail.com> — 2024-09-03T07:07:58Z
At Tue, 03 Sep 2024 15:37:49 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in > When I first looked at this patch, my initial thought was whether we > should let these stats stay "fixed." The reason why the current > PGSTAT_KIND_IO is fixed is that there is only one global statistics > storage for the entire database. If we have stats for a flexible > number of backends, it would need to be non-fixed, perhaps with the > entry for INVALID_PROC_NUMBER storing the global I/O stats, I > suppose. However, one concern with that approach would be the impact > on performance due to the frequent creation and deletion of stats > entries caused by high turnover of backends. As an additional benefit of this approach, the client can set a connection variable, for example, no_backend_iostats to true, or set its inverse variable to false, to restrict memory usage to only the required backends. regards. -- Kyotaro Horiguchi NTT Open Source Software Center
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-03T07:21:23Z
Hi, On Tue, Sep 03, 2024 at 03:37:49PM +0900, Kyotaro Horiguchi wrote: > At Mon, 2 Sep 2024 14:55:52 +0000, Bertrand Drouvot <bertranddrouvot.pg@gmail.com> wrote in > > Hi hackers, > > > > Please find attached a patch to implement $SUBJECT. > > > > While pg_stat_io provides cluster-wide I/O statistics, this patch adds a new > > pg_my_stat_io view to display "my" backend I/O statistics and a new > > pg_stat_get_backend_io() function to retrieve the I/O statistics for a given > > backend pid. > > > > I'm not sure about the usefulness of having the stats only available > from the current session. Since they are stored in shared memory, > shouldn't we make them accessible to all backends? Thanks for the feedback! The stats are accessible to all backends thanks to 0002 and the introduction of the pg_stat_get_backend_io() function. > However, this would > introduce permission considerations and could become complex. Not sure that the data exposed here is sensible enough to consider permission restriction. > When I first looked at this patch, my initial thought was whether we > should let these stats stay "fixed." The reason why the current > PGSTAT_KIND_IO is fixed is that there is only one global statistics > storage for the entire database. If we have stats for a flexible > number of backends, it would need to be non-fixed, perhaps with the > entry for INVALID_PROC_NUMBER storing the global I/O stats, I > suppose. However, one concern with that approach would be the impact > on performance due to the frequent creation and deletion of stats > entries caused by high turnover of backends. > The pros of using the fixed amount are: - less code change (I think as I did not write the non fixed counterpart) - probably better performance and less scalabilty impact (in case of high rate of backends creation/ deletion) Cons is probably allocating shared memory space that might not be used ( sizeof(PgStat_IO) is 16392 so that could be a concern for a high number of unused connection). OTOH, if a high number of connections is not used that might be worth to reduce the max_connections setting. "Conceptually" speaking, we know what the maximum number of backend is, so I think that using the fixed amount approach makes sense (somehow I think it can be compared to PGSTAT_KIND_SLRU which relies on SLRU_NUM_ELEMENTS). > Just to be clear, the above comments are not meant to oppose the > current implementation approach. They are purely for the sake of > discussing comparisons with other possible approaches. No problem at all, thanks for your feedback and sharing your thoughts! Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-04T04:45:24Z
Hi, On Tue, Sep 03, 2024 at 04:07:58PM +0900, Kyotaro Horiguchi wrote: > At Tue, 03 Sep 2024 15:37:49 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in > > When I first looked at this patch, my initial thought was whether we > > should let these stats stay "fixed." The reason why the current > > PGSTAT_KIND_IO is fixed is that there is only one global statistics > > storage for the entire database. If we have stats for a flexible > > number of backends, it would need to be non-fixed, perhaps with the > > entry for INVALID_PROC_NUMBER storing the global I/O stats, I > > suppose. However, one concern with that approach would be the impact > > on performance due to the frequent creation and deletion of stats > > entries caused by high turnover of backends. > > As an additional benefit of this approach, the client can set a > connection variable, for example, no_backend_iostats to true, or set > its inverse variable to false, to restrict memory usage to only the > required backends. Thanks for the feedback! If we were to add an on/off switch button, I think I'd vote for a global one instead. Indeed, I see this feature more like an "Administrator" one, where the administrator wants to be able to find out which session is reponsible of what (from an I/O point of view): like being able to anwser "which session is generating this massive amount of reads"? If we allow each session to disable the feature then the administrator would lost this ability. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Alvaro Herrera <alvherre@alvh.no-ip.org> — 2024-09-05T13:03:32Z
On 2024-Sep-03, Bertrand Drouvot wrote: > Cons is probably allocating shared memory space that might not be used ( > sizeof(PgStat_IO) is 16392 so that could be a concern for a high number of > unused connection). OTOH, if a high number of connections is not used that might > be worth to reduce the max_connections setting. I was surprised by the size you mention so I went to look for the definition of that struct: typedef struct PgStat_IO { TimestampTz stat_reset_timestamp; PgStat_BktypeIO stats[BACKEND_NUM_TYPES]; } PgStat_IO; (It would be good to have more than zero comments here BTW) So what's happening is that struct PgStat_IO stores the data for every single process type, be it regular backends, backend-like auxiliary processes, and all other potential postmaster children. So it seems to me that storing one of these struct for "my backend stats" is wrong: I think you should be using PgStat_BktypeIO instead (or maybe another struct which has a reset timestamp plus BktypeIO, if you care about the reset time). That struct is only 1024 bytes long, so it seems much more reasonable to have one of those per backend. Another way to think about this might be to say that the B_BACKEND element of the PgStat_Snapshot.io array should really be spread out to MaxBackends separate elements. This would make it more difficult to obtain a total value accumulating ops done by all backends (since it's require to sum the values of each backend), but it allows you to obtain backend-specific values, including those of remote backends rather than only your own, as Kyotaro suggests. -- Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/ -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-05T14:14:47Z
Hi, On Thu, Sep 05, 2024 at 03:03:32PM +0200, Alvaro Herrera wrote: > On 2024-Sep-03, Bertrand Drouvot wrote: > > > Cons is probably allocating shared memory space that might not be used ( > > sizeof(PgStat_IO) is 16392 so that could be a concern for a high number of > > unused connection). OTOH, if a high number of connections is not used that might > > be worth to reduce the max_connections setting. > > I was surprised by the size you mention so I went to look for the > definition of that struct: > Thanks for looking at it! > typedef struct PgStat_IO > { > TimestampTz stat_reset_timestamp; > PgStat_BktypeIO stats[BACKEND_NUM_TYPES]; > } PgStat_IO; > > (It would be good to have more than zero comments here BTW) > > So what's happening is that struct PgStat_IO stores the data for every > single process type, be it regular backends, backend-like auxiliary > processes, and all other potential postmaster children. Yeap. > So it seems to > me that storing one of these struct for "my backend stats" is wrong: I > think you should be using PgStat_BktypeIO instead (or maybe another > struct which has a reset timestamp plus BktypeIO, if you care about the > reset time). That struct is only 1024 bytes long, so it seems much more > reasonable to have one of those per backend. Yeah, that could be an area of improvement. Thanks, I'll look at it. Currently the filtering is done when retrieving the per backend stats but better to do it when storing the stats. > Another way to think about this might be to say that the B_BACKEND > element of the PgStat_Snapshot.io array should really be spread out to > MaxBackends separate elements. This would make it more difficult to > obtain a total value accumulating ops done by all backends (since it's > require to sum the values of each backend), but it allows you to obtain > backend-specific values, including those of remote backends rather than > only your own, as Kyotaro suggests. > One backend can already see the stats of the other backends thanks to the pg_stat_get_backend_io() function (that takes a backend pid as parameter) that is introduced in the 0002 sub-patch. I'll ensure that's still the case with the next version of the patch. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-06T15:03:17Z
Hi, On Thu, Sep 05, 2024 at 02:14:47PM +0000, Bertrand Drouvot wrote: > Hi, > > On Thu, Sep 05, 2024 at 03:03:32PM +0200, Alvaro Herrera wrote: > > So it seems to > > me that storing one of these struct for "my backend stats" is wrong: I > > think you should be using PgStat_BktypeIO instead (or maybe another > > struct which has a reset timestamp plus BktypeIO, if you care about the > > reset time). That struct is only 1024 bytes long, so it seems much more > > reasonable to have one of those per backend. > > Yeah, that could be an area of improvement. Thanks, I'll look at it. > Currently the filtering is done when retrieving the per backend stats but better > to do it when storing the stats. I ended up creating (in v2 attached): " typedef struct PgStat_Backend_IO { TimestampTz stat_reset_timestamp; BackendType bktype; PgStat_BktypeIO stats; } PgStat_Backend_IO; " The stat_reset_timestamp is there so that one knows when a particular backend had its I/O stats reset. Also the backend type is part of the struct to be able to filter the stats correctly when we display them. The struct size is 1040 Bytes and that's much more reasonable than the size needed for per backend I/O stats in v1 (about 16KB). > One backend can already see the stats of the other backends thanks to the > pg_stat_get_backend_io() function (that takes a backend pid as parameter) > that is introduced in the 0002 sub-patch. 0002 still provides the pg_stat_get_backend_io() function so that one could get the stats of other backends. Example: postgres=# select backend_type,object,context,reads,extends,hits from pg_stat_get_backend_io(3779502); backend_type | object | context | reads | extends | hits ----------------+---------------+-----------+-------+---------+-------- client backend | relation | bulkread | 0 | | 0 client backend | relation | bulkwrite | 0 | 0 | 0 client backend | relation | normal | 73 | 2216 | 504674 client backend | relation | vacuum | 0 | 0 | 0 client backend | temp relation | normal | 0 | 0 | 0 (5 rows) could be an individual walsender: postgres=# select pid, backend_type from pg_stat_activity where backend_type = 'walsender'; pid | backend_type ---------+-------------- 3779565 | walsender (1 row) postgres=# select backend_type,object,context,reads,hits from pg_stat_get_backend_io(3779565); backend_type | object | context | reads | hits --------------+---------------+-----------+-------+------ walsender | relation | bulkread | 0 | 0 walsender | relation | bulkwrite | 0 | 0 walsender | relation | normal | 6 | 48 walsender | relation | vacuum | 0 | 0 walsender | temp relation | normal | 0 | 0 (5 rows) and so on... Remarks: - As stated up-thread, the pg_stat_get_backend_io() behaves as if stats_fetch_consistency is set to none (each execution re-fetches counters from shared memory). Indeed, the snapshot is not build in each backend to copy all the others backends stats, as 1/ there is no use case (there is no need to get others backends I/O statistics while taking care of the stats_fetch_consistency) and 2/ that could be memory expensive depending of the number of max connections. - If we agree on the current proposal then I'll do some refactoring in pg_stat_get_backend_io(), pg_stat_get_my_io() and pg_stat_get_io() to avoid duplicated code (it's not done yet to ease the review). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-09T06:29:18Z
Hi, On Fri, Sep 06, 2024 at 03:03:17PM +0000, Bertrand Drouvot wrote: > - If we agree on the current proposal then I'll do some refactoring in > pg_stat_get_backend_io(), pg_stat_get_my_io() and pg_stat_get_io() to avoid > duplicated code (it's not done yet to ease the review). Please find attached v3, mandatory rebase due to fc415edf8c. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-13T04:25:46Z
Hi, On Fri, Sep 06, 2024 at 03:03:17PM +0000, Bertrand Drouvot wrote: > The struct size is 1040 Bytes and that's much more reasonable than the size > needed for per backend I/O stats in v1 (about 16KB). One could think that's a high increase of shared memory usage with a high number of connections (due to the fact that it's implemented as "fixed amount" stats based on the max number of backends). So out of curiosity, I did some measurements with: dynamic_shared_memory_type=sysv shared_memory_type=sysv max_connections=20000 On my lab, ipcs -m gives me: - on master key shmid owner perms bytes nattch status 0x00113a04 51347487 postgres 600 1149394944 6 0x4bc9f2fa 51347488 postgres 600 4006976 6 0x46790800 51347489 postgres 600 1048576 2 - with v3 applied key shmid owner perms bytes nattch status 0x00113a04 51347477 postgres 600 1170227200 6 0x08e04b0a 51347478 postgres 600 4006976 6 0x74688c9c 51347479 postgres 600 1048576 2 So, with 20000 max_connections (not advocating that's a reasonable number in all the cases), that's a 1170227200 - 1149394944 = 20 MB increase of shared memory (expected with 20K max_connections and the new struct size of 1040 Bytes) as compare to master which is 1096 MB. It means that v3 produces about 2% shared memory increase with 20000 max_connections. Out of curiosity with max_connections=100000, then: - on master: ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00113a04 52953134 postgres 600 5053915136 6 0x37abf5ce 52953135 postgres 600 20006976 6 0x71c07d5c 52953136 postgres 600 1048576 2 - with v3: ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00113a04 52953144 postgres 600 5157945344 6 0x7afb24de 52953145 postgres 600 20006976 6 0x2695af58 52953146 postgres 600 1048576 2 So, with 100000 max_connections (not advocating that's a reasonable number in all the cases), that's a 5157945344 - 5053915136 = 100 MB increase of shared memory (expected with 100K max_connections and the new struct size of 1040 Bytes) as compare to master which is about 4800 MB. It means that v3 produces about 2% shared memory increase with 100000 max_connections. Then, based on those numbers, I think that the "fixed amount" approach is a good one as 1/ the amount of shared memory increase is "relatively" small and 2/ most probably provides performance benefits as compare to the "non fixed" approach. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Nazir Bilal Yavuz <byavuz81@gmail.com> — 2024-09-13T13:45:08Z
Hi, Thanks for working on this! Your patch applies and builds cleanly. On Fri, 6 Sept 2024 at 18:03, Bertrand Drouvot <bertranddrouvot.pg@gmail.com> wrote: > > - As stated up-thread, the pg_stat_get_backend_io() behaves as if > stats_fetch_consistency is set to none (each execution re-fetches counters > from shared memory). Indeed, the snapshot is not build in each backend to copy > all the others backends stats, as 1/ there is no use case (there is no need to > get others backends I/O statistics while taking care of the stats_fetch_consistency) > and 2/ that could be memory expensive depending of the number of max connections. I believe this is the correct approach. I manually tested your patches, and they work as expected. Here is some feedback: - The stats_reset column is NULL in both pg_my_stat_io and pg_stat_get_backend_io() until the first call to reset io statistics. While I'm not sure if it's necessary, it might be useful to display the more recent of the two times in the stats_reset column: the statistics reset time or the backend creation time. - The pgstat_reset_io_counter_internal() is called in the pgstat_shutdown_hook(). This causes the stats_reset column showing the termination time of the old backend when its proc num is reassigned to a new backend. -- Regards, Nazir Bilal Yavuz Microsoft
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-13T16:09:40Z
Hi, On Fri, Sep 13, 2024 at 04:45:08PM +0300, Nazir Bilal Yavuz wrote: > Hi, > > Thanks for working on this! > > Your patch applies and builds cleanly. Thanks for looking at it! > On Fri, 6 Sept 2024 at 18:03, Bertrand Drouvot > <bertranddrouvot.pg@gmail.com> wrote: > > > > - As stated up-thread, the pg_stat_get_backend_io() behaves as if > > stats_fetch_consistency is set to none (each execution re-fetches counters > > from shared memory). Indeed, the snapshot is not build in each backend to copy > > all the others backends stats, as 1/ there is no use case (there is no need to > > get others backends I/O statistics while taking care of the stats_fetch_consistency) > > and 2/ that could be memory expensive depending of the number of max connections. > > I believe this is the correct approach. Thanks for sharing your thoughts. > I manually tested your patches, and they work as expected. Here is > some feedback: > > - The stats_reset column is NULL in both pg_my_stat_io and > pg_stat_get_backend_io() until the first call to reset io statistics. > While I'm not sure if it's necessary, it might be useful to display > the more recent of the two times in the stats_reset column: the > statistics reset time or the backend creation time. I'm not sure about that as one can already get the backend "creation time" through pg_stat_activity.backend_start. > - The pgstat_reset_io_counter_internal() is called in the > pgstat_shutdown_hook(). This causes the stats_reset column showing the > termination time of the old backend when its proc num is reassigned to > a new backend. doh! Nice catch, thanks! And also new backends that are not re-using a previous "existing" process slot are getting the last reset time (if any). So the right place to fix this is in pgstat_io_init_backend_cb(): done in v4 attached. v4 also sets the reset time to 0 in pgstat_shutdown_hook() (but that's not necessary though, that's just to be right "conceptually" speaking). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Nazir Bilal Yavuz <byavuz81@gmail.com> — 2024-09-17T11:52:01Z
Hi, On Fri, 13 Sept 2024 at 19:09, Bertrand Drouvot <bertranddrouvot.pg@gmail.com> wrote: > On Fri, Sep 13, 2024 at 04:45:08PM +0300, Nazir Bilal Yavuz wrote: > > - The pgstat_reset_io_counter_internal() is called in the > > pgstat_shutdown_hook(). This causes the stats_reset column showing the > > termination time of the old backend when its proc num is reassigned to > > a new backend. > > doh! Nice catch, thanks! > > And also new backends that are not re-using a previous "existing" process slot > are getting the last reset time (if any). So the right place to fix this is in > pgstat_io_init_backend_cb(): done in v4 attached. v4 also sets the reset time to > 0 in pgstat_shutdown_hook() (but that's not necessary though, that's just to be > right "conceptually" speaking). Thanks, I confirm that it is fixed. You mentioned some refactoring upthread: On Fri, 6 Sept 2024 at 18:03, Bertrand Drouvot <bertranddrouvot.pg@gmail.com> wrote: > > - If we agree on the current proposal then I'll do some refactoring in > pg_stat_get_backend_io(), pg_stat_get_my_io() and pg_stat_get_io() to avoid > duplicated code (it's not done yet to ease the review). Could we remove pg_stat_get_my_io() completely and use pg_stat_get_backend_io() with the current backend's pid to get the current backend's stats? If you meant the same thing, please don't mind it. -- Regards, Nazir Bilal Yavuz Microsoft
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-17T13:07:07Z
Hi, On Tue, Sep 17, 2024 at 02:52:01PM +0300, Nazir Bilal Yavuz wrote: > Hi, > > On Fri, 13 Sept 2024 at 19:09, Bertrand Drouvot > <bertranddrouvot.pg@gmail.com> wrote: > > On Fri, Sep 13, 2024 at 04:45:08PM +0300, Nazir Bilal Yavuz wrote: > > > - The pgstat_reset_io_counter_internal() is called in the > > > pgstat_shutdown_hook(). This causes the stats_reset column showing the > > > termination time of the old backend when its proc num is reassigned to > > > a new backend. > > > > doh! Nice catch, thanks! > > > > And also new backends that are not re-using a previous "existing" process slot > > are getting the last reset time (if any). So the right place to fix this is in > > pgstat_io_init_backend_cb(): done in v4 attached. v4 also sets the reset time to > > 0 in pgstat_shutdown_hook() (but that's not necessary though, that's just to be > > right "conceptually" speaking). > > Thanks, I confirm that it is fixed. Thanks! > You mentioned some refactoring upthread: > > On Fri, 6 Sept 2024 at 18:03, Bertrand Drouvot > <bertranddrouvot.pg@gmail.com> wrote: > > > > - If we agree on the current proposal then I'll do some refactoring in > > pg_stat_get_backend_io(), pg_stat_get_my_io() and pg_stat_get_io() to avoid > > duplicated code (it's not done yet to ease the review). > > Could we remove pg_stat_get_my_io() completely and use > pg_stat_get_backend_io() with the current backend's pid to get the > current backend's stats? The reason why I keep pg_stat_get_my_io() is because (as mentioned in [1]), the statistics snapshot is build for "my backend stats" (means it depends of the stats_fetch_consistency value). I can see use cases for that. OTOH, pg_stat_get_backend_io() behaves as if stats_fetch_consistency is set to none (each execution re-fetches counters from shared memory) (see [2]). Indeed, the snapshot is not build in each backend to copy all the others backends stats, as 1/ I think that there is no use case (there is no need to get others backends I/O statistics while taking care of the stats_fetch_consistency) and 2/ that could be memory expensive depending of the number of max connections. So I think it's better to keep both functions as they behave differently. Thoughts? > If you meant the same thing, please don't > mind it. What I meant to say is to try to remove the duplicate code that we can find in those 3 functions (say creating a new function that would contain the duplicate code and make use of this new function in the 3 others). Did not look at it in details yet. [1]: https://www.postgresql.org/message-id/ZtXR%2BCtkEVVE/LHF%40ip-10-97-1-34.eu-west-3.compute.internal [2]: https://www.postgresql.org/message-id/ZtsZtaRza9bFFeF8%40ip-10-97-1-34.eu-west-3.compute.internal Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Nazir Bilal Yavuz <byavuz81@gmail.com> — 2024-09-17T13:47:51Z
Hi, On Tue, 17 Sept 2024 at 16:07, Bertrand Drouvot <bertranddrouvot.pg@gmail.com> wrote: > On Tue, Sep 17, 2024 at 02:52:01PM +0300, Nazir Bilal Yavuz wrote: > > Could we remove pg_stat_get_my_io() completely and use > > pg_stat_get_backend_io() with the current backend's pid to get the > > current backend's stats? > > The reason why I keep pg_stat_get_my_io() is because (as mentioned in [1]), the > statistics snapshot is build for "my backend stats" (means it depends of the > stats_fetch_consistency value). I can see use cases for that. > > OTOH, pg_stat_get_backend_io() behaves as if stats_fetch_consistency is set to > none (each execution re-fetches counters from shared memory) (see [2]). Indeed, > the snapshot is not build in each backend to copy all the others backends stats, > as 1/ I think that there is no use case (there is no need to get others backends > I/O statistics while taking care of the stats_fetch_consistency) and 2/ that > could be memory expensive depending of the number of max connections. > > So I think it's better to keep both functions as they behave differently. > > Thoughts? Yes, that is correct. Sorry, you already had explained it and I had agreed with it but I forgot. > > If you meant the same thing, please don't > > mind it. > > What I meant to say is to try to remove the duplicate code that we can find in > those 3 functions (say creating a new function that would contain the duplicate > code and make use of this new function in the 3 others). Did not look at it in > details yet. I got it, thanks for the explanation. -- Regards, Nazir Bilal Yavuz Microsoft
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-09-17T13:56:34Z
Hi, On Tue, Sep 17, 2024 at 04:47:51PM +0300, Nazir Bilal Yavuz wrote: > Hi, > > On Tue, 17 Sept 2024 at 16:07, Bertrand Drouvot > <bertranddrouvot.pg@gmail.com> wrote: > > So I think it's better to keep both functions as they behave differently. > > > > Thoughts? > > Yes, that is correct. Sorry, you already had explained it and I had > agreed with it but I forgot. No problem at all! (I re-explained because I'm not always 100% sure that my explanations are crystal clear ;-) ) Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-09-20T03:53:43Z
On Wed, Sep 04, 2024 at 04:45:24AM +0000, Bertrand Drouvot wrote: > On Tue, Sep 03, 2024 at 04:07:58PM +0900, Kyotaro Horiguchi wrote: >> As an additional benefit of this approach, the client can set a >> connection variable, for example, no_backend_iostats to true, or set >> its inverse variable to false, to restrict memory usage to only the >> required backends. > > Thanks for the feedback! > > If we were to add an on/off switch button, I think I'd vote for a global one > instead. Indeed, I see this feature more like an "Administrator" one, where > the administrator wants to be able to find out which session is reponsible of > what (from an I/O point of view): like being able to anwser "which session is > generating this massive amount of reads"? > > If we allow each session to disable the feature then the administrator > would lost this ability. Hmm, I've been studying this patch, and I am not completely sure to agree with this feeling of using fixed-numbered stats, actually, after reading the whole and seeing the structure of the patch (FLEXIBLE_ARRAY_MEMBER is a new way to handle the fact that we don't know exactly the number of slots we need to know for the fixed-numbered stats as MaxBackends may change). If we make these kind of stats variable-numbered, does it have to actually involve many creations or removals of the stats entries, though? One point is that the number of entries to know about is capped by max_connections, which is a PGC_POSTMASTER. That's the same kind of control as replication slots. So one approach would be to reuse entries in the dshash and use in the hashing key the number in the procarrays. If a new connection spawns and reuses a slot that was used in the past, then reset all the existing fields and assign its PID. Another thing is the consistency of the data that we'd like to keep at shutdown. If the connections have a balanced amount of stats shared among them, doing decision-making based on them is kind of easy. But that may cause confusion if the activity is unbalanced across the sessions. We could also not flush them to disk as an option, but it still seems more useful to me to save this data across restarts if one takes frequent snapshots of the new system view reporting everything, so as it is possible to get an idea of the deltas across the snapshots for each connection slot. -- Michael
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-09-20T04:26:49Z
On Tue, Sep 17, 2024 at 01:56:34PM +0000, Bertrand Drouvot wrote: > No problem at all! (I re-explained because I'm not always 100% sure that my > explanations are crystal clear ;-) ) We've discussed a bit this patch offline, but after studying the patch I doubt that this part is a good idea: + /* has to be at the end due to FLEXIBLE_ARRAY_MEMBER */ + PgStatShared_IO io; } PgStat_ShmemControl; We are going to be in trouble if we introduce a second member in this routine that has a FLEXIBLE_ARRAY_MEMBER, because PgStat_ShmemControl relies on the fact that all its members after deterministic offset positions in this structure. So this lacks flexibility. This choice is caused by the fact that we don't exactly know the number of backends because that's controlled by the PGC_POSTMASTER GUC max_connections so the size of the structure would be undefined. There is a parallel with replication slot statistics here, where we save the replication slot data in the dshash based on their index number in shmem. Hence, wouldn't it be better to do like replication slot stats, where we use the dshash and a key based on the procnum of each backend or auxiliary process (ProcNumber in procnumber.h)? If at restart max_connections is lower than what was previously used, we could discard entries that would not fit anymore into the charts. This is probably not something that happens often, so I'm not really worried about forcing the removal of these stats depending on how the upper-bound of ProcNumber evolves. So, using a new kind of ID and making this kind variable-numbered may ease the implementation quite a bit, while avoiding any extensibility issues with the shmem portion of the patch if these are fixed-numbered. The reporting of these stats comes down to having a parallel with pgstat_count_io_op_time(), but to make sure that the stats are split by connection slot number rather than the current split of pg_stat_io. All its callers are in localbuf.c, bufmgr.c and md.c, living with some duplication in the code paths to gather the stats may be OK. pg_stat_get_my_io() is based on a O(n^3). IOOBJECT_NUM_TYPES is fortunately low, still that's annoying. This would rely on the fact that we would use the ProcNumber for the dshash key, and this information is not provided in pg_stat_activity. Perhaps we should add this information in pg_stat_activity so as it would be easily possible to do joins with a SQL function that returns a SRF with all the stats associated with a given connection slot (auxiliary or backend process)? That would be a separate patch. Perhaps that's even something that has popped up for the work with threading (did not follow this part closely, TBH)? The active PIDs of the live sessions are not stored in the active stats, why not? Perhaps that's useless anyway if we expose the ProcNumbers in pg_stat_activity and make the stats available with a single function taking in input a ProcNumber. Just mentioning an option to consider. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-10-07T09:52:22Z
Hi, On Fri, Sep 20, 2024 at 12:53:43PM +0900, Michael Paquier wrote: > On Wed, Sep 04, 2024 at 04:45:24AM +0000, Bertrand Drouvot wrote: > > On Tue, Sep 03, 2024 at 04:07:58PM +0900, Kyotaro Horiguchi wrote: > >> As an additional benefit of this approach, the client can set a > >> connection variable, for example, no_backend_iostats to true, or set > >> its inverse variable to false, to restrict memory usage to only the > >> required backends. > > > > Thanks for the feedback! > > > > If we were to add an on/off switch button, I think I'd vote for a global one > > instead. Indeed, I see this feature more like an "Administrator" one, where > > the administrator wants to be able to find out which session is reponsible of > > what (from an I/O point of view): like being able to anwser "which session is > > generating this massive amount of reads"? > > > > If we allow each session to disable the feature then the administrator > > would lost this ability. > > Hmm, I've been studying this patch, Thanks for looking at it! > and I am not completely sure to > agree with this feeling of using fixed-numbered stats, actually, after > reading the whole and seeing the structure of the patch > (FLEXIBLE_ARRAY_MEMBER is a new way to handle the fact that we don't > know exactly the number of slots we need to know for the > fixed-numbered stats as MaxBackends may change). Right, that's a new way of dealing with "unknown" number of slots (and it has cons as you mentioned in [1]). > If we make these > kind of stats variable-numbered, does it have to actually involve many > creations or removals of the stats entries, though? One point is that > the number of entries to know about is capped by max_connections, > which is a PGC_POSTMASTER. That's the same kind of control as > replication slots. So one approach would be to reuse entries in the > dshash and use in the hashing key the number in the procarrays. If a > new connection spawns and reuses a slot that was used in the past, > then reset all the existing fields and assign its PID. Yeah, like it's done currently with the "fixed-numbered" stats proposal. That sounds reasonable to me, I'll look at this proposed approach and come back with a new patch version, thanks! > Another thing is the consistency of the data that we'd like to keep at > shutdown. If the connections have a balanced amount of stats shared > among them, doing decision-making based on them is kind of easy. But > that may cause confusion if the activity is unbalanced across the > sessions. We could also not flush them to disk as an option, but it > still seems more useful to me to save this data across restarts if one > takes frequent snapshots of the new system view reporting everything, > so as it is possible to get an idea of the deltas across the snapshots > for each connection slot. The idea that has been implemented so far in this patch is that we still maintain an aggregated version of the stats (visible through pg_stat_io) and that only the aggregated stats are flushed/read to/from disk (means we don't flush the per-backend stats). I think that it makes sense that way. The way I see it is that the per-backend I/O stats is more for current activity instrumentation. So it's not clear to me what would be the benefits of restoring the per-backend stats at startup knowing that: 1) we restored the aggregated stats and 2) the sessions that were responsible for the the restored stats are gone. [1]: https://www.postgresql.org/message-id/Zuz5iQ4AjcuOMx_w%40paquier.xyz Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-10-07T09:54:21Z
Hi, On Fri, Sep 20, 2024 at 01:26:49PM +0900, Michael Paquier wrote: > On Tue, Sep 17, 2024 at 01:56:34PM +0000, Bertrand Drouvot wrote: > > No problem at all! (I re-explained because I'm not always 100% sure that my > > explanations are crystal clear ;-) ) > > We've discussed a bit this patch offline, but after studying the patch > I doubt that this part is a good idea: > > + /* has to be at the end due to FLEXIBLE_ARRAY_MEMBER */ > + PgStatShared_IO io; > } PgStat_ShmemControl; > > We are going to be in trouble if we introduce a second member in this > routine that has a FLEXIBLE_ARRAY_MEMBER, because PgStat_ShmemControl > relies on the fact that all its members after deterministic offset > positions in this structure. Agree that it would be an issue should we have to add a new FLEXIBLE_ARRAY_MEMBER. > So this lacks flexibility. This choice > is caused by the fact that we don't exactly know the number of > backends because that's controlled by the PGC_POSTMASTER GUC > max_connections so the size of the structure would be undefined. Right. > There is a parallel with replication slot statistics here, where we > save the replication slot data in the dshash based on their index > number in shmem. Hence, wouldn't it be better to do like replication > slot stats, where we use the dshash and a key based on the procnum of > each backend or auxiliary process (ProcNumber in procnumber.h)? If at > restart max_connections is lower than what was previously used, we > could discard entries that would not fit anymore into the charts. > This is probably not something that happens often, so I'm not really > worried about forcing the removal of these stats depending on how the > upper-bound of ProcNumber evolves. Yeah, I'll look at implementing the dshash based on their procnum and see where it goes. > So, using a new kind of ID and making this kind variable-numbered may > ease the implementation quite a bit, while avoiding any extensibility > issues with the shmem portion of the patch if these are > fixed-numbered. Agree. > This would rely on the fact that we would use the ProcNumber for the > dshash key, and this information is not provided in pg_stat_activity. > Perhaps we should add this information in pg_stat_activity so as it > would be easily possible to do joins with a SQL function that returns > a SRF with all the stats associated with a given connection slot > (auxiliary or backend process)? I'm not sure that's needed. What has been done in the previous versions is to get the stats based on the pid (see pg_stat_get_backend_io()) where the procnumber is retrieved with something like GetNumberFromPGProc(BackendPidGetProc(pid)). Do you see an issue with that approach? > The active PIDs of the live sessions are not stored in the active > stats, why not? That was not needed. We can still retrieve the stats based on the pid thanks to something like GetNumberFromPGProc(BackendPidGetProc(pid)) without having to actually store the pid in the stats. I think that's fine because the pid only matters at "display" time (pg_stat_get_backend_io()). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-10-08T04:46:23Z
On Mon, Oct 07, 2024 at 09:54:21AM +0000, Bertrand Drouvot wrote: > On Fri, Sep 20, 2024 at 01:26:49PM +0900, Michael Paquier wrote: >> This would rely on the fact that we would use the ProcNumber for the >> dshash key, and this information is not provided in pg_stat_activity. >> Perhaps we should add this information in pg_stat_activity so as it >> would be easily possible to do joins with a SQL function that returns >> a SRF with all the stats associated with a given connection slot >> (auxiliary or backend process)? > > I'm not sure that's needed. What has been done in the previous versions is > to get the stats based on the pid (see pg_stat_get_backend_io()) where the > procnumber is retrieved with something like GetNumberFromPGProc(BackendPidGetProc(pid)). Ah, I see. So you could just have the proc number in the key to control the upper-bound on the number of possible stats entries in the dshash. Assuming that none of this data is persisted to the stats file at shutdown and that the stats of a single entry are reset each time a new backend reuses a previous proc slot, that would be OK by me, I guess. >> The active PIDs of the live sessions are not stored in the active >> stats, why not? > > That was not needed. We can still retrieve the stats based on the pid thanks > to something like GetNumberFromPGProc(BackendPidGetProc(pid)) without having > to actually store the pid in the stats. I think that's fine because the pid > only matters at "display" time (pg_stat_get_backend_io()). Okay, per the above and the persistency of the stats. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-10-08T16:28:39Z
Hi, On Tue, Oct 08, 2024 at 01:46:23PM +0900, Michael Paquier wrote: > On Mon, Oct 07, 2024 at 09:54:21AM +0000, Bertrand Drouvot wrote: > > On Fri, Sep 20, 2024 at 01:26:49PM +0900, Michael Paquier wrote: > >> This would rely on the fact that we would use the ProcNumber for the > >> dshash key, and this information is not provided in pg_stat_activity. > >> Perhaps we should add this information in pg_stat_activity so as it > >> would be easily possible to do joins with a SQL function that returns > >> a SRF with all the stats associated with a given connection slot > >> (auxiliary or backend process)? > > > > I'm not sure that's needed. What has been done in the previous versions is > > to get the stats based on the pid (see pg_stat_get_backend_io()) where the > > procnumber is retrieved with something like GetNumberFromPGProc(BackendPidGetProc(pid)). > > Ah, I see. So you could just have the proc number in the key to > control the upper-bound on the number of possible stats entries in the > dshash. Yes. > Assuming that none of this data is persisted to the stats file at > shutdown and that the stats of a single entry are reset each time a > new backend reuses a previous proc slot, that would be OK by me, I > guess. > > >> The active PIDs of the live sessions are not stored in the active > >> stats, why not? > > > > That was not needed. We can still retrieve the stats based on the pid thanks > > to something like GetNumberFromPGProc(BackendPidGetProc(pid)) without having > > to actually store the pid in the stats. I think that's fine because the pid > > only matters at "display" time (pg_stat_get_backend_io()). > > Okay, per the above and the persistency of the stats. Great, I'll work on an updated patch version then. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-10-31T05:09:56Z
Hi, On Tue, Oct 08, 2024 at 04:28:39PM +0000, Bertrand Drouvot wrote: > > > On Fri, Sep 20, 2024 at 01:26:49PM +0900, Michael Paquier wrote: > > > > Okay, per the above and the persistency of the stats. > > Great, I'll work on an updated patch version then. > I spend some time on this during the last 2 days and I think we have 3 design options. === GOALS === But first let's sump up the goals that I think we agreed on: - Keep pg_stat_io as it is today: give the whole server picture and serialize the stats to disk. - Introduce per-backend IO stats and 2 new APIs to: 1. Provide the IO stats for "my backend" (through say pg_my_stat_io), this would take care of the stats_fetch_consistency. 2. Retrieve the IO stats for another backend (through say pg_stat_get_backend_io(pid)) that would _not_ take care of stats_fetch_consistency, as: 2.1/ I think that there is no use case (there is no need to get others backends I/O statistics while taking care of the stats_fetch_consistency) 2.2/ That could be memory expensive to store a snapshot for all the backends (depending of the number of backend created) - There is no need to serialize the per-backend IO stats to disk (no point to see stats for backends that do not exist anymore after a re-start). - The per-backend IO stats should be variable-numbered (not fixed), as per up-thread discussion. === OPTIONS === So, based on this, I think that we could: Option 1: "move" the existing PGSTAT_KIND_IO to variable-numbered and let this KIND take care of the aggregated view (pg_stat_io) and the per-backend stats. Option 2: let PGSTAT_KIND_IO as it is and introduce a new PGSTAT_KIND_BACKEND_IO that would be variable-numbered. Option 3: Remove PGSTAT_KIND_IO, introduce a new PGSTAT_KIND_BACKEND_IO that would be variable-numbered and store the "aggregated stats aka pg_stat_io" in shared memory (not part of the variable-numbered hash). Per-backend stats could be aggregated into "pg_stat_io" during the flush_pending_cb call for example. === BEST OPTION? === I would opt for Option 2 as: - The stats system is currently not designed for Option 1 and our goals (for example the shared_data_len is used to serialize but also to fetch the entries, see pgstat_fetch_entry()) so that would need some hack to serialize only a part of them and still be able to fetch them all). - Mixing "fixed" and "variable" in the same KIND does not sound like a good idea (though that might be possible with some hacks, I don't think that would be easy to maintain). - Having the per-backend as "variable" in its dedicated kind looks more reasonable and less error-prone. - I don't think there is a stats design similar to option 3 currently, so I'm not sure there is a need to develop something new while Option 2 could be done. - Option 3 would need some hack for (at least) the "pg_stat_io" [de]serialization part. - Option 2 seems to offer more flexibility (as compare to Option 1 and 3). Thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-04T10:01:50Z
Hi, On Thu, Oct 31, 2024 at 05:09:56AM +0000, Bertrand Drouvot wrote: > === OPTIONS === > > So, based on this, I think that we could: > > Option 1: "move" the existing PGSTAT_KIND_IO to variable-numbered and let this > KIND take care of the aggregated view (pg_stat_io) and the per-backend stats. > > Option 2: let PGSTAT_KIND_IO as it is and introduce a new PGSTAT_KIND_BACKEND_IO > that would be variable-numbered. > > Option 3: Remove PGSTAT_KIND_IO, introduce a new PGSTAT_KIND_BACKEND_IO that > would be variable-numbered and store the "aggregated stats aka pg_stat_io" in > shared memory (not part of the variable-numbered hash). Per-backend stats > could be aggregated into "pg_stat_io" during the flush_pending_cb call for example. > > === BEST OPTION? === > > I would opt for Option 2 as: > > - The stats system is currently not designed for Option 1 and our goals (for > example the shared_data_len is used to serialize but also to fetch the entries, > see pgstat_fetch_entry()) so that would need some hack to serialize only a part > of them and still be able to fetch them all). > > - Mixing "fixed" and "variable" in the same KIND does not sound like a good idea > (though that might be possible with some hacks, I don't think that would be > easy to maintain). > > - Having the per-backend as "variable" in its dedicated kind looks more reasonable > and less error-prone. > > - I don't think there is a stats design similar to option 3 currently, so I'm > not sure there is a need to develop something new while Option 2 could be done. > > - Option 3 would need some hack for (at least) the "pg_stat_io" [de]serialization > part. > > - Option 2 seems to offer more flexibility (as compare to Option 1 and 3). > > Thoughts? And why not add more per-backend stats in the future? (once the I/O part is done). I think that's one more reason to go with option 2 (and implementing a brand new PGSTAT_KIND_BACKEND kind). Thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-05T17:37:15Z
Hi, On Mon, Nov 04, 2024 at 10:01:50AM +0000, Bertrand Drouvot wrote: > And why not add more per-backend stats in the future? (once the I/O part is done). > > I think that's one more reason to go with option 2 (and implementing a brand new > PGSTAT_KIND_BACKEND kind). I'm starting working on option 2, I think it will be easier to discuss with a patch proposal to look at. If in the meantime, one strongly disagree with option 2 (means implement a brand new PGSTAT_KIND_BACKEND and keep PGSTAT_KIND_IO), please let me know. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-05T23:39:07Z
On Tue, Nov 05, 2024 at 05:37:15PM +0000, Bertrand Drouvot wrote: > I'm starting working on option 2, I think it will be easier to discuss with > a patch proposal to look at. > > If in the meantime, one strongly disagree with option 2 (means implement a brand > new PGSTAT_KIND_BACKEND and keep PGSTAT_KIND_IO), please let me know. Sorry for the late reply, catching up a bit. As you are quoting in [1], you do not expect the backend-io stats and the more global pg_stat_io to achieve the same level of consistency as the backend stats would be gone at restart, and wiped out when a backend shuts down. So, splitting them with a different stats kind feels more natural because it would be possible to control how each stat kind behaves depending on the code shutdown and reset paths within their own callbacks rather than making the callbacks of PGSTAT_KIND_IO more complex than they already are. And pg_stat_io is a fixed-numbered stats kind because of the way it aggregates its stats with a number states defined at compile-time. Is the structure you have in mind different than PgStat_BktypeIO? Perhaps a split is better anyway with that in mind. The amount of memory required to store the snapshots of backend-IO does not worry me much, TBH, but you are worried about a high turnover of connections that could cause a lot of bloat in the backend-IO snapshots because of the persistency that these stats would have, right? Actually, we already have cases with other stats kinds where it is possible for a backend to hold references to some stats on an object that has been dropped concurrently. At least, that's possible when a backend shuts down. If possible, supporting snapshots would be more consistent with the other stats. Just to be clear, I am not in favor of making PgStat_HashKey larger than it already is. With 8 bytes allocated for the object ID, the chances of conflicts in the dshash for a single variable-numbered stats kind play in our favor already even with a couple of million entries. [1]: https://www.postgresql.org/message-id/ZyMRJIbUpNPoCXUe@ip-10-97-1-34.eu-west-3.compute.internal -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-06T13:51:02Z
Hi, On Wed, Nov 06, 2024 at 08:39:07AM +0900, Michael Paquier wrote: > On Tue, Nov 05, 2024 at 05:37:15PM +0000, Bertrand Drouvot wrote: > > I'm starting working on option 2, I think it will be easier to discuss with > > a patch proposal to look at. > > > > If in the meantime, one strongly disagree with option 2 (means implement a brand > > new PGSTAT_KIND_BACKEND and keep PGSTAT_KIND_IO), please let me know. > > Sorry for the late reply, catching up a bit. No problem at all, thanks for looking at it! > As you are quoting in [1], you do not expect the backend-io stats and > the more global pg_stat_io to achieve the same level of consistency as > the backend stats would be gone at restart, and wiped out when a > backend shuts down. Yes. > So, splitting them with a different stats kind > feels more natural because it would be possible to control how each > stat kind behaves depending on the code shutdown and reset paths > within their own callbacks rather than making the callbacks of > PGSTAT_KIND_IO more complex than they already are. Yeah, thanks for sharing your thoughts. > And pg_stat_io is > a fixed-numbered stats kind because of the way it aggregates its stats > with a number states defined at compile-time. > > Is the structure you have in mind different than PgStat_BktypeIO? Very close. > Perhaps a split is better anyway with that in mind. The in-progress patch (not shared yet) is using the following: " typedef struct PgStat_Backend { TimestampTz stat_reset_timestamp; BackendType bktype; PgStat_BktypeIO stats; } PgStat_Backend; " The bktype is used to be able to filter the stats correctly when we display them. > The amount of memory required to store the snapshots of backend-IO > does not worry me much, TBH, but you are worried about a high turnover > of connections that could cause a lot of bloat in the backend-IO > snapshots because of the persistency that these stats would have, > right? Not only a high turnover but also a high number of entries created in the hash. Furthermore I don't see any use case of relying on stats_fetch_consistency while querying other backend's stats. > If possible, supporting snapshots would be > more consistent with the other stats. I have I mind to support the snapshots _only_ when querying our own stats. I can measure the memory impact if we use them also when querying other backends stats too (though I don't see a use case). > Just to be clear, I am not in favor of making PgStat_HashKey larger > than it already is. That's not needed, the patch I'm working on stores the proc number in the objid field of the key. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-07T00:50:59Z
On Wed, Nov 06, 2024 at 01:51:02PM +0000, Bertrand Drouvot wrote: > That's not needed, the patch I'm working on stores the proc number in the > objid field of the key. Relying on the procnumber for the object ID gets a +1 here. That provides an automatic cap on the maximum number of entries that can exist at once for this new stats kind. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-07T16:32:44Z
Hi, On Thu, Nov 07, 2024 at 09:50:59AM +0900, Michael Paquier wrote: > On Wed, Nov 06, 2024 at 01:51:02PM +0000, Bertrand Drouvot wrote: > > That's not needed, the patch I'm working on stores the proc number in the > > objid field of the key. > > Relying on the procnumber for the object ID gets a +1 here. Thanks! > That > provides an automatic cap on the maximum number of entries that can > exist at once for this new stats kind. Yeah. POC patch is now working, will wear a reviewer hat now and will share in one or 2 days. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-08T14:09:30Z
Hi, On Thu, Nov 07, 2024 at 04:32:44PM +0000, Bertrand Drouvot wrote: > Hi, > > On Thu, Nov 07, 2024 at 09:50:59AM +0900, Michael Paquier wrote: > > On Wed, Nov 06, 2024 at 01:51:02PM +0000, Bertrand Drouvot wrote: > > > That's not needed, the patch I'm working on stores the proc number in the > > > objid field of the key. > > > > Relying on the procnumber for the object ID gets a +1 here. > > Thanks! > > > That > > provides an automatic cap on the maximum number of entries that can > > exist at once for this new stats kind. > > Yeah. > > POC patch is now working, will wear a reviewer hat now and will share in one > or 2 days. > Please find attached v5 that implements the per-backend IO stats as variable-numbered stats kind (as per the up-thread discussion). It is split into 4 sub-patches: ==== 0001 (the largest one) Introduces a new statistics KIND. It is named PGSTAT_KIND_PER_BACKEND as it could be used in the future to store other statistics (than the I/O ones) per backend. The new KIND is a variable-numbered one and has an automatic cap on the maximum number of entries (as its hash key contains the proc number). There is no need to serialize the per backend I/O stats to disk (no point to see stats for backends that do not exist anymore after a re-start), so a new "to_serialize" field is added in the PgStat_KindInfo struct. It adds a new pg_my_stat_io view to display "my" backend I/O statistics. It also adds a new function pg_stat_reset_single_backend_io_counters() to be able to reset the I/O stats for a given backend pid. It contains doc updates and dedicated tests. A few remarks: 1. one assertion in pgstat_drop_entry_internal() is not necessary true anymore with this new stat kind. So, adding an extra bool as parameter to take care of it. 2. a new struct "PgStat_Backend" is created and does contain the backend type. The backend type is used for filtering purpose when the stats are displayed. 3. when the stats are reset, we need to keep the backend type so the change in shared_stat_reset_contents(). 4. the pending stats are updated in the existing pgstat_count_io_op_n() and pgstat_count_io_op_time() functions. 5. this new kind has its own flush callback: pgstat_per_backend_flush_cb(). But there is no need to maintain 2 callbacks for the I/O stats, so 0002 will merge both and remove the one from the fixed stats. The reason it's not done in 0001 is to ease the review. ==== 0002 Merge both IO stats flush callback. There is no need to keep both callbacks. Merging both allows to save O(N^3) while looping on IOOBJECT_NUM_TYPES, IOCONTEXT_NUM_TYPES and IOCONTEXT_NUM_TYPES. The patch removes: 1. pgstat_io_flush_cb() 2. PendingIOStats (as the same information is already stored in the pending entries) 3. have_iostats (the patch relies on the pending entries instead) ==== 0003 Don't include other backend's stats in the snapshot. When stats_fetch_consistency is set to 'snapshot', don't include other backend's stats in the snapshot. There is no use case, so save memory usage. ==== 0004 Adding the pg_stat_get_backend_io() function to retrieve I/O statistics for a particular backend pid. Note that this function does not return any rows if stats_fetch_consistency is set to 'snapshot' and the pid of interest is not our own pid (there is no use case of retrieving other backend's stats with stats_fetch_consistency set to 'snapshot'). The patch: 1. replaces pg_stat_get_my_io() with pg_stat_get_backend_io() 2. adds pgstat_fetch_proc_stat_io() 3. adds doc 4. adds tests === Remarks R1. The key field is still "objid" even if it stores the proc number. I think that's fine and there is no need to rename it as it's related comment states: " /* object ID (table, function, etc.), or identifier. */ " R2. pg_stat_get_io() and pg_stat_get_backend_io() could probably be merged ( duplicated code). That's not mandatory to provide the new per backend I/O stats feature. So let's keep it as future work to ease the review. R3. There is no use case of retrieving other backend's IO stats with stats_fetch_consistency set to 'snapshot'. Avoiding this behavior allows us to save memory (that could be non negligeable as pgstat_build_snapshot() would add _all_ the other backend's stats in the snapshot). I choose to document it and to not return any rows: I think that's better than returning some data (that would not "ensure" the snapshot consistency) or an error. Looking forward to your feedback, Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-14T06:31:51Z
On Fri, Nov 08, 2024 at 02:09:30PM +0000, Bertrand Drouvot wrote: > ==== 0001 (the largest one) > > Introduces a new statistics KIND. It is named PGSTAT_KIND_PER_BACKEND as it could > be used in the future to store other statistics (than the I/O ones) per backend. > The new KIND is a variable-numbered one and has an automatic cap on the > maximum number of entries (as its hash key contains the proc number). > > There is no need to serialize the per backend I/O stats to disk (no point to > see stats for backends that do not exist anymore after a re-start), so a > new "to_serialize" field is added in the PgStat_KindInfo struct. > > It adds a new pg_my_stat_io view to display "my" backend I/O statistics. > > It also adds a new function pg_stat_reset_single_backend_io_counters() to be > able to reset the I/O stats for a given backend pid. > > It contains doc updates and dedicated tests. > > A few remarks: > > 1. one assertion in pgstat_drop_entry_internal() is not necessary true anymore > with this new stat kind. So, adding an extra bool as parameter to take care of it. Why? I have to admit that the addition of this argument at this level specific to a new stats kind feels really weird and it looks like a layer violation, while this happens only when resetting the whole pgstats state because we have loaded a portion of the stats but the file loaded was in such a state that we don't have a consistent picture. > 2. a new struct "PgStat_Backend" is created and does contain the backend type. > The backend type is used for filtering purpose when the stats are displayed. Is that necessary? We can guess that from the PID with a join in pg_stat_activity. pg_stat_get_backend_io() from 0004 returns a set of tuples for a specific PID, as well.. + /* save the bktype */ + if (kind == PGSTAT_KIND_PER_BACKEND) + bktype = ((PgStatShared_Backend *) header)->stats.bktype; [...] + /* restore the bktype */ + if (kind == PGSTAT_KIND_PER_BACKEND) + ((PgStatShared_Backend *) header)->stats.bktype = bktype; Including the backend type results in these blips in shared_stat_reset_contents() which should not have anything related to stats kinds and should remain neutral, as well. pgstat_prep_per_backend_pending() is used only in pgstat_io.c, so I guess that it should be static in this file rather than declared in pgstat.h? +typedef struct PgStat_PendingIO Perhaps this part should use a separate structure named "BackendPendingIO"? The definition of the structure has to be in pgstat.h as this is the pending_size of the new stats kind. It looks like it would be cleaner to keep PgStat_PendingIO local to pgstat_io.c, and define PgStat_PendingIO based on PgStat_BackendPendingIO? + /* + * Do serialize or not this kind of stats. + */ + bool to_serialize:1; Not sure that "serialize" is the best term that applies here. For pgstats entries, serialization refers to the matter of writing their entries with a "serialized" name because they have an undefined number when stored locally after a reload. I'd suggest to split this concept into its own patch, rename the flag as "write_to_file" (or what you think is suited), and also apply the flag in the fixed-numbered loop done in pgstat_write_statsfile() before going through the dshash. + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_stat_reset_single_backend_io_counters</primary> + </indexterm> + <function>pg_stat_reset_single_backend_io_counters</function> ( <type>int4</type> ) + <returnvalue>void</returnvalue> This should document that the input argument is a PID. Is pg_my_stat_io() the best name ever? I'd suggest to just merge 0004 with 0001. Structurally, it may be cleaner to keep all the callbacks and the backend-I/O specific logic into a separate file, perhaps pgstat_io_backend.c or pgstat_backend_io? > ==== 0002 > > Merge both IO stats flush callback. There is no need to keep both callbacks. > > Merging both allows to save O(N^3) while looping on IOOBJECT_NUM_TYPES, > IOCONTEXT_NUM_TYPES and IOCONTEXT_NUM_TYPES. Not sure to be a fan of that, TBH, still I get the performance argument of the matter. Each stats kind has its own flush path, and this assumes that we'll never going to diverge in terms of the information maintained for each backend and the existing pg_stat_io. Perhaps there could be a divergence at some point? > === Remarks > > R1. The key field is still "objid" even if it stores the proc number. I think > that's fine and there is no need to rename it as it's related comment states: Let's not change the object ID and the hash key. The approach you are using here with a variable-numbered stats kinds and a lookup with the procnumber is sensible here. > R2. pg_stat_get_io() and pg_stat_get_backend_io() could probably be merged ( > duplicated code). That's not mandatory to provide the new per backend I/O stats > feature. So let's keep it as future work to ease the review. Not sure about that. > R3. There is no use case of retrieving other backend's IO stats with > stats_fetch_consistency set to 'snapshot'. Avoiding this behavior allows us to > save memory (that could be non negligeable as pgstat_build_snapshot() would add > _all_ the other backend's stats in the snapshot). I choose to document it and to > not return any rows: I think that's better than returning some data (that would > not "ensure" the snapshot consistency) or an error. I'm pretty sure that there is a sensible argument about being able to get a snapshot of the I/O stat of another backend and consider that a feature. For example, keeping a look at the activity of the checkpointer while doing a scan at a certain point in time? With a GUC, we could have both behaviors and control which one we want. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-14T13:30:11Z
Hi, On Thu, Nov 14, 2024 at 03:31:51PM +0900, Michael Paquier wrote: > On Fri, Nov 08, 2024 at 02:09:30PM +0000, Bertrand Drouvot wrote: > > 1. one assertion in pgstat_drop_entry_internal() is not necessary true anymore > > with this new stat kind. So, adding an extra bool as parameter to take care of it. > > Why? I have to admit that the addition of this argument at this level > specific to a new stats kind feels really weird and it looks like a > layer violation, while this happens only when resetting the whole > pgstats state because we have loaded a portion of the stats but the > file loaded was in such a state that we don't have a consistent > picture. Yes. I agree that looks weird and I don't like it that much. But the assertion is not true anymore. If you: - change the arguments to false in the pgstat_drop_entry_internal() call in pgstat_drop_all_entries() - start the engine - kill -9 postgres - restart the engine You'll see the assert failing due to the startup process. I don't think it is doing something wrong though, just populating its backend stats. Do you have another view on it? > > 2. a new struct "PgStat_Backend" is created and does contain the backend type. > > The backend type is used for filtering purpose when the stats are displayed. > > Is that necessary? We can guess that from the PID with a join in > pg_stat_activity. pg_stat_get_backend_io() from 0004 returns a set of > tuples for a specific PID, as well.. How would that work for someone doing "select * from pg_stat_get_backend_io(<pid>)"? Do you mean copy/paste part of the code from pg_stat_get_activity() into pg_stat_get_backend_io() to get the backend type? That sounds like an idea, I'll have a look at it. > + /* save the bktype */ > + if (kind == PGSTAT_KIND_PER_BACKEND) > + bktype = ((PgStatShared_Backend *) header)->stats.bktype; > [...] > + /* restore the bktype */ > + if (kind == PGSTAT_KIND_PER_BACKEND) > + ((PgStatShared_Backend *) header)->stats.bktype = bktype; > > Including the backend type results in these blips in > shared_stat_reset_contents() which should not have anything related > to stats kinds and should remain neutral, as well. Yeah, we can simply get rid of it if we remove the backend type in PgStat_Backend. > pgstat_prep_per_backend_pending() is used only in pgstat_io.c, so I > guess that it should be static in this file rather than declared in > pgstat.h? Good catch, thanks! > +typedef struct PgStat_PendingIO > > Perhaps this part should use a separate structure named > "BackendPendingIO"? The definition of the structure has to be in > pgstat.h as this is the pending_size of the new stats kind. It looks > like it would be cleaner to keep PgStat_PendingIO local to > pgstat_io.c, and define PgStat_PendingIO based on > PgStat_BackendPendingIO? I see what you meean, what about simply "PgStat_BackendPending" in pgstat.h? > + /* > + * Do serialize or not this kind of stats. > + */ > + bool to_serialize:1; > > Not sure that "serialize" is the best term that applies here. For > pgstats entries, serialization refers to the matter of writing their > entries with a "serialized" name because they have an undefined number > when stored locally after a reload. I'd suggest to split this concept > into its own patch, rename the flag as "write_to_file" (or what you > think is suited), and also apply the flag in the fixed-numbered loop > done in pgstat_write_statsfile() before going through the dshash. Makes sense to create its own patch, will have a look. > + <row> > + <entry role="func_table_entry"><para role="func_signature"> > + <indexterm> > + <primary>pg_stat_reset_single_backend_io_counters</primary> > + </indexterm> > + <function>pg_stat_reset_single_backend_io_counters</function> ( <type>int4</type> ) > + <returnvalue>void</returnvalue> > > This should document that the input argument is a PID. Yeap, will add. > > Is pg_my_stat_io() the best name ever? Not 100% sure, but there is already "pg_my_temp_schema" so I thought that pg_my_stat_io would not be that bad. Open to suggestions though. > I'd suggest to just merge 0004 with 0001. Sure. > Structurally, it may be cleaner to keep all the callbacks and the > backend-I/O specific logic into a separate file, perhaps > pgstat_io_backend.c or pgstat_backend_io? Yeah, I was wondering the same. What about pgstat_backend.c (that would contain only one "section" dedicated to IO currently)? > > ==== 0002 > > > > Merge both IO stats flush callback. There is no need to keep both callbacks. > > > > Merging both allows to save O(N^3) while looping on IOOBJECT_NUM_TYPES, > > IOCONTEXT_NUM_TYPES and IOCONTEXT_NUM_TYPES. > > Not sure to be a fan of that, TBH, still I get the performance > argument of the matter. Each stats kind has its own flush path, and > this assumes that we'll never going to diverge in terms of the > information maintained for each backend and the existing pg_stat_io. > Perhaps there could be a divergence at some point? Yeah perhaps, so in case of divergence let's split "again"? I mean for the moment I don't see any reason to keep both and we have pros related to efficiency during flush. > > === Remarks > > > > R1. The key field is still "objid" even if it stores the proc number. I think > > that's fine and there is no need to rename it as it's related comment states: > > Let's not change the object ID and the hash key. The approach you are > using here with a variable-numbered stats kinds and a lookup with the > procnumber is sensible here. Agree, thanks for confirming. > > R2. pg_stat_get_io() and pg_stat_get_backend_io() could probably be merged ( > > duplicated code). That's not mandatory to provide the new per backend I/O stats > > feature. So let's keep it as future work to ease the review. > > Not sure about that. I don't have a strong opinion about this one, so I'm ok to not merge those. > > R3. There is no use case of retrieving other backend's IO stats with > > stats_fetch_consistency set to 'snapshot'. Avoiding this behavior allows us to > > save memory (that could be non negligeable as pgstat_build_snapshot() would add > > _all_ the other backend's stats in the snapshot). I choose to document it and to > > not return any rows: I think that's better than returning some data (that would > > not "ensure" the snapshot consistency) or an error. > > I'm pretty sure that there is a sensible argument about being able to > get a snapshot of the I/O stat of another backend and consider that a > feature. For example, keeping a look at the activity of the > checkpointer while doing a scan at a certain point in time? hm, not sure how the stats_fetch_consistency set to 'snapshot' could help here: - the checkpointer could write stuff for reason completly unrelated to "your" backend - if the idea is to 1. record checkpointer stats, 2. do stuff in the backend and 3. check again the checkpointer stats then I don't think setting stats_fetch_consistency to snapshot is needed at all. In fact it's quite the opposite as 1. and 3. would report the same values with stats_fetch_consistency set to 'snapshot' (if done in the same transaction). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-19T01:47:53Z
On Thu, Nov 14, 2024 at 01:30:11PM +0000, Bertrand Drouvot wrote: > - change the arguments to false in the pgstat_drop_entry_internal() call in > pgstat_drop_all_entries() > - start the engine > - kill -9 postgres > - restart the engine > > You'll see the assert failing due to the startup process. I don't think it is > doing something wrong though, just populating its backend stats. Do you have > another view on it? It feels sad that we have to plug in the internals at this level for this particular case. Perhaps there is something to do with more callbacks. Or perhaps there is just no point in tracking the stats of auxiliary processes because we already have this data in the existing pg_stat_io already? > How would that work for someone doing "select * from pg_stat_get_backend_io(<pid>)"? > > Do you mean copy/paste part of the code from pg_stat_get_activity() into > pg_stat_get_backend_io() to get the backend type? That sounds like an idea, > I'll have a look at it. I was under the impression that we should keep PgStat_Backend for the reset_timestamp part, but drop BackendType as it can be guessed from pg_stat_activity itself. For example a LATERAL to grab the current live stats of these backends. >> +typedef struct PgStat_PendingIO >> >> Perhaps this part should use a separate structure named >> "BackendPendingIO"? The definition of the structure has to be in >> pgstat.h as this is the pending_size of the new stats kind. It looks >> like it would be cleaner to keep PgStat_PendingIO local to >> pgstat_io.c, and define PgStat_PendingIO based on >> PgStat_BackendPendingIO? > > I see what you meean, what about simply "PgStat_BackendPending" in pgstat.h? That should be OK. >> Structurally, it may be cleaner to keep all the callbacks and the >> backend-I/O specific logic into a separate file, perhaps >> pgstat_io_backend.c or pgstat_backend_io? > > Yeah, I was wondering the same. What about pgstat_backend.c (that would contain > only one "section" dedicated to IO currently)? pgstat_backend.c looks good to me. Could there be other stats than just IO, actually? Perhaps not, just asking.. > - if the idea is to 1. record checkpointer stats, 2. do stuff in the backend and > 3. check again the checkpointer stats then I don't think setting stats_fetch_consistency > to snapshot is needed at all. In fact it's quite the opposite as 1. and 3. would > report the same values with stats_fetch_consistency set to 'snapshot' (if done > in the same transaction). Hmm. Not sure. It looks like you're right to treat this in a separate patch as it would exist for different reasons than the original proposal. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-19T16:28:55Z
Hi, On Tue, Nov 19, 2024 at 10:47:53AM +0900, Michael Paquier wrote: > On Thu, Nov 14, 2024 at 01:30:11PM +0000, Bertrand Drouvot wrote: > > - change the arguments to false in the pgstat_drop_entry_internal() call in > > pgstat_drop_all_entries() > > - start the engine > > - kill -9 postgres > > - restart the engine > > > > You'll see the assert failing due to the startup process. I don't think it is > > doing something wrong though, just populating its backend stats. Do you have > > another view on it? > > It feels sad that we have to plug in the internals at this level for > this particular case. Perhaps there is something to do with more > callbacks. Or perhaps there is just no point in tracking the stats of > auxiliary processes because we already have this data in the existing > pg_stat_io already? We can not discard the "per backend" stats collection for auxiliary processes because those are the source for pg_stat_io too (once the 2 flush callbacks are merged). I have another idea: after a bit more of investigation it turns out that only the startup process is generating the failed assertion. So, for the startup process only, what about? - don't call pgstat_create_backend_stat() in pgstat_beinit()... - but call it in StartupXLOG() instead (after the stats are discarded or restored). That way we could get rid of the changes linked to the assertion and still handle the startup process particular case. Thoughts? > > How would that work for someone doing "select * from pg_stat_get_backend_io(<pid>)"? > > > > Do you mean copy/paste part of the code from pg_stat_get_activity() into > > pg_stat_get_backend_io() to get the backend type? That sounds like an idea, > > I'll have a look at it. > > I was under the impression that we should keep PgStat_Backend for the > reset_timestamp part, but drop BackendType as it can be guessed from > pg_stat_activity itself. Removing BackendType sounds doable, I'll look at it. > >> Structurally, it may be cleaner to keep all the callbacks and the > >> backend-I/O specific logic into a separate file, perhaps > >> pgstat_io_backend.c or pgstat_backend_io? > > > > Yeah, I was wondering the same. What about pgstat_backend.c (that would contain > > only one "section" dedicated to IO currently)? > > pgstat_backend.c looks good to me. Could there be other stats than > just IO, actually? Perhaps not, just asking.. Yeah that's the reason why I suggested "pgstat_backend.c". I would not be surprised if we add more "per backend" stats (that are not I/O related) in the future as the main machinery would be there. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-20T00:01:26Z
On Tue, Nov 19, 2024 at 04:28:55PM +0000, Bertrand Drouvot wrote: > So, for the startup process only, what about? > > - don't call pgstat_create_backend_stat() in pgstat_beinit()... > - but call it in StartupXLOG() instead (after the stats are discarded or restored). > > That way we could get rid of the changes linked to the assertion and still handle > the startup process particular case. Thoughts? Hmm. That may prove to be a good idea in the long-term. The startup process is a specific path kicked in at a very early stage, so it is also a bit weird that we'd try to insert statistics while we are going to reset them anyway a bit later. That may also be relevant for custom statistics, actually, especially if some calls happen in some hook paths taken before the reset is done. This could happen for injection point stats when loading it with shared_preload_libraries, actually, if you load, attach or run a callback at this early stage. The existing sanity checks are a safety net that we should not change or adapt for specific stats kinds conditions, IMO. Perhaps this had better be done as a patch of its own, on top of the rest. > Yeah that's the reason why I suggested "pgstat_backend.c". I would not be > surprised if we add more "per backend" stats (that are not I/O related) in the > future as the main machinery would be there. Okay. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-20T14:10:23Z
Hi, On Thu, Nov 14, 2024 at 03:31:51PM +0900, Michael Paquier wrote: > + /* > + * Do serialize or not this kind of stats. > + */ > + bool to_serialize:1; > > Not sure that "serialize" is the best term that applies here. For > pgstats entries, serialization refers to the matter of writing their > entries with a "serialized" name because they have an undefined number > when stored locally after a reload. I'd suggest to split this concept > into its own patch, rename the flag as "write_to_file" Yeah, also this could useful for custom statistics. So I created a dedicated thread and a patch proposal (see [1]). [1]: https://www.postgresql.org/message-id/Zz3skBqzBncSFIuY%40ip-10-97-1-34.eu-west-3.compute.internal Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-20T14:20:18Z
Hi, On Wed, Nov 20, 2024 at 09:01:26AM +0900, Michael Paquier wrote: > On Tue, Nov 19, 2024 at 04:28:55PM +0000, Bertrand Drouvot wrote: > > So, for the startup process only, what about? > > > > - don't call pgstat_create_backend_stat() in pgstat_beinit()... > > - but call it in StartupXLOG() instead (after the stats are discarded or restored). > > > > That way we could get rid of the changes linked to the assertion and still handle > > the startup process particular case. Thoughts? > > Hmm. That may prove to be a good idea in the long-term. The startup > process is a specific path kicked in at a very early stage, so it is > also a bit weird that we'd try to insert statistics while we are going > to reset them anyway a bit later. Exactly. > That may also be relevant for > custom statistics, actually, especially if some calls happen in some > hook paths taken before the reset is done. This could happen for > injection point stats when loading it with shared_preload_libraries, > actually, if you load, attach or run a callback at this early stage. Right. I did not had in mind to go that far here (for the per backend stats needs). My idea was "just" to move the new pgstat_create_backend_stat() (which is related to per backend stats only) call at the right place in StartupXLOG() for the startup process only. As that's the startup process that will reset or restore the stats I think that makes sense. It looks like that what you have in mind is much more generic, what about: - Focus on this thread first and then move the call as proposed above - Think about a more generic idea later on (on the per-backend I/O stats is in). Thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-20T22:18:24Z
On Wed, Nov 20, 2024 at 02:20:18PM +0000, Bertrand Drouvot wrote: > Right. I did not had in mind to go that far here (for the per backend stats > needs). My idea was "just" to move the new pgstat_create_backend_stat() (which > is related to per backend stats only) call at the right place in StartupXLOG() > for the startup process only. As that's the startup process that will reset > or restore the stats I think that makes sense. > > It looks like that what you have in mind is much more generic, what about: > > - Focus on this thread first and then move the call as proposed above > - Think about a more generic idea later on (on the per-backend I/O stats is > in). Moving pgstat_create_backend_stat() may be OK in the long-term, at least that would document why we need to care about the startup process. Still, moving only the call feels incomplete, so how about adding a boolean field in PgStat_ShmemControl that defaults to false when the shmem area is initialized in StatsShmemInit(), then switched to true once we know that the stats have been restored or reset by the startup process. Something like that should work to control the dshash inserts, I guess? -- Michael
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-21T00:42:03Z
On Wed, Nov 20, 2024 at 02:10:23PM +0000, Bertrand Drouvot wrote: > Yeah, also this could useful for custom statistics. So I created a dedicated > thread and a patch proposal (see [1]). > > [1]: https://www.postgresql.org/message-id/Zz3skBqzBncSFIuY%40ip-10-97-1-34.eu-west-3.compute.internal Thanks for putting that on its own thread. Will look at it. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-21T17:23:42Z
Hi, On Thu, Nov 21, 2024 at 07:18:24AM +0900, Michael Paquier wrote: > On Wed, Nov 20, 2024 at 02:20:18PM +0000, Bertrand Drouvot wrote: > > Right. I did not had in mind to go that far here (for the per backend stats > > needs). My idea was "just" to move the new pgstat_create_backend_stat() (which > > is related to per backend stats only) call at the right place in StartupXLOG() > > for the startup process only. As that's the startup process that will reset > > or restore the stats I think that makes sense. > > > > It looks like that what you have in mind is much more generic, what about: > > > > - Focus on this thread first and then move the call as proposed above > > - Think about a more generic idea later on (on the per-backend I/O stats is > > in). > > Moving pgstat_create_backend_stat() may be OK in the long-term, at > least that would document why we need to care about the startup > process. Yeap. > Still, moving only the call feels incomplete, so how about adding a > boolean field in PgStat_ShmemControl that defaults to false when the > shmem area is initialized in StatsShmemInit(), then switched to true > once we know that the stats have been restored or reset by the startup > process. Something like that should work to control the dshash > inserts, I guess? I did some tests (on a primary and on a standby) and currently there is no call to pgstat_get_entry_ref() at all before we reach the stats reset or restore in StartupXLOG(). The first ones appear after "we really open for business" (quoting process_pm_child_exit()). Now, with the per-backend I/O stats patch in place, there is 3 processes that could call pgstat_get_entry_ref() before we reach the stats reset or restore in StartupXLOG() (observed by setting a breakpoint on the startup process before stats are reset or restored): - checkpointer - background writer - startup process All calls are for the new backend stat kind. It also makes sense to see non "regular" backends as the "regulars" are not allowed to connect yet. Results: they could collect some stats for nothing since a reset or restore will happen after. Now, if we want to prevent new entries to be created before the stats are reset or restored: - then the end results will be the same (means starting the instance with reset or restored stats). The only difference would be that they would not collect stats for "nothing" during this small time window. - it looks like that would lead to some non negligible refactoring: I started the coding and observed the potential impact. The reason is that all the code (at least the one I looked at) does not expect to receive a NULL value from pgstat_get_entry_ref() (when asking for creation) and we would need to take care of all the cases (all the stats, all backend type) for safety reason. So, given that: - the end result would be the same - the code changes would be non negligible (unless we have a better idea than pgstat_get_entry_ref() returning a NULL value). I think that might be valid to try to implement it (to avoid those processes to collect the stats for nothing during this small time window) but I am not sure that's worth it (as the end result would be the same and the code change non negligible). Thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-22T01:36:29Z
On Thu, Nov 21, 2024 at 05:23:42PM +0000, Bertrand Drouvot wrote: > So, given that: > > - the end result would be the same > - the code changes would be non negligible (unless we have a better idea than > pgstat_get_entry_ref() returning a NULL value). Hmm. created_entry only matters for pgstat_init_function_usage(). All the other callers of pgstat_prep_pending_entry() pass a NULL value. This makes me wonder if there is an argument for reworking a bit that. There's a fat comment about the reason why, still, that would make the get interface for variable-numbered stats a lot leaner.. Not sure what to think about that. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-22T07:49:58Z
Hi, On Fri, Nov 22, 2024 at 10:36:29AM +0900, Michael Paquier wrote: > On Thu, Nov 21, 2024 at 05:23:42PM +0000, Bertrand Drouvot wrote: > > So, given that: > > > > - the end result would be the same > > - the code changes would be non negligible (unless we have a better idea than > > pgstat_get_entry_ref() returning a NULL value). > > Hmm. created_entry only matters for pgstat_init_function_usage(). > All the other callers of pgstat_prep_pending_entry() pass a NULL > value. I meant to say all the calls that passe "create" as true in pgstat_get_entry_ref(). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-25T01:06:44Z
On Fri, Nov 22, 2024 at 07:49:58AM +0000, Bertrand Drouvot wrote: > On Fri, Nov 22, 2024 at 10:36:29AM +0900, Michael Paquier wrote: >> Hmm. created_entry only matters for pgstat_init_function_usage(). >> All the other callers of pgstat_prep_pending_entry() pass a NULL >> value. > > I meant to say all the calls that passe "create" as true in pgstat_get_entry_ref(). Ah, OK, I think that I see your point here. I am wondering how much this would matter as well for custom stats, but we're not there yet without at least one release out and folks try new things with these APIs and variable-numbered kinds. Allowing pgstat_prep_pending_entry() to return NULL even if "create" is true may be a good thing, at the end, because that's the only way I can see based on the current APIs where we could say "Sorry, but the stats have not been loaded yet, so you cannot try to do anything related to the dshash". From my view having a kind of barrier would be cleaner in the long run, but it's true that it may not be mandatory, as well. pg_stat_io is currently OK to be called because the stats are loaded for auxiliary processes because it uses fixed-numbered stats in shmem. And it means we already have early calls that add stats getting overwritten once the stats are loaded from the on-disk file (Am I getting this part right?). Anyway, do we really require that for the sake of this thread? We know that there's only one of each auxiliary process at a time, and they keep a footprint in pg_stat_io already. So we could just limit outselves to live database backends, WAL senders and autovacuum workers, everything that's not auxiliary and spawned on request? -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-25T07:12:56Z
Hi, On Mon, Nov 25, 2024 at 10:06:44AM +0900, Michael Paquier wrote: > On Fri, Nov 22, 2024 at 07:49:58AM +0000, Bertrand Drouvot wrote: > > On Fri, Nov 22, 2024 at 10:36:29AM +0900, Michael Paquier wrote: > >> Hmm. created_entry only matters for pgstat_init_function_usage(). > >> All the other callers of pgstat_prep_pending_entry() pass a NULL > >> value. > > > > I meant to say all the calls that passe "create" as true in pgstat_get_entry_ref(). > > Ah, OK, I think that I see your point here. > > I am wondering how much this would matter as well for custom stats, > but we're not there yet without at least one release out and folks try > new things with these APIs and variable-numbered kinds. Not sure here, could custom stats start incrementing before the database system is ready to accept connections? > pgstat_prep_pending_entry() to return NULL even if "create" is true > may be a good thing, at the end, because that's the only way I can see > based on the current APIs where we could say "Sorry, but the stats > have not been loaded yet, so you cannot try to do anything related to > the dshash". Yeah, same here. > From my view having a kind of barrier would be cleaner in the long > run, but it's true that it may not be mandatory, as well. pg_stat_io > is currently OK to be called because the stats are loaded for > auxiliary processes because it uses fixed-numbered stats in shmem. > And it means we already have early calls that add stats getting > overwritten once the stats are loaded from the on-disk file (Am I > getting this part right?). Yeah, we can already see that, for example, the background writer could enter pgstat_io_flush_cb() before the stats are reset or restored. > Anyway, do we really require that for the sake of this thread? We > know that there's only one of each auxiliary process at a time, and > they keep a footprint in pg_stat_io already. So we could just limit > outselves to live database backends, WAL senders and autovacuum > workers, everything that's not auxiliary and spawned on request? I think that's a fair starting point and that we will not lose any informations doing so (as you said there is only one of each auxiliary process at a time, so that one could already see their stats from pg_stat_io). The only cons that I can see is that we will not be able to merge the flush cb but I don't think that's a blocker (the flush are done in shared memory so the impact on performance should not be that much of an issue). I'll come back with a new version implementing the above. [1]: https://www.postgresql.org/message-id/Zz9sno%2BJJbWqdXhQ%40ip-10-97-1-34.eu-west-3.compute.internal Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics[
Michael Paquier <michael@paquier.xyz> — 2024-11-25T07:18:54Z
On Mon, Nov 25, 2024 at 07:12:56AM +0000, Bertrand Drouvot wrote: > Not sure here, could custom stats start incrementing before the database system > is ready to accept connections? In theory, that could be possible. Like pg_stat_io currently, I am ready to assume that it likely won't matter much. > The only cons that I can see is that we will not be able to merge the flush cb > but I don't think that's a blocker (the flush are done in shared memory so the > impact on performance should not be that much of an issue). The backend and I/O stats could begin diverging as a result of a new implementation detail, and the performance of the flushes don't worry me knowing at which frequency they happen on a live system. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-25T15:47:59Z
Hi, On Mon, Nov 25, 2024 at 04:18:54PM +0900, Michael Paquier wrote: > On Mon, Nov 25, 2024 at 07:12:56AM +0000, Bertrand Drouvot wrote: > > Not sure here, could custom stats start incrementing before the database system > > is ready to accept connections? > > In theory, that could be possible. Like pg_stat_io currently, I am > ready to assume that it likely won't matter much. Yeah right, agree. > > The only cons that I can see is that we will not be able to merge the flush cb > > but I don't think that's a blocker (the flush are done in shared memory so the > > impact on performance should not be that much of an issue). > > The backend and I/O stats could begin diverging as a result of a new > implementation detail, and the performance of the flushes don't worry > me knowing at which frequency they happen on a live system. Same here. Please find attached v6 that enables per-backend I/O stats for the B_AUTOVAC_WORKER, B_BACKEND, B_BG_WORKER, B_STANDALONE_BACKEND, B_SLOTSYNC_WORKER and B_WAL_SENDER backend types. It also takes care of most of the comments that you have made in [1], meaning that it: - removes the backend type from PgStat_Backend and look for the backend type at "display" time. - creates PgStat_BackendPendingIO and PgStat_PendingIO now refers to it (I used PgStat_BackendPendingIO and not PgStat_BackendPending because this is what it is after all). - adds the missing comment related to the PID in the doc. - merges 0004 with 0001 (so that pg_stat_get_backend_io() is now part of 0001). - creates its own pgstat_backend.c file. === Remarks R1: as compared to v5, v6 removes the per-backend I/O stats reset from pg_stat_reset_shared(). I think it makes more sense that way, since we are adding pg_stat_reset_single_backend_io_counters(). The per-backend I/O stats behaves then as the subscription stats as far the reset is concerned. R2: as we can't merge the flush cb anymore, only the patches related to the stats_fetch_consistency/'snapshot' are missing in v6 (as compared to v5). I propose to re-submit them, re-start the discussion once 0001 goes in. [1]: https://www.postgresql.org/message-id/ZzWZV9LdyZ9aFSWs%40paquier.xyz Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-11-27T06:33:38Z
On Mon, Nov 25, 2024 at 03:47:59PM +0000, Bertrand Drouvot wrote: > It also takes care of most of the comments that you have made in [1], meaning > that it: > > - removes the backend type from PgStat_Backend and look for the backend type > at "display" time. > - creates PgStat_BackendPendingIO and PgStat_PendingIO now refers to it (I > used PgStat_BackendPendingIO and not PgStat_BackendPending because this is what > it is after all). > - adds the missing comment related to the PID in the doc. > - merges 0004 with 0001 (so that pg_stat_get_backend_io() is now part of 0001). > - creates its own pgstat_backend.c file. I have begun studying the patch, and I have one question. +void +pgstat_create_backend_stat(ProcNumber procnum) [...] + /* Create the per-backend statistics entry */ + if (pgstat_tracks_per_backend_bktype(MyBackendType)) + pgstat_create_backend_stat(MyProcNumber); Perhaps that's a very stupid question, but I was looking at this part of the patch, and wondered why we don't use init_backend_cb? I vaguely recalled that MyProcNumber and MyBackendType would be set before we go through the pgstat initialization step. MyDatabaseId is filled after the pgstat initialization, but we don't care about this information for such backend stats. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-11-27T16:00:14Z
Hi, On Wed, Nov 27, 2024 at 03:33:38PM +0900, Michael Paquier wrote: > On Mon, Nov 25, 2024 at 03:47:59PM +0000, Bertrand Drouvot wrote: > > It also takes care of most of the comments that you have made in [1], meaning > > that it: > > > > - removes the backend type from PgStat_Backend and look for the backend type > > at "display" time. > > - creates PgStat_BackendPendingIO and PgStat_PendingIO now refers to it (I > > used PgStat_BackendPendingIO and not PgStat_BackendPending because this is what > > it is after all). > > - adds the missing comment related to the PID in the doc. > > - merges 0004 with 0001 (so that pg_stat_get_backend_io() is now part of 0001). > > - creates its own pgstat_backend.c file. > > I have begun studying the patch, and I have one question. > > +void > +pgstat_create_backend_stat(ProcNumber procnum) > [...] > + /* Create the per-backend statistics entry */ > + if (pgstat_tracks_per_backend_bktype(MyBackendType)) > + pgstat_create_backend_stat(MyProcNumber); > > Perhaps that's a very stupid question, but I was looking at this part > of the patch, and wondered why we don't use init_backend_cb? I > vaguely recalled that MyProcNumber and MyBackendType would be set > before we go through the pgstat initialization step. MyDatabaseId is > filled after the pgstat initialization, but we don't care about this > information for such backend stats. Using init_backend_cb (and moving the pgstat_tracks_per_backend_bktype() check in it) is currently producing a failed assertion: TRAP: failed Assert("pgstat_is_initialized && !pgstat_is_shutdown"), File: "pgstat.c", Line: 1567, PID: 2080000 postgres: postgres postgres [local] initializing(ExceptionalCondition+0xbb)[0x5fd0c69afaed] postgres: postgres postgres [local] initializing(pgstat_assert_is_up+0x3f)[0x5fd0c67d1b77] postgres: postgres postgres [local] initializing(pgstat_get_entry_ref+0x95)[0x5fd0c67db068] postgres: postgres postgres [local] initializing(pgstat_prep_pending_entry+0xaa)[0x5fd0c67d1181] postgres: postgres postgres [local] initializing(pgstat_create_backend_stat+0x96)[0x5fd0c67d3986] But even if we, say move the "pgstat_is_initialized = true" before the init_backend_cb() call in pgstat_initialize() (not saying that makes sense, just trying out), then we are back to the restore/reset issue but this time during initdb: TRAP: failed Assert("!pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, shent->key)"), File: "pgstat_shmem.c", Line: 852, PID: 2109086 /home/postgres/postgresql/pg_installed/pg18/bin/postgres(ExceptionalCondition+0xbb)[0x621723499c5a] /home/postgres/postgresql/pg_installed/pg18/bin/postgres(+0x70dd2b)[0x6217232c5d2b] /home/postgres/postgresql/pg_installed/pg18/bin/postgres(pgstat_drop_all_entries+0x61)[0x6217232c60b5] /home/postgres/postgresql/pg_installed/pg18/bin/postgres(+0x705356)[0x6217232bd356] /home/postgres/postgresql/pg_installed/pg18/bin/postgres(+0x70462a)[0x6217232bc62a] /home/postgres/postgresql/pg_installed/pg18/bin/postgres(pgstat_restore_stats+0x1c)[0x6217232b9f01] /home/postgres/postgresql/pg_installed/pg18/bin/postgres(StartupXLOG+0x693)[0x621722da9697] /home/postgres/postgresql/pg_installed/pg18/bin/postgres(InitPostgres+0x1d8)[0x6217234b40df] /home/postgres/postgresql/pg_installed/pg18/bin/postgres(BootstrapModeMain+0x532)[0x621722dd79bf] where "PID: 2109086" is a B_STANDALONE_BACKEND. This is due to the fact that, during the initdb bootstrap, init_backend_cb() is called before StartupXLOG(). One option could be to move B_STANDALONE_BACKEND in the "false" section of pgstat_tracks_per_backend_bktype() and ensure that we set pgstat_is_initialized to true before init_backend_cb() is called (but I don't think that makes that much sense). I'd vote to just keep the pgstat_create_backend_stat() call in pgstat_beinit(). That said, we probably should document that init_backend_cb() should not call pgstat_get_entry_ref(), but that's probably worth another thread. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-12T04:11:09Z
On Wed, Nov 27, 2024 at 04:00:14PM +0000, Bertrand Drouvot wrote: > I'd vote to just keep the pgstat_create_backend_stat() call in pgstat_beinit(). > > That said, we probably should document that init_backend_cb() should not call > pgstat_get_entry_ref(), but that's probably worth another thread. Hmm, yeah. I have considered this point and your approach does not seem that bad to me after thinking much more about it, and you are putting the call in pgstat_beinit(), which is about initializing the stats for the backend. So I'm OK with what the patch does here in terms of the location where pgstat_create_backend_stat() is called. -- Michael
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-12T04:52:03Z
On Mon, Nov 25, 2024 at 03:47:59PM +0000, Bertrand Drouvot wrote: > === Remarks > > R1: as compared to v5, v6 removes the per-backend I/O stats reset from > pg_stat_reset_shared(). I think it makes more sense that way, since we are > adding pg_stat_reset_single_backend_io_counters(). The per-backend I/O stats > behaves then as the subscription stats as far the reset is concerned. Makes sense to me to not include that in pg_stat_reset_shared(). > R2: as we can't merge the flush cb anymore, only the patches related to > the stats_fetch_consistency/'snapshot' are missing in v6 (as compared to v5). > I propose to re-submit them, re-start the discussion once 0001 goes in. Yeah, thanks. I should think more about this part, but I'm still kind of unconvinced. Let's do things step by step. For now, I have looked at v6. + view. The function does not return I/O statistics for the checkpointer, + the background writer, the startup process and the autovacuum launcher + as they are already visible in the <link linkend="monitoring-pg-stat-io-view"> <structname>pg_stat_io</structname></link> + view and there is only one of those. This last sentence seems unnecessary? The function is named "backend", and well, all these processes are not backends. + /* + * Maybe an auxiliary process? That should not be possible, due to + * pgstat_tracks_per_backend_bktype() though. + */ + if (proc == NULL) + proc = AuxiliaryPidGetProc(backend_pid); [...] + /* + * Maybe an auxiliary process? That should not be possible, due to + * pgstat_tracks_per_backend_bktype() though. + */ + if (proc == NULL) + proc = AuxiliaryPidGetProc(pid); This does not seem right. Shouldn't we return immediately if BackendPidGetProc() finds nothing matching with the PID? + /* Look for the backend type */ + for (curr_backend = 1; curr_backend <= num_backends; curr_backend++) + { + LocalPgBackendStatus *local_beentry; + PgBackendStatus *beentry; + + /* Get the next one in the list */ + local_beentry = pgstat_get_local_beentry_by_index(curr_backend); + beentry = &local_beentry->backendStatus; + + /* looking for specific PID, ignore all the others */ + if (beentry->st_procpid != pid) + continue; + + bktype = beentry->st_backendType; + break; + } Sounds to me that the backend type is not strictly required in this function call if pg_stat_activity can tell already that? + (void) pgstat_per_backend_flush_cb(entry_ref, nowait); I'd recommend to not directly call the callback, use a wrapper function instead if need be. pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt) { + if (track_io_timing) Noise diff. /* - * Simpler wrapper of pgstat_io_flush_cb() + * Simpler wrapper of pgstat_io_flush_cb() and pgstat_per_backend_flush_cb(). */ void pgstat_flush_io(bool nowait) This is also called in the checkpointer and the bgwriter and the walwriter via pgstat_report_wal(), which is kind of useless. Perhaps just use a different, separate function instead and use that where it makes sense (per se also the argument of upthread that backend stats may not be only IO-related..). Sounds to me that PgStat_BackendPendingIO should be PgStat_BackendPendingStats? +{ oid => '8806', descr => 'statistics: per backend IO statistics', + proname => 'pg_stat_get_backend_io', prorows => '5', proretset => 't', Similarly, s/pg_stat_get_backend_io/pg_stat_get_backend_stats/? + descr => 'statistics: reset collected IO statistics for a single backend', + proname => 'pg_stat_reset_single_backend_io_counters', provolatile => 'v', And here, pg_stat_reset_backend_stats? #define PGSTAT_KIND_SUBSCRIPTION 5 /* per-subscription statistics */ +#define PGSTAT_KIND_PER_BACKEND 6 Missing one comment here. FWIW, I'm so-so about the addition of pg_my_stat_io, knowing that pg_stat_get_backend_io(NULL/pg_backend_pid()) does the same job. I would just add a note in the docs with a query showing how to use it with pg_stat_activity. An example with LATERAL, doing the same work: select a.pid, s.* from pg_stat_activity as a, lateral pg_stat_get_backend_io(a.pid) as s where pid = pg_backend_pid(); -- Michael -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-12T14:02:38Z
Hi, On Thu, Dec 12, 2024 at 01:52:03PM +0900, Michael Paquier wrote: > On Mon, Nov 25, 2024 at 03:47:59PM +0000, Bertrand Drouvot wrote: > + view. The function does not return I/O statistics for the checkpointer, > + the background writer, the startup process and the autovacuum launcher > + as they are already visible in the <link linkend="monitoring-pg-stat-io-view"> <structname>pg_stat_io</structname></link> > + view and there is only one of those. > > This last sentence seems unnecessary? The function is named > "backend", and well, all these processes are not backends. Yeah, but you can find their pid through pg_stat_activity for which the pid field description is "Process ID of this backend". Also we can find "backend_type" in both pg_stat_activity and pg_stat_io, so I think this last sentence could help to avoid any confusion though. > + /* > + * Maybe an auxiliary process? That should not be possible, due to > + * pgstat_tracks_per_backend_bktype() though. > + */ > + if (proc == NULL) > + proc = AuxiliaryPidGetProc(backend_pid); > [...] > + /* > + * Maybe an auxiliary process? That should not be possible, due to > + * pgstat_tracks_per_backend_bktype() though. > + */ > + if (proc == NULL) > + proc = AuxiliaryPidGetProc(pid); > > This does not seem right. Shouldn't we return immediately if > BackendPidGetProc() finds nothing matching with the PID? Yeah, that would work. I was keeping the AuxiliaryPidGetProc() calls just in case we want to add the Aux processes back in the future. Replaced with a comment in v7 attached instead. > > + /* Look for the backend type */ > + for (curr_backend = 1; curr_backend <= num_backends; curr_backend++) > + { > + LocalPgBackendStatus *local_beentry; > + PgBackendStatus *beentry; > + > + /* Get the next one in the list */ > + local_beentry = pgstat_get_local_beentry_by_index(curr_backend); > + beentry = &local_beentry->backendStatus; > + > + /* looking for specific PID, ignore all the others */ > + if (beentry->st_procpid != pid) > + continue; > + > + bktype = beentry->st_backendType; > + break; > + } > > Sounds to me that the backend type is not strictly required in this > function call if pg_stat_activity can tell already that? Yeah, but it's needed in pg_stat_get_backend_io() for the stats filtering (to display only those linked to this backend type), later in the function here: + /* + * Some combinations of BackendType, IOObject, and IOContext are + * not valid for any type of IOOp. In such cases, omit the entire + * row from the view. + */ + if (!pgstat_tracks_io_object(bktype, io_obj, io_context)) + continue; OTOH, now that we get rid of the AuxiliaryPidGetProc() call in pg_stat_reset_single_backend_io_counters() we can also remove the need to look for the backend type in this function. > > + (void) pgstat_per_backend_flush_cb(entry_ref, nowait); > > I'd recommend to not directly call the callback, use a wrapper > function instead if need be. Makes sense, created its own callback in pgstat_backend.c. Bonus point, it avoids unnecessary pgstat_tracks_per_backend_bktype() checks in : pgstat_report_bgwriter() pgstat_report_checkpointer() pgstat_report_wal() as there is no attempt to call the callback anymore in those places. > /* > - * Simpler wrapper of pgstat_io_flush_cb() > + * Simpler wrapper of pgstat_io_flush_cb() and pgstat_per_backend_flush_cb(). > */ > void > pgstat_flush_io(bool nowait) > > This is also called in the checkpointer and the bgwriter and the > walwriter via pgstat_report_wal(), which is kind of useless. Perhaps > just use a different, separate function instead and use that where it > makes sense (per se also the argument of upthread that backend stats > may not be only IO-related..). Yeah, done that way. BTW, not related to this particular patch but I realized that pgstat_flush_io() is called for the walwriter. Indeed, it's coming from the pgstat_report_wal() call in WalWriterMain(). That can not report any I/O stats activity (as the walwriter is not part of the I/O stats tracking, see pgstat_tracks_io_bktype()). So it looks like, we could move pgstat_flush_io() outside of pgstat_report_wal() and add the pgstat_flush_io() calls only where they need to be made (and so, not in WalWriterMain()). Maybe a dedicated thread is worth it for that, thoughts? > Sounds to me that PgStat_BackendPendingIO should be > PgStat_BackendPendingStats? Yeah, can do that as that's what is being used for the pending_size for example. OTOH, it's clear that this one in pgstat_io.c has to be "linked" to an "IO" related one: " typedef PgStat_BackendPendingStats PgStat_PendingIO; " The right way would probably be to do something like: " typedef struct PgStat_BackendPendingStats { PgStat_BackendPendingIO pendingio; } PgStat_BackendPendingStats; " But I'm not sure that's worth it until we don't have a need to add more pending stats per-backend, thoughts? > +{ oid => '8806', descr => 'statistics: per backend IO statistics', > + proname => 'pg_stat_get_backend_io', prorows => '5', proretset => 't', > > Similarly, s/pg_stat_get_backend_io/pg_stat_get_backend_stats/? I think that's fine to keep pg_stat_get_backend_io(). If we add more per-backend stats in the future then we could add "dedicated" get functions too and a generic one retrieving all of them. > + descr => 'statistics: reset collected IO statistics for a single backend', > + proname => 'pg_stat_reset_single_backend_io_counters', provolatile => 'v', > > And here, pg_stat_reset_backend_stats? Same as above, we could imagine that in the future the backend would get mutiple stats and that one would want to reset only the I/O ones for example. > #define PGSTAT_KIND_SUBSCRIPTION 5 /* per-subscription statistics */ > +#define PGSTAT_KIND_PER_BACKEND 6 > > Missing one comment here. Yeap. > FWIW, I'm so-so about the addition of pg_my_stat_io, knowing that > pg_stat_get_backend_io(NULL/pg_backend_pid()) does the same job. Okay, I don't have a strong opinion about that. Removed in v7. > I > would just add a note in the docs with a query showing how to use it > with pg_stat_activity. An example with LATERAL, doing the same work: > select a.pid, s.* from pg_stat_activity as a, > lateral pg_stat_get_backend_io(a.pid) as s > where pid = pg_backend_pid(); I'm not sure it's worth it. I think that's clear that to get our own stats then we need to provide our own backend pid. For example pg_stat_get_activity() does not provide such an example using pg_stat_activity or using something like pg_stat_get_activity(pg_backend_pid()). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-13T02:02:53Z
On Thu, Dec 12, 2024 at 02:02:38PM +0000, Bertrand Drouvot wrote: > On Thu, Dec 12, 2024 at 01:52:03PM +0900, Michael Paquier wrote: > Yeah, but it's needed in pg_stat_get_backend_io() for the stats filtering (to > display only those linked to this backend type), later in the function here: > > + /* > + * Some combinations of BackendType, IOObject, and IOContext are > + * not valid for any type of IOOp. In such cases, omit the entire > + * row from the view. > + */ > + if (!pgstat_tracks_io_object(bktype, io_obj, io_context)) > + continue; > > OTOH, now that we get rid of the AuxiliaryPidGetProc() call in > pg_stat_reset_single_backend_io_counters() we can also remove the need to > look for the backend type in this function. Ah, you need that for the pgstat_tracks_io_object() filtering. I'm wondering if we should think about making that cheaper at some point. As a O(N^2) when coupling a call of pg_stat_get_backend_io() with a scan of pg_stat_activity, perhaps it does not matter much anyway.. Anyway, isn't it possible that this lookup loop finishes by finding nothing depending on concurrent updates of other beentries? It sounds to me that this warrants an early exit in the function. > BTW, not related to this particular patch but I realized that pgstat_flush_io() > is called for the walwriter. Indeed, it's coming from the pgstat_report_wal() > call in WalWriterMain(). That can not report any I/O stats activity (as the > walwriter is not part of the I/O stats tracking, see pgstat_tracks_io_bktype()). > > So it looks like, we could move pgstat_flush_io() outside of pgstat_report_wal() > and add the pgstat_flush_io() calls only where they need to be made (and so, not > in WalWriterMain()). Perhaps, yes. pgstat_tracks_io_bktype() has always been discarded walwriters since pgstat_io.c exists. > But I'm not sure that's worth it until we don't have a need to add more > pending stats per-backend, thoughts? Okay with your argument here. >> +{ oid => '8806', descr => 'statistics: per backend IO statistics', >> + proname => 'pg_stat_get_backend_io', prorows => '5', proretset => 't', >> >> Similarly, s/pg_stat_get_backend_io/pg_stat_get_backend_stats/? > > I think that's fine to keep pg_stat_get_backend_io(). If we add more per-backend > stats in the future then we could add "dedicated" get functions too and a generic > one retrieving all of them. Okay about this layer, discarding my remark. You have a point about that: other stats associated to a single backend may be OK if not returned as a SRF, and they'll most likely return a different set of attributes. >> + descr => 'statistics: reset collected IO statistics for a single backend', >> + proname => 'pg_stat_reset_single_backend_io_counters', provolatile => 'v', >> >> And here, pg_stat_reset_backend_stats? > > Same as above, we could imagine that in the future the backend would get mutiple > stats and that one would want to reset only the I/O ones for example. Disagreed about this part. It is slightly simpler to do a full reset of the stats in a single entry. If another subset of stats is added to the backend-level entries, we could always introduce a new function that has more control over what subset of a single backend entry is reset. And I'm pretty sure that we are going to need the function that does the full reset anyway. >> I >> would just add a note in the docs with a query showing how to use it >> with pg_stat_activity. An example with LATERAL, doing the same work: >> select a.pid, s.* from pg_stat_activity as a, >> lateral pg_stat_get_backend_io(a.pid) as s >> where pid = pg_backend_pid(); > > I'm not sure it's worth it. I think that's clear that to get our own stats > then we need to provide our own backend pid. For example pg_stat_get_activity() > does not provide such an example using pg_stat_activity or using something like > pg_stat_get_activity(pg_backend_pid()). Okay. As far as I can see, the patch relies entirely on write_to_file to prevent any entries to be flushed out. It means that we leave in the dshash entries that may sit idle for as long as the server is up once a pgproc slot is used at least once. This scales depending on max_connections. It also means that we skip the sanity check about dropped entries at shutdown, which may be a good thing to do because we don't need to loop through them when writing the stats file. Hmm. Could it be better to be more aggressive with the handling of these stats, marking them as dropped when their backend exists and cleanup the dshash, without relying on the write flag to make sure that all the entries are discarded at shutdown? The point is that we do shutdown in a controlled manner, with all backends exiting before the checkpointer writes the stats file after the shutdown checkpoint is completed. The patch handles things so as entries are reset when a procnum is reused, leaving past stats around until that happens. We should perhaps aim for more consistency with the way beentry is refreshed and be more proactive with the backend entry drop or reset at backend shutdown (pgstat_beshutdown_hook?), so as what is in the dshash reflects exactly what's in shared memory for each PGPROC and beentry. Not sure that the "_per_" added in the various references of the patch are good to keep, like pgstat_tracks_per_backend_bktype. These could be removed, I guess, doing also a PGSTAT_KIND_PER_BACKEND => PGSTAT_KIND_BACKEND? -- Michael -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-13T09:20:13Z
Hi, On Fri, Dec 13, 2024 at 11:02:53AM +0900, Michael Paquier wrote: > On Thu, Dec 12, 2024 at 02:02:38PM +0000, Bertrand Drouvot wrote: > > Anyway, isn't it possible that this lookup loop finishes by finding > nothing depending on concurrent updates of other beentries? It sounds > to me that this warrants an early exit in the function. Right, done that way in the attached. > Perhaps, yes. pgstat_tracks_io_bktype() has always been discarded > walwriters since pgstat_io.c exists. Yeap. The comment on top of pgstat_tracks_io_bktype() says that it's not done "for now". I think that we could update the code as proposed until it's done. > >> + descr => 'statistics: reset collected IO statistics for a single backend', > >> + proname => 'pg_stat_reset_single_backend_io_counters', provolatile => 'v', > >> > >> And here, pg_stat_reset_backend_stats? > > > > Same as above, we could imagine that in the future the backend would get mutiple > > stats and that one would want to reset only the I/O ones for example. > > Disagreed about this part. It is slightly simpler to do a full reset > of the stats in a single entry. If another subset of stats is added > to the backend-level entries, we could always introduce a new function > that has more control over what subset of a single backend entry is > reset. And I'm pretty sure that we are going to need the function > that does the full reset anyway. Yeah, would have added it when a new stats subset would be added. It's fine by me to have it now though, so done that way. > As far as I can see, the patch relies entirely on write_to_file to > prevent any entries to be flushed out. Yes. > It means that we leave in the > dshash entries that may sit idle for as long as the server is up once > a pgproc slot is used at least once. This scales depending on > max_connections. It also means that we skip the sanity check about > dropped entries at shutdown, which may be a good thing to do because > we don't need to loop through them when writing the stats file. Agree. > Hmm. > Could it be better to be more aggressive with the handling of these > stats, marking them as dropped when their backend exists and cleanup > the dshash, without relying on the write flag to make sure that all > the entries are discarded at shutdown? Yeah we can do it to be consistent with other stats kind, done. > The point is that we do > shutdown in a controlled manner, with all backends exiting before the > checkpointer writes the stats file after the shutdown checkpoint is > completed. The patch handles things so as entries are reset when a > procnum is reused, leaving past stats around until that happens. We > should perhaps aim for more consistency with the way beentry is > refreshed and be more proactive with the backend entry drop or reset > at backend shutdown (pgstat_beshutdown_hook?), so as what is in the > dshash reflects exactly what's in shared memory for each PGPROC and > beentry. That can't be done in pgstat_beshutdown_hook because pgstat_shutdown_hook is called before and so resets the pgStatLocal.shared_hash during pgstat_detach_shmem(). So, did it in pgstat_shutdown_hook instead. > Not sure that the "_per_" added in the various references of the patch > are good to keep, like pgstat_tracks_per_backend_bktype. These could > be removed, I guess, doing also a PGSTAT_KIND_PER_BACKEND => > PGSTAT_KIND_BACKEND? Yeah makes sense, that's consistent with other kinds: done. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-16T08:07:52Z
On Fri, Dec 13, 2024 at 09:20:13AM +0000, Bertrand Drouvot wrote: > Yeah makes sense, that's consistent with other kinds: done. This looks to be taking shape. I don't have much more comments. Not feeling so sure about the value brought by the backend_type returned in pg_stat_get_backend_io(), but well.. + /* drop the backend stats entry */ + pgstat_drop_entry(PGSTAT_KIND_BACKEND, InvalidOid, MyProcNumber); Oh, I've missed something. Shouldn't pgstat_request_entry_refs_gc() be called when this returns false? The creation of the dshash entry is a bit too early, I think.. How about delaying it more so as we don't create entries that could be useless if we fail the last steps of authentication? One spot would be to delay the creation of the new entry at the end of pgstat_bestart(), where we know that we are done with authentication and that the backend is ready to report back to the client connected to it. It is true that some subsystems could produce stats as of the early transactions they generate, which is why pgstat_initialize() is done that early in BaseInit(), but that's not really relevant for this case? I'm still feeling a bit uneasy about the drop done in pgstat_shutdown_hook(); it would be nice to make sure that this happens in a path that would run just after we're done with the creation of the entry to limit windows where we have an entry but no way to drop it, or vice-versa, so as the shutdown assertions would never trigger. Perhaps there's an argument for an entirely separate callback that would run before pgstat is plugged off, like a new before_shmem_exit() callback registered after the entry is created? -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-16T15:42:04Z
Hi, On Mon, Dec 16, 2024 at 05:07:52PM +0900, Michael Paquier wrote: > On Fri, Dec 13, 2024 at 09:20:13AM +0000, Bertrand Drouvot wrote: > > Not feeling so sure about the value brought by the backend_type > returned in pg_stat_get_backend_io(), but well.. It's not necessary per say, but it ensures that pg_stat_get_backend_io() does not return rows full of "invalid" combinations. For example: With the filtering in place, on a "client backend" we would get: postgres=# select * from pg_stat_get_backend_io(pg_backend_pid()); backend_type | object | context | reads | read_time | writes | write_time | writebacks | writeback_time | extends | extend_time | op_bytes | hits | evictions | reuses | fsyncs | fsync_time | stats_reset ----------------+---------------+-----------+-------+-----------+--------+------------+------------+----------------+---------+-------------+----------+------+-----------+--------+--------+------------+------------- client backend | relation | bulkread | 0 | 0 | 0 | 0 | 0 | 0 | | | 8192 | 0 | 0 | 0 | | | client backend | relation | bulkwrite | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 0 | 0 | 0 | | | client backend | relation | normal | 86 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 1604 | 0 | | 0 | 0 | client backend | relation | vacuum | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 0 | 0 | 0 | | | client backend | temp relation | normal | 0 | 0 | 0 | 0 | | | 0 | 0 | 8192 | 0 | 0 | | | | (5 rows) and for example for the walsender: postgres=# select * from pg_stat_get_backend_io(3982910); backend_type | object | context | reads | read_time | writes | write_time | writebacks | writeback_time | extends | extend_time | op_bytes | hits | evictions | reuses | fsyncs | fsync_time | stats_reset --------------+---------------+-----------+-------+-----------+--------+------------+------------+----------------+---------+-------------+----------+------+-----------+--------+--------+------------+------------- walsender | relation | bulkread | 0 | 0 | 0 | 0 | 0 | 0 | | | 8192 | 0 | 0 | 0 | | | walsender | relation | bulkwrite | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 0 | 0 | 0 | | | walsender | relation | normal | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 54 | 0 | | 0 | 0 | walsender | relation | vacuum | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 0 | 0 | 0 | | | walsender | temp relation | normal | 0 | 0 | 0 | 0 | | | 0 | 0 | 8192 | 0 | 0 | | | | (5 rows) While, without the filtering we would get: postgres=# select * from pg_stat_get_backend_io(pg_backend_pid()); backend_type | object | context | reads | read_time | writes | write_time | writebacks | writeback_time | extends | extend_time | op_bytes | hits | evictions | reuses | fsyncs | fsync_time | stats_reset ----------------+---------------+-----------+-------+-----------+--------+------------+------------+----------------+---------+-------------+----------+------+-----------+--------+--------+------------+------------- client backend | relation | bulkread | 0 | 0 | 0 | 0 | 0 | 0 | | | 8192 | 0 | 0 | 0 | | | client backend | relation | bulkwrite | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 0 | 0 | 0 | | | client backend | relation | normal | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 50 | 0 | | 0 | 0 | client backend | relation | vacuum | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 0 | 0 | 0 | | | client backend | temp relation | bulkread | | | | | | | | | 8192 | | | | | | client backend | temp relation | bulkwrite | | | | | | | | | 8192 | | | | | | client backend | temp relation | normal | 0 | 0 | 0 | 0 | | | 0 | 0 | 8192 | 0 | 0 | | | | client backend | temp relation | vacuum | | | | | | | | | 8192 | | | | | | (8 rows) and for a walsender: postgres=# select * from pg_stat_get_backend_io(3981588); backend_type | object | context | reads | read_time | writes | write_time | writebacks | writeback_time | extends | extend_time | op_bytes | hits | evictions | reuses | fsyncs | fsync_time | stats_reset --------------+---------------+-----------+-------+-----------+--------+------------+------------+----------------+---------+-------------+----------+------+-----------+--------+--------+------------+------------- walsender | relation | bulkread | 0 | 0 | 0 | 0 | 0 | 0 | | | 8192 | 0 | 0 | 0 | | | walsender | relation | bulkwrite | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 0 | 0 | 0 | | | walsender | relation | normal | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 48 | 0 | | 0 | 0 | walsender | relation | vacuum | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 8192 | 0 | 0 | 0 | | | walsender | temp relation | bulkread | | | | | | | | | 8192 | | | | | | walsender | temp relation | bulkwrite | | | | | | | | | 8192 | | | | | | walsender | temp relation | normal | 0 | 0 | 0 | 0 | | | 0 | 0 | 8192 | 0 | 0 | | | | walsender | temp relation | vacuum | | | | | | | | | 8192 | | | | | | (8 rows) It would not be possible to remove those "extra 3 rows" with a join on the backend type on pg_stat_activity because only the C code knows about what the compatibility is (though pgstat_tracks_io_object). > + /* drop the backend stats entry */ > + pgstat_drop_entry(PGSTAT_KIND_BACKEND, InvalidOid, MyProcNumber); > > Oh, I've missed something. Shouldn't pgstat_request_entry_refs_gc() > be called when this returns false? I'm not sure that would be possible for a PGSTAT_KIND_BACKEND kind to return false here but I agree that's better to call pgstat_request_entry_refs_gc() if that's the case. Done in v9 attached. > The creation of the dshash entry is a bit too early, I think.. How > about delaying it more so as we don't create entries that could be > useless if we fail the last steps of authentication? One spot would > be to delay the creation of the new entry at the end of > pgstat_bestart(), where we know that we are done with authentication > and that the backend is ready to report back to the client connected > to it. It is true that some subsystems could produce stats as of the > early transactions they generate, which is why pgstat_initialize() is > done that early in BaseInit(), but that's not really relevant for this > case? I think that makes sense to move the stats entry creation in pgstat_bestart(), done that way in v9. > I'm still feeling a bit uneasy about the drop done in > pgstat_shutdown_hook(); it would be nice to make sure that this > happens in a path that would run just after we're done with the > creation of the entry to limit windows where we have an entry but no > way to drop it, or vice-versa, I don't believe that's possible as MyProcNumber can't be "reused" (and is guaranteed to remain valid) until ProcKill() is done (which happens after the pgstat_shutdown_hook()). > Perhaps there's an argument for an entirely separate > callback that would run before pgstat is plugged off, like a new > before_shmem_exit() callback registered after the entry is created? As the ProcKill() is run in shmem_exit() (and so after before_shmem_exit()), I think that the way we currently drop the backend stats entry is fine (unless I miss something about your concern). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-17T06:26:02Z
On Mon, Dec 16, 2024 at 03:42:04PM +0000, Bertrand Drouvot wrote: > It's not necessary per say, but it ensures that pg_stat_get_backend_io() does not > return rows full of "invalid" combinations. Okay. I am not planning to fight more over this point. > I'm not sure that would be possible for a PGSTAT_KIND_BACKEND kind to return > false here but I agree that's better to call pgstat_request_entry_refs_gc() > if that's the case. Done in v9 attached. It seems to me that it could be possible if a different backend keeps a reference to this entry. >> Perhaps there's an argument for an entirely separate >> callback that would run before pgstat is plugged off, like a new >> before_shmem_exit() callback registered after the entry is created? > > As the ProcKill() is run in shmem_exit() (and so after before_shmem_exit()), > I think that the way we currently drop the backend stats entry is fine (unless > I miss something about your concern). Looking closely at this one, I think that you're right as long as the shutdown callback is registered before the entry is created. So I'm OK because the drop is a no-op if the entry cannot be found, and we would not try a pgstat_request_entry_refs_gc(). Anyway, I have put my hands on v9. A couple of notes, while hacking through it. See v9-0002 for the parts I have modified, that applies on top of your v9-0001. You may have noticed fee2b3ea2ecdg, which led me to fix two comments as these paths are not related to only database objects. Added more documentation, tweaked quite a bit the comments, a bit less the docs (no need for the two linkends) and applied an indentation. pg_stat_get_backend_io() can be simpler, and does not need the loop with the extra LocalPgBackendStatus. It is possible to call once pgstat_get_beentry_by_proc_number() and retrieve the PID and the bktype for the two sanity checks we want to do on them. s/pgstat_fetch_proc_stat_io/pgstat_fetch_stat_backend/. s/pgstat_create_backend_stat/pgstat_create_backend/. I've been wondering for quite a bit about PgStat_BackendPendingIO and PgStat_PendingIO, and concluded to define both in pgstat.h, with the former being defined based on the latter to keep the dependency between both at the same place. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-17T08:13:59Z
Hi, On Tue, Dec 17, 2024 at 03:26:02PM +0900, Michael Paquier wrote: > On Mon, Dec 16, 2024 at 03:42:04PM +0000, Bertrand Drouvot wrote: > >> Perhaps there's an argument for an entirely separate > >> callback that would run before pgstat is plugged off, like a new > >> before_shmem_exit() callback registered after the entry is created? > > > > As the ProcKill() is run in shmem_exit() (and so after before_shmem_exit()), > > I think that the way we currently drop the backend stats entry is fine (unless > > I miss something about your concern). > > Looking closely at this one, I think that you're right as long as the > shutdown callback is registered before the entry is created. Yeah, which is the case. > Anyway, I have put my hands on v9. A couple of notes, while hacking > through it. See v9-0002 for the parts I have modified, that applies > on top of your v9-0001. Thanks! > You may have noticed fee2b3ea2ecdg, which led me to fix two comments > as these paths are not related to only database objects. Yeap ;-) > Added more documentation, tweaked quite a bit the comments, a bit less > the docs (no need for the two linkends) and applied an indentation. Looks good to me. > pg_stat_get_backend_io() can be simpler, and does not need the loop > with the extra LocalPgBackendStatus. It is possible to call once > pgstat_get_beentry_by_proc_number() and retrieve the PID and the > bktype for the two sanity checks we want to do on them. Looked at the changes you've done and agree that's simpler. > s/pgstat_fetch_proc_stat_io/pgstat_fetch_stat_backend/. Not sure about this one as being called in pg_stat_get_backend_io(). > s/pgstat_create_backend_stat/pgstat_create_backend/. LGTM. > I've been wondering for quite a bit about PgStat_BackendPendingIO and > PgStat_PendingIO, and concluded to define both in pgstat.h, with the > former being defined based on the latter to keep the dependency > between both at the same place. That's fine by me. Also: === 1 the changes in pgstat_flush_backend() make sense to me. === 2 - * Create the backend statistics entry for procnum. + * Create backend statistics entry for proc number. Yeah, "proc number" looks better as already used in multiple places. === 3 the changes in stats.sql look good to me. Having said that, v9-0002 looks good to me (except the pgstat_fetch_proc_stat_io renaming). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-17T09:13:44Z
On Tue, Dec 17, 2024 at 08:13:59AM +0000, Bertrand Drouvot wrote: > Having said that, v9-0002 looks good to me (except the pgstat_fetch_proc_stat_io > renaming). This routine returns a PgStat_Backend from a pgstats entry of type PGSTAT_KIND_BACKEND, so the name in v9-0001 would not be true once more types of stats data are attached to this structure. The name in v9-0002 is more consistent long-term. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-17T09:35:37Z
Hi, On Tue, Dec 17, 2024 at 06:13:44PM +0900, Michael Paquier wrote: > On Tue, Dec 17, 2024 at 08:13:59AM +0000, Bertrand Drouvot wrote: > > Having said that, v9-0002 looks good to me (except the pgstat_fetch_proc_stat_io > > renaming). > > This routine returns a PgStat_Backend from a pgstats entry of type > PGSTAT_KIND_BACKEND, so the name in v9-0001 would not be true once > more types of stats data are attached to this structure. Fair enough, let's go with the name change done in v9-0002. > The name in > v9-0002 is more consistent long-term. Agree, we may need to add parameters to it but we'll see when the time comes. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-18T04:57:53Z
On Tue, Dec 17, 2024 at 09:35:37AM +0000, Bertrand Drouvot wrote: > Agree, we may need to add parameters to it but we'll see when the time comes. Another thing that's been itching me: the loop in pg_stat_get_backend_io() that exists as well in pg_stat_get_io() looks worth refactoring in a single routine. The only difference between both is the reset timestamp, still both of them can pass a value for it depending on their stats kind entry. This shaves a bit more code in your own patch, even if the check on pgstat_tracks_io_bktype() and the Assert are not in the inner routine that fills the tuplestore with the I/O data. See pg_stat_fill_io_data() in v10-0002. If you have a better name for this routine, feel free.. What do you think about this refactoring? This should come in first, of course, so as the final patch introducing the backend stats is easier to parse. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-18T08:11:55Z
Hi, On Wed, Dec 18, 2024 at 01:57:53PM +0900, Michael Paquier wrote: > On Tue, Dec 17, 2024 at 09:35:37AM +0000, Bertrand Drouvot wrote: > > Agree, we may need to add parameters to it but we'll see when the time comes. > > Another thing that's been itching me: the loop in > pg_stat_get_backend_io() that exists as well in pg_stat_get_io() looks > worth refactoring in a single routine. The only difference between > both is the reset timestamp, still both of them can pass a value for > it depending on their stats kind entry. Yeah, I also had something like this in mind (see R2 in [1]). So, +1 for it. > This shaves a bit more code > in your own patch, even if the check on pgstat_tracks_io_bktype() and > the Assert are not in the inner routine that fills the tuplestore with > the I/O data. Yeah, that's fine by me. > See pg_stat_fill_io_data() in v10-0002. If you have a > better name for this routine, feel free.. I think I prefer pg_stat_io_build_tuples() and used that name in v11 attached. > What do you think about this refactoring? Makes fully sense to me (as per my first comment above). > This should come in first, > of course, so as the final patch introducing the backend stats is > easier to parse. Yeah, it's in 0001 attached, with a few changes: === 1 s/Save tuples with data from this PgStat_BktypeIO./save tuples with data from this PgStat_BktypeIO/ to be consistent with single line comments around. === 2 + if (stat_reset_timestamp != 0) + values[IO_COL_RESET_TIME] = TimestampTzGetDatum(stat_reset_timestamp); + else + nulls[IO_COL_RESET_TIME] = true; This is not necessary until the per backend I/O stat is introduced but I added it in 0001 to ease 0002 parsing. === 3 "In Assert builds, we can afford an extra loop through all of the" I think that this comment is now confusing since the extra loop would be done in pg_stat_io_build_tuples() and not where the comment is written. One option could have been to move the assert and the comment in pg_stat_io_build_tuples() but I think it's better to have the assert before the pgstat_tracks_io_bktype() call in pg_stat_get_io(), so modified the comment a bit instead. 0002 is the per-backend stats I/O with yours tweaks. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-18T08:16:12Z
On Wed, Dec 18, 2024 at 08:11:55AM +0000, Bertrand Drouvot wrote: > Yeah, I also had something like this in mind (see R2 in [1]). So, +1 for it. [1] being: https://www.postgresql.org/message-id/Zy4bmvgHqGjcK1pI%40ip-10-97-1-34.eu-west-3.compute.internal Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-19T04:21:54Z
On Wed, Dec 18, 2024 at 08:11:55AM +0000, Bertrand Drouvot wrote: > I think I prefer pg_stat_io_build_tuples() and used that name in v11 > attached. I'll rely to your naming sense than mine, then :D > I think that this comment is now confusing since the extra loop would be > done in pg_stat_io_build_tuples() and not where the comment is written. One > option could have been to move the assert and the comment in pg_stat_io_build_tuples() > but I think it's better to have the assert before the pgstat_tracks_io_bktype() > call in pg_stat_get_io(), so modified the comment a bit instead. > > 0002 is the per-backend stats I/O with yours tweaks. While doing more tests with backends exiting concurrently with their stats scanned, I have detected one path in pg_stat_get_backend_io() after calling pgstat_get_beentry_by_proc_number() where we should also check that it does not return NULL, or we would crash on a pointer dereference when reading the backend type. Fixed that, bumped the two version counters, and done. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-19T06:12:04Z
Hi, On Thu, Dec 19, 2024 at 01:21:54PM +0900, Michael Paquier wrote: > > While doing more tests with backends exiting concurrently with their > stats scanned, I have detected one path in pg_stat_get_backend_io() > after calling pgstat_get_beentry_by_proc_number() where we should also > check that it does not return NULL, or we would crash on a pointer > dereference when reading the backend type. > > Fixed that, Oh right, indeed all the others pgstat_get_beentry_by_proc_number() callers are checking for a NULL returned value. > bumped the two version counters, and done. Thanks! I think I'll start a dedicated thread to discuss the stats_fetch_consistency/'snapshot' point (will be easier to follow than resuming the discussion in this thread). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Alexander Law <exclusion@gmail.com> — 2024-12-20T06:00:00Z
Hello Michael, 19.12.2024 06:21, Michael Paquier wrote: > Fixed that, bumped the two version counters, and done. Could you, please, look at recent failures produced by grassquit (which has fsync = on in it's config), on an added test case? For instance, [1]: --- /home/bf/bf-build/grassquit/HEAD/pgsql/src/test/regress/expected/stats.out 2024-12-19 04:44:08.779311933 +0000 +++ /home/bf/bf-build/grassquit/HEAD/pgsql.build/testrun/recovery/027_stream_regress/data/results/stats.out 2024-12-19 16:37:41.351784840 +0000 @@ -1333,7 +1333,7 @@ AND :my_io_sum_shared_after_fsyncs= 0); ?column? ---------- - t + f (1 row) The complete query is: SELECT current_setting('fsync') = 'off' OR (:my_io_sum_shared_after_fsyncs = :my_io_sum_shared_before_fsyncs AND :my_io_sum_shared_after_fsyncs= 0); And the corresponding query in 027_stream_regress_primary.log is: 2024-12-19 16:37:39.907 UTC [4027467][client backend][15/1980:0] LOG: statement: SELECT current_setting('fsync') = 'off' OR (1 = 1 AND 1= 0); (I can reproduce this locally with an asan-enabled build too.) [1] https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=grassquit&dt=2024-12-19%2016%3A28%3A58 Best regards, Alexander -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-20T09:09:00Z
Hi, On Fri, Dec 20, 2024 at 08:00:00AM +0200, Alexander Lakhin wrote: > Hello Michael, > > 19.12.2024 06:21, Michael Paquier wrote: > > Fixed that, bumped the two version counters, and done. > > Could you, please, look at recent failures produced by grassquit (which > has fsync = on in it's config), on an added test case? For instance, [1]: > --- /home/bf/bf-build/grassquit/HEAD/pgsql/src/test/regress/expected/stats.out 2024-12-19 04:44:08.779311933 +0000 > +++ /home/bf/bf-build/grassquit/HEAD/pgsql.build/testrun/recovery/027_stream_regress/data/results/stats.out > 2024-12-19 16:37:41.351784840 +0000 > @@ -1333,7 +1333,7 @@ > AND :my_io_sum_shared_after_fsyncs= 0); > ?column? > ---------- > - t > + f > (1 row) > > The complete query is: > SELECT current_setting('fsync') = 'off' > OR (:my_io_sum_shared_after_fsyncs = :my_io_sum_shared_before_fsyncs > AND :my_io_sum_shared_after_fsyncs= 0); > > And the corresponding query in 027_stream_regress_primary.log is: > 2024-12-19 16:37:39.907 UTC [4027467][client backend][15/1980:0] LOG: statement: SELECT current_setting('fsync') = 'off' > OR (1 = 1 > AND 1= 0); > > (I can reproduce this locally with an asan-enabled build too.) > > [1] https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=grassquit&dt=2024-12-19%2016%3A28%3A58 Thanks for the report! I was not able able to reproduce (even with asan-enabled) but I think the test is wrong. Indeed the backend could fsync too during the test (see register_dirty_segment() and the case where the request queue is full). I think the test should look like the attached instead, thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-20T09:24:37Z
On Fri, Dec 20, 2024 at 09:09:00AM +0000, Bertrand Drouvot wrote: > Thanks for the report! I was not able able to reproduce (even with asan-enabled) > but I think the test is wrong. Indeed the backend could fsync too during the test > (see register_dirty_segment() and the case where the request queue is full). > > I think the test should look like the attached instead, thoughts? Hmm. I cannot reproduce that here either. FWIW, I use these settings by default in my local builds, similarly to the CI which did not complain: ASAN_OPTIONS="print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0" UBSAN_OPTIONS="print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2" CFLAGS+="-fsanitize=undefined " LDFLAGS+="-fsanitize=undefined " grassquit uses something a bit different, which don't allow me to see a problem with 027 even with fsync enabled: ASAN_OPTIONS="print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0" CFLAGS+="-fsanitize=address -fno-sanitize-recover=all " LDFLAGS+="-fsanitize=address -fno-sanitize-recover=all " Anyway, I was arriving at the same conclusion as you, because this is just telling us that there could be "some" sync activity. As rewritten, this would just check that the after-the-fact counter is never lower than the before-the-fact counter, which is still better than removing the query. I was thinking about doing the latter and remove the query, but I'm also OK with what you have here, keeping the query with a relaxed check. I'll go adjust that in a bit.. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2024-12-20T09:57:19Z
Hi, On Thu, Dec 19, 2024 at 06:12:04AM +0000, Bertrand Drouvot wrote: > On Thu, Dec 19, 2024 at 01:21:54PM +0900, Michael Paquier wrote: > > bumped the two version counters, and done. > > The existing structure could be expanded in the > > future to add more information about other statistics related to > > backends, depending on requirements or ideas. BTW, now that the per backend I/O statistics is done, I'll start working on per backend wal statistics. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2024-12-24T05:35:16Z
On Fri, Dec 20, 2024 at 09:57:19AM +0000, Bertrand Drouvot wrote: > BTW, now that the per backend I/O statistics is done, I'll start working on per > backend wal statistics. I think that this is a good idea. It does not actually overlap the proposal in [1] as the stats persistency is not the same. What this thread has taught me is that you could just plug in the stats of the new backend-level structure a PgStat_WalStats and retrieve them with a new function that returns a single tuple with the WAL stats attributes. That should be rather straight-forward to achieve. [1]: https://commitfest.postgresql.org/51/4950/ -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-03T10:48:41Z
Hi, On Tue, Dec 24, 2024 at 02:35:16PM +0900, Michael Paquier wrote: > On Fri, Dec 20, 2024 at 09:57:19AM +0000, Bertrand Drouvot wrote: > > BTW, now that the per backend I/O statistics is done, I'll start working on per > > backend wal statistics. > > I think that this is a good idea. Thanks for sharing your thoughts. > It does not actually overlap the > proposal in [1] as the stats persistency is not the same. What this > thread has taught me is that you could just plug in the stats of the > new backend-level structure a PgStat_WalStats and retrieve them with a > new function that returns a single tuple with the WAL stats > attributes. That should be rather straight-forward to achieve. I started to look at it and should be able to share a patch next week. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-07T08:54:59Z
Hi, On Fri, Jan 03, 2025 at 10:48:41AM +0000, Bertrand Drouvot wrote: > I started to look at it and should be able to share a patch next week. A dedicated thread and a patch have been created, see [1]. [1]: https://www.postgresql.org/message-id/flat/Z3zqc4o09dM/Ezyz%40ip-10-97-1-34.eu-west-3.compute.internal Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-07T23:54:40Z
On Tue, Jan 07, 2025 at 08:54:59AM +0000, Bertrand Drouvot wrote: > A dedicated thread and a patch have been created, see [1]. > > [1]: https://www.postgresql.org/message-id/flat/Z3zqc4o09dM/Ezyz%40ip-10-97-1-34.eu-west-3.compute.internal Hmm. I can see that you have some refactoring pieces in the lines of some stuff I wanted to structure for the sake of this thread, but I have discarded them to simplify the final result at the end and it did not change much. Will look at all that on this other thread, no need to start a separate thread just for the sake of the refactoring bits. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-10T13:56:01Z
Hi, On Thu, Dec 19, 2024 at 06:12:04AM +0000, Bertrand Drouvot wrote: > I think I'll start a dedicated thread to discuss the stats_fetch_consistency/'snapshot' > point (will be easier to follow than resuming the discussion in this thread). I gave more thoughts on it and did some research in the mailing list. I've read those comments, from [1]: " We had a lot of discussion around what consistency model we want, and Tom was adamant that there needs to be a mode that behaves like the current consistency model (which is what snapshot behaves like, with very minor differences) " and from [2]: " One thing we definitely need to add documentation for is the stats_fetch_consistency GUC. I think we should change its default to 'cache', because that still gives the ability to "self-join", without the cost of the current method. " So now, I think that it is not a good idea for the per backend stats to behave differently than the other stats kinds. I think we should get rid of the "snapshot" for all of them or for none of them. Reading the above comments, it looks like it has already been discussed and that the outcome is to keep it for all of them. Regards, [1]: https://www.postgresql.org/message-id/20220404210610.6dgbwzpbiveyl5y3%40alap3.anarazel.de [2]: https://www.postgresql.org/message-id/20220329072651.imjqtzxwk6xycojv%40alap3.anarazel.de -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-14T04:56:13Z
On Fri, Jan 10, 2025 at 01:56:01PM +0000, Bertrand Drouvot wrote: > So now, I think that it is not a good idea for the per backend stats to > behave differently than the other stats kinds. I think we should get rid of > the "snapshot" for all of them or for none of them. Reading the above comments, > it looks like it has already been discussed and that the outcome is to keep > it for all of them. Thanks a lot for diving into these details! I did not recall that there was a strict argument for the current behavior, even if I was pretty sure that introducing an exception for the backend stats was not quite right compared to the other stats kinds. The consistency line prevails here, then. -- Michael
-
Re: per backend I/O statistics
Nazir Bilal Yavuz <byavuz81@gmail.com> — 2025-01-15T08:03:54Z
Hi, On Thu, 19 Dec 2024 at 07:22, Michael Paquier <michael@paquier.xyz> wrote: > > Fixed that, bumped the two version counters, and done. I encountered a problem while trying to add WAL stats to pg_stat_io and I wanted to hear your thoughts. Right now, pgstat_prep_backend_pending() is called in both pgstat_count_io_op() and pgstat_count_io_op_time() to create a local PgStat_BackendPending entry. In that process, pgstat_prep_pending_entry() -> MemoryContextAllocZero() is called. The problem is that MemoryContextAllocZero() can not be called in the critical sections. For example, here is what happens in the walsender backend: ''' ... -> exec_replication_command() -> SendBaseBackup() -> ... -> XLogInsertRecord() -> START_CRIT_SECTION() /* Now we are in the critical section */ -> ... -> XLogWrite() -> pgstat_count_io_op_time() for the pg_pwrite() IO -> pgstat_prep_backend_pending() -> pgstat_prep_pending_entry() -> MemoryContextAllocZero() -> Failed at Assert("CritSectionCount == 0 || (context)->allowInCritSection") ''' With this commit it may not be possible to count IOs in the critical sections. I think the problem happens only if the local PgStat_BackendPending entry is being created for the first time for this backend in the critical section. -- Regards, Nazir Bilal Yavuz Microsoft -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-15T08:30:20Z
Hi, On Wed, Jan 15, 2025 at 11:03:54AM +0300, Nazir Bilal Yavuz wrote: > Hi, > > On Thu, 19 Dec 2024 at 07:22, Michael Paquier <michael@paquier.xyz> wrote: > > > > Fixed that, bumped the two version counters, and done. > > I encountered a problem while trying to add WAL stats to pg_stat_io > and I wanted to hear your thoughts. > > Right now, pgstat_prep_backend_pending() is called in both > pgstat_count_io_op() and pgstat_count_io_op_time() to create a local > PgStat_BackendPending entry. In that process, > pgstat_prep_pending_entry() -> MemoryContextAllocZero() is called. The > problem is that MemoryContextAllocZero() can not be called in the > critical sections. > > For example, here is what happens in the walsender backend: > > ''' > ... -> > exec_replication_command() -> > SendBaseBackup() -> > ... -> > XLogInsertRecord() -> > START_CRIT_SECTION() /* Now we are in the critical section */ -> > ... -> > XLogWrite() -> > pgstat_count_io_op_time() for the pg_pwrite() IO -> > pgstat_prep_backend_pending() -> > pgstat_prep_pending_entry() -> > MemoryContextAllocZero() -> > Failed at Assert("CritSectionCount == 0 || (context)->allowInCritSection") > ''' > > With this commit it may not be possible to count IOs in the critical > sections. I think the problem happens only if the local > PgStat_BackendPending entry is being created for the first time for > this backend in the critical section. Yeah, I encountered the exact same thing and mentioned it in [1] (see R1.). In [1] I did propose to use a new PendingBackendWalStats variable to "bypass" the pgstat_prep_backend_pending() usage. Michael mentioned in [2] that is not really consistent with the rest (what I agree with) and that "we should rethink a bit the way pending entries are retrieved". I did not think about it yet but that might be the way to go, thoughts? [1]: https://www.postgresql.org/message-id/Z3zqc4o09dM/Ezyz%40ip-10-97-1-34.eu-west-3.compute.internal [2]: https://www.postgresql.org/message-id/Z4dRlNuhSQ3hPPv2%40paquier.xyz Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-15T09:27:22Z
On Wed, Jan 15, 2025 at 08:30:20AM +0000, Bertrand Drouvot wrote: > On Wed, Jan 15, 2025 at 11:03:54AM +0300, Nazir Bilal Yavuz wrote: >> With this commit it may not be possible to count IOs in the critical >> sections. I think the problem happens only if the local >> PgStat_BackendPending entry is being created for the first time for >> this backend in the critical section. > > Yeah, I encountered the exact same thing and mentioned it in [1] (see R1.). > > In [1] I did propose to use a new PendingBackendWalStats variable to "bypass" the > pgstat_prep_backend_pending() usage. > > Michael mentioned in [2] that is not really consistent with the rest (what I > agree with) and that "we should rethink a bit the way pending entries are > retrieved". I did not think about it yet but that might be the way to > go, thoughts? > > [1]: https://www.postgresql.org/message-id/Z3zqc4o09dM/Ezyz%40ip-10-97-1-34.eu-west-3.compute.internal > [2]: https://www.postgresql.org/message-id/Z4dRlNuhSQ3hPPv2%40paquier.xyz My problem is that this is not only related to backend stats, but to all variable-numbered stats kinds that require this behavior. One other case where I've seen this as being an issue is injection point stats, for example, while enabling these stats for all callbacks and some of them are run in critical sections. A generic solution to the problem would be to allow pgStatPendingContext to have MemoryContextAllowInCriticalSection() set temporarily for the allocation of the pending data. Perhaps not for all stats kinds, just for these where we're OK with the potential memory footprint so we could have a flag in PgStat_KindInfo. Giving to all stats kinds the responsibility to allocate a pending entry beforehand outside a critical section is another option, but that means going through different tweaks for all stats kinds that require them. Andres, do you have any thoughts about that? Not sure what would be your view on this matter. MemoryContextAllowInCriticalSection() for stats kinds that allow the case would be OK for me I guess, we should not be talking about a lot of memory. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-15T10:55:44Z
Hi, On Wed, Jan 15, 2025 at 06:27:22PM +0900, Michael Paquier wrote: > On Wed, Jan 15, 2025 at 08:30:20AM +0000, Bertrand Drouvot wrote: > > On Wed, Jan 15, 2025 at 11:03:54AM +0300, Nazir Bilal Yavuz wrote: > >> With this commit it may not be possible to count IOs in the critical > >> sections. I think the problem happens only if the local > >> PgStat_BackendPending entry is being created for the first time for > >> this backend in the critical section. > > > > Yeah, I encountered the exact same thing and mentioned it in [1] (see R1.). > > > > In [1] I did propose to use a new PendingBackendWalStats variable to "bypass" the > > pgstat_prep_backend_pending() usage. > > > > Michael mentioned in [2] that is not really consistent with the rest (what I > > agree with) and that "we should rethink a bit the way pending entries are > > retrieved". I did not think about it yet but that might be the way to > > go, thoughts? > > > > [1]: https://www.postgresql.org/message-id/Z3zqc4o09dM/Ezyz%40ip-10-97-1-34.eu-west-3.compute.internal > > [2]: https://www.postgresql.org/message-id/Z4dRlNuhSQ3hPPv2%40paquier.xyz > > My problem is that this is not only related to backend stats, but to > all variable-numbered stats kinds that require this behavior. Yeah, agree that it's better to have a "generic" solution. > A generic solution to the problem would be to allow > pgStatPendingContext to have MemoryContextAllowInCriticalSection() set > temporarily for the allocation of the pending data. > Perhaps not for all stats kinds, just for these where we're OK with > the potential memory footprint so we could have a flag in > PgStat_KindInfo. Giving to all stats kinds the responsibility to > allocate a pending entry beforehand outside a critical section is > another option, but that means going through different tweaks for all > stats kinds that require them. > > Andres, do you have any thoughts about that? Not sure what would be > your view on this matter. MemoryContextAllowInCriticalSection() for > stats kinds that allow the case would be OK for me I guess, Same here, that looks ok to me too. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Nazir Bilal Yavuz <byavuz81@gmail.com> — 2025-01-15T14:20:57Z
Hi, On Wed, 15 Jan 2025 at 12:27, Michael Paquier <michael@paquier.xyz> wrote: > > On Wed, Jan 15, 2025 at 08:30:20AM +0000, Bertrand Drouvot wrote: > > On Wed, Jan 15, 2025 at 11:03:54AM +0300, Nazir Bilal Yavuz wrote: > >> With this commit it may not be possible to count IOs in the critical > >> sections. I think the problem happens only if the local > >> PgStat_BackendPending entry is being created for the first time for > >> this backend in the critical section. > > > > Yeah, I encountered the exact same thing and mentioned it in [1] (see R1.). > > > > In [1] I did propose to use a new PendingBackendWalStats variable to "bypass" the > > pgstat_prep_backend_pending() usage. > > > > Michael mentioned in [2] that is not really consistent with the rest (what I > > agree with) and that "we should rethink a bit the way pending entries are > > retrieved". I did not think about it yet but that might be the way to > > go, thoughts? > > > > [1]: https://www.postgresql.org/message-id/Z3zqc4o09dM/Ezyz%40ip-10-97-1-34.eu-west-3.compute.internal > > [2]: https://www.postgresql.org/message-id/Z4dRlNuhSQ3hPPv2%40paquier.xyz Thanks! I must have missed these emails. > > My problem is that this is not only related to backend stats, but to > all variable-numbered stats kinds that require this behavior. One > other case where I've seen this as being an issue is injection point > stats, for example, while enabling these stats for all callbacks and > some of them are run in critical sections. > > A generic solution to the problem would be to allow > pgStatPendingContext to have MemoryContextAllowInCriticalSection() set > temporarily for the allocation of the pending data. > Perhaps not for all stats kinds, just for these where we're OK with > the potential memory footprint so we could have a flag in > PgStat_KindInfo. Giving to all stats kinds the responsibility to > allocate a pending entry beforehand outside a critical section is > another option, but that means going through different tweaks for all > stats kinds that require them. I think allowing only pgStatPendingContext to have MemoryContextAllowInCriticalSection() is not enough. We need to allow at least pgStatSharedRefContext as well to have MemoryContextAllowInCriticalSection() as it can be allocated too. ''' pgstat_prep_pending_entry() -> pgstat_get_entry_ref() -> pgstat_get_entry_ref_cached() -> MemoryContextAlloc(pgStatSharedRefContext, sizeof(PgStat_EntryRef)) ''' Also, I encountered another problem. I did not write it in the first email because I thought I fixed it but it seems I did not. While doing the initdb, we are restoring stats with the pgstat_restore_stats() and we do not expect any pending stats. The problem goes like that: ''' pgstat_restore_stats() -> pgstat_read_statsfile() -> pgstat_reset_after_failure() -> pgstat_drop_all_entries() -> pgstat_drop_entry_internal() -> We have an assertion there which checks if there is a pending stat entry: /* should already have released local reference */ if (pgStatEntryRefHash) Assert(!pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, shent->key)); ''' And we have this at the same time: ''' BootstrapModeMain() -> InitPostgres() -> StartupXLOG() -> ReadCheckpointRecord() -> InitWalRecovery() -> ... -> XLogReadAhead() -> XLogDecodeNextRecord() -> ReadPageInternal() -> state->routine.page_read = XLogPageRead() then WAL read happens ''' So, this assert fails because we have pending stats for the PGSTAT_KIND_BACKEND. My fix was simply not restoring stats when the bootstrap is happening; but it did not work. Because, we reset all fixed-numbered stats 'pgstat_reset_after_failure() -> kind_info->reset_all_cb()' there, so if we skip it; we have some NULL stats, for example reset timestamps. Some of the tests do not expect them to be NULL at the start like below: SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset SELECT pg_stat_reset_shared('archiver'); SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver; This test fails because archiver_reset_ts is NULL when the server is started. I was a bit surprised that Bertrand did not encounter the same problem while working on the 'per backend WAL statistics' patch. Then I found the reason, it is because this problem happens only for WAL read and WAL init IOs which are starting to be tracked in my patch. By saying that, I could not decide which thread to write about this problem, migrating WAL stats thread or this thread. Since this thread is active and other stats may cause the same problem, I decided to write here. Please warn me if you think I need to write this to the migrating WAL stats thread. [1] diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index bf3dbda901d..0538859cc7f 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5681,7 +5681,7 @@ StartupXLOG(void) */ if (didCrash) pgstat_discard_stats(); - else + else if (!IsBootstrapProcessingMode()) pgstat_restore_stats(checkPoint.redo); -- Regards, Nazir Bilal Yavuz Microsoft -
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-15T16:00:12Z
Hi, On Wed, Jan 15, 2025 at 05:20:57PM +0300, Nazir Bilal Yavuz wrote: > While doing the initdb, we are restoring stats with the > pgstat_restore_stats() and we do not expect any pending stats. The > problem goes like that: > > I was a bit surprised that Bertrand did not encounter the same problem > while working on the 'per backend WAL statistics' patch. Then I found > the reason, it is because this problem happens only for WAL read and > WAL init IOs which are starting to be tracked in my patch. By saying > that, I could not decide which thread to write about this problem, > migrating WAL stats thread or this thread. Since this thread is active > and other stats may cause the same problem, I decided to write here. > Please warn me if you think I need to write this to the migrating WAL > stats thread. Thanks for the report! As it looks like that you hit the issue for "WAL read and WAL init IOs which are starting to be tracked in my patch", then I think it would make more sense to mention the issue in the "migrating WAL stats thread" so that one could try to reproduce it (with a patch producing the issue at hands). So it seems to me that the "migrating WAL stats thread" is a better place to discuss about it. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-16T00:55:10Z
On Wed, Jan 15, 2025 at 05:20:57PM +0300, Nazir Bilal Yavuz wrote: > I think allowing only pgStatPendingContext to have > MemoryContextAllowInCriticalSection() is not enough. We need to allow > at least pgStatSharedRefContext as well to have > MemoryContextAllowInCriticalSection() as it can be allocated too. > > ''' > pgstat_prep_pending_entry() -> > pgstat_get_entry_ref() -> > pgstat_get_entry_ref_cached() -> > MemoryContextAlloc(pgStatSharedRefContext, sizeof(PgStat_EntryRef)) > ''' Yep, I was pretty sure that we have a bit more going on. Last time I began digging into the issue I was loading injection_points in shared_preload_libraries with stats enabled to see how much I could break, and this was one pattern once I've forced the pending part. I didn't get through the whole exercise. > While doing the initdb, we are restoring stats with the > pgstat_restore_stats() and we do not expect any pending stats. The > problem goes like that: > > ''' > pgstat_restore_stats() -> > pgstat_read_statsfile() -> > pgstat_reset_after_failure() -> > pgstat_drop_all_entries() -> > pgstat_drop_entry_internal() -> > We have an assertion there which checks if there is a pending stat entry: > > /* should already have released local reference */ > if (pgStatEntryRefHash) > Assert(!pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, shent->key)); > ''' You mean that this is not something that happens on HEAD, but as an effect of trying to add WAL stats to pg_stat_io, right? > I was a bit surprised that Bertrand did not encounter the same problem > while working on the 'per backend WAL statistics' patch. Then I found > the reason, it is because this problem happens only for WAL read and > WAL init IOs which are starting to be tracked in my patch. By saying > that, I could not decide which thread to write about this problem, > migrating WAL stats thread or this thread. Since this thread is active > and other stats may cause the same problem, I decided to write here. > Please warn me if you think I need to write this to the migrating WAL > stats thread. I'd rather treat that on a separate thread (please add me in CC if I'm not there yet!). I am OK to discuss any issues related to backend statistics here if HEAD is impacted based on how the feature is limited currently now, though. Another, simpler, idea would be to force more calls pgstat_prep_backend_pending() where this is problematic, like before entering a critical section when generating a WAL record. I am not sure that it would take care of everything, as you mention; that would leave some holes depending on the kind of interactions with the pgstats dshash we do in these paths. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-16T06:48:58Z
Hi, On Thu, Jan 16, 2025 at 09:55:10AM +0900, Michael Paquier wrote: > On Wed, Jan 15, 2025 at 05:20:57PM +0300, Nazir Bilal Yavuz wrote: > > I think allowing only pgStatPendingContext to have > > MemoryContextAllowInCriticalSection() is not enough. We need to allow > > at least pgStatSharedRefContext as well to have > > MemoryContextAllowInCriticalSection() as it can be allocated too. > > > > ''' > > pgstat_prep_pending_entry() -> > > pgstat_get_entry_ref() -> > > pgstat_get_entry_ref_cached() -> > > MemoryContextAlloc(pgStatSharedRefContext, sizeof(PgStat_EntryRef)) > > ''' > > Yep, I was pretty sure that we have a bit more going on. Last time I > began digging into the issue I was loading injection_points in > shared_preload_libraries with stats enabled to see how much I could > break, and this was one pattern once I've forced the pending part. I > didn't get through the whole exercise. I'll look at it and come back with a proposal as part of [1]. [1]: https://www.postgresql.org/message-id/Z4dRlNuhSQ3hPPv2@paquier.xyz Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-16T16:05:35Z
Hi, On Thu, Jan 16, 2025 at 06:48:58AM +0000, Bertrand Drouvot wrote: > Hi, > > On Thu, Jan 16, 2025 at 09:55:10AM +0900, Michael Paquier wrote: > > On Wed, Jan 15, 2025 at 05:20:57PM +0300, Nazir Bilal Yavuz wrote: > > > I think allowing only pgStatPendingContext to have > > > MemoryContextAllowInCriticalSection() is not enough. We need to allow > > > at least pgStatSharedRefContext as well to have > > > MemoryContextAllowInCriticalSection() as it can be allocated too. > > > > > > ''' > > > pgstat_prep_pending_entry() -> > > > pgstat_get_entry_ref() -> > > > pgstat_get_entry_ref_cached() -> > > > MemoryContextAlloc(pgStatSharedRefContext, sizeof(PgStat_EntryRef)) > > > ''' > > > > Yep, I was pretty sure that we have a bit more going on. Last time I > > began digging into the issue I was loading injection_points in > > shared_preload_libraries with stats enabled to see how much I could > > break, and this was one pattern once I've forced the pending part. I > > didn't get through the whole exercise. > > I'll look at it and come back with a proposal as part of [1]. I looked at it and shared the outcome in [1]. It looks like it's more complicated as we could also hit a failed assertion in MemoryContextCreate(), like: TRAP: failed Assert("CritSectionCount == 0"), File: "mcxt.c", Line: 1107, PID: 3295726 pg18/bin/postgres(ExceptionalCondition+0xbb)[0x59668bee1f6d] pg18/bin/postgres(MemoryContextCreate+0x46)[0x59668bf2a8fe] pg18/bin/postgres(AllocSetContextCreateInternal+0x1df)[0x59668bf1bb11] pg18/bin/postgres(pgstat_prep_pending_entry+0x86)[0x59668bcff8cc] pg18/bin/postgres(pgstat_prep_backend_pending+0x2b)[0x59668bd024a9] I propose that as of now we discuss the issue in [1] instead of here. [1]: https://www.postgresql.org/message-id/Z4ks4%2BwnAz8eEyX9%40ip-10-97-1-34.eu-west-3.compute.internal Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Andres Freund <andres@anarazel.de> — 2025-01-16T16:28:43Z
Hi, On 2025-01-15 18:27:22 +0900, Michael Paquier wrote: > On Wed, Jan 15, 2025 at 08:30:20AM +0000, Bertrand Drouvot wrote: > > On Wed, Jan 15, 2025 at 11:03:54AM +0300, Nazir Bilal Yavuz wrote: > >> With this commit it may not be possible to count IOs in the critical > >> sections. I think the problem happens only if the local > >> PgStat_BackendPending entry is being created for the first time for > >> this backend in the critical section. > > > > Yeah, I encountered the exact same thing and mentioned it in [1] (see R1.). > > > > In [1] I did propose to use a new PendingBackendWalStats variable to "bypass" the > > pgstat_prep_backend_pending() usage. > > > > Michael mentioned in [2] that is not really consistent with the rest (what I > > agree with) and that "we should rethink a bit the way pending entries are > > retrieved". I did not think about it yet but that might be the way to > > go, thoughts? > > > > [1]: https://www.postgresql.org/message-id/Z3zqc4o09dM/Ezyz%40ip-10-97-1-34.eu-west-3.compute.internal > > [2]: https://www.postgresql.org/message-id/Z4dRlNuhSQ3hPPv2%40paquier.xyz > > My problem is that this is not only related to backend stats, but to > all variable-numbered stats kinds that require this behavior. The issue here imo is that recently IO stats were turned into a variable numbered stat, where it previously wasn't. It seems like a bad idea that now we regularly do a somewhat sizable memory allocation for backend stats. For table stats allocating the pending memory is somewhat a necessity - there could be a lot of different tables after all. And later transactions won't necessarily access the same set of tables, so we can't just keep the memory for pending around - but that's not true for IO. > One other case where I've seen this as being an issue is injection point > stats, for example, while enabling these stats for all callbacks and some of > them are run in critical sections. That seems somewhat fundamental - you could have arbitrary numbers of injection points and thus need arbitrary amounts of memory. You can't just do that in a critical section. And it's not just about a potential memory allocation for pending stats, the DSM allocation can't be done in a critical section either. > A generic solution to the problem would be to allow > pgStatPendingContext to have MemoryContextAllowInCriticalSection() set > temporarily for the allocation of the pending data. > Perhaps not for all stats kinds, just for these where we're OK with > the potential memory footprint so we could have a flag in > PgStat_KindInfo. That seems like an *incredibly* bad idea. That restriction exists for a reason. > Andres, do you have any thoughts about that? Not sure what would be > your view on this matter. MemoryContextAllowInCriticalSection() for > stats kinds that allow the case would be OK for me I guess, we should > not be talking about a lot of memory. My view is that for IO stats no memory allocation should be required - that used to be the case and should be the case again. And for something like injection points (not really convinced that it's a good thing to have stats for, but ...), allocation the shared memory stats object outside of the critical section and not having any pending stats seems to be the right approach. Greetings, Andres Freund
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-17T00:08:02Z
On Thu, Jan 16, 2025 at 11:28:43AM -0500, Andres Freund wrote: > On 2025-01-15 18:27:22 +0900, Michael Paquier wrote: >> My problem is that this is not only related to backend stats, but to >> all variable-numbered stats kinds that require this behavior. > > The issue here imo is that recently IO stats were turned into a variable > numbered stat, where it previously wasn't. It seems like a bad idea that now > we regularly do a somewhat sizable memory allocation for backend stats. For > table stats allocating the pending memory is somewhat a necessity - there > could be a lot of different tables after all. And later transactions won't > necessarily access the same set of tables, so we can't just keep the memory > for pending around - but that's not true for IO. Yep, for the reason that backend stats require that with one entry in the pgstats dshash for each backend as these are sized depending on max_connections & co using a proc number for the hash key. >> Andres, do you have any thoughts about that? Not sure what would be >> your view on this matter. MemoryContextAllowInCriticalSection() for >> stats kinds that allow the case would be OK for me I guess, we should >> not be talking about a lot of memory. > > My view is that for IO stats no memory allocation should be required - that > used to be the case and should be the case again. And for something like > injection points (not really convinced that it's a good thing to have stats > for, but ...), allocation the shared memory stats object outside of the > critical section and not having any pending stats seems to be the right > approach. Not sure to completely agree on that as this pushes the responsibility of how to deal with the critical section handling to each stats kind, but I won't fight over it for this case, either. It would not be the first time we have specific logic to do allocations beforehand when dealing with critical sections (38c579b08988 is the most recent example coming in mind, there are many others). Anyway, let's just switch pgstat_backend.c so as we use a static PgStat_BackendPending (pending name) to store the pending IO stats that could be reused for also the WAL bits. It does not seem that complicated as far as I can see, removing pgstat_prep_backend_pending and changing pgstat_flush_backend_entry_io to use the static pending data. The patch set posted here is doing that within its pgstat_flush_backend_entry_wal(): https://www.postgresql.org/message-id/Z4DrFhdlO6Xf13Xd@ip-10-97-1-34.eu-west-3.compute.internal I could tweak that around the beginning of next week with a proposal of patch. Bertrand, perhaps you'd prefer hack on this one? -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-17T06:06:35Z
Hi, On Fri, Jan 17, 2025 at 09:08:02AM +0900, Michael Paquier wrote: > Anyway, let's just switch pgstat_backend.c so as we use a static > PgStat_BackendPending (pending name) to store the pending IO stats > that could be reused for also the WAL bits. It does not seem that > complicated as far as I can see, removing pgstat_prep_backend_pending > and changing pgstat_flush_backend_entry_io to use the static pending > data. The patch set posted here is doing that within its > pgstat_flush_backend_entry_wal(): > https://www.postgresql.org/message-id/Z4DrFhdlO6Xf13Xd@ip-10-97-1-34.eu-west-3.compute.internal > > I could tweak that around the beginning of next week with a proposal > of patch. Bertrand, perhaps you'd prefer hack on this one? Yeah, I had in mind to work on it (in the exact same line as you are describing above). I'll work on it. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-17T06:12:36Z
On Fri, Jan 17, 2025 at 06:06:35AM +0000, Bertrand Drouvot wrote: > On Fri, Jan 17, 2025 at 09:08:02AM +0900, Michael Paquier wrote: >> I could tweak that around the beginning of next week with a proposal >> of patch. Bertrand, perhaps you'd prefer hack on this one? > > Yeah, I had in mind to work on it (in the exact same line as you are describing > above). I'll work on it. Thanks. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-17T10:23:48Z
Hi, On Fri, Jan 17, 2025 at 03:12:36PM +0900, Michael Paquier wrote: > On Fri, Jan 17, 2025 at 06:06:35AM +0000, Bertrand Drouvot wrote: > > On Fri, Jan 17, 2025 at 09:08:02AM +0900, Michael Paquier wrote: > >> I could tweak that around the beginning of next week with a proposal > >> of patch. Bertrand, perhaps you'd prefer hack on this one? > > > > Yeah, I had in mind to work on it (in the exact same line as you are describing > > above). I'll work on it. Please find attached a patch implementing the ideas above, meaning: - It creates a new PendingBackendStats variable - It uses this variable to increment and flush per backend pending IO statistics That way we get rid of the memory allocation for pending IO statistics. One remark: a special case has been added in pgstat_flush_pending_entries(). The reason is that while the per backend stats are "variable-numbered" stats, it could be that their pending stats are not part of pgStatPending. This is currently the case (with this patch) as the per backend pending IO stats are not tracked with pgstat_prep_backend_pending() and friends anymore. Thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-18T08:53:31Z
On Fri, Jan 17, 2025 at 10:23:48AM +0000, Bertrand Drouvot wrote: > Please find attached a patch implementing the ideas above, meaning: > > - It creates a new PendingBackendStats variable > - It uses this variable to increment and flush per backend pending IO statistics > > That way we get rid of the memory allocation for pending IO statistics. > > One remark: a special case has been added in pgstat_flush_pending_entries(). The > reason is that while the per backend stats are "variable-numbered" stats, it could > be that their pending stats are not part of pgStatPending. This is currently the > case (with this patch) as the per backend pending IO stats are not tracked with > pgstat_prep_backend_pending() and friends anymore. + /* + * There is a special case for some pending stats that are tracked in + * PendingBackendStats. It's possible that those have not been flushed + * above, hence the extra check here. + */ + if (!pg_memory_is_all_zeros(&PendingBackendStats, + sizeof(struct PgStat_BackendPending))) + { + PgStat_EntryRef *entry_ref; + + entry_ref = pgstat_get_entry_ref(PGSTAT_KIND_BACKEND, InvalidOid, + MyProcNumber, false, NULL); Hmm. Such special complexities in pgstat.c are annoying. There is a stupid thing I am wondering here. For the WAL stats, why couldn't we place some calls of pgstat_prep_backend_pending() in strategic places like XLogBeginInsert() to force all the allocation steps of the pending entry to happen before we would enter the critical sections when doing a WAL insertion? As far as I can see, there is a special case with 2PC where XLogBeginInsert() could be called in a critical section, but that seems to be the only one at quick glance. -- Michael -
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-20T06:34:41Z
On Sat, Jan 18, 2025 at 05:53:31PM +0900, Michael Paquier wrote: > Hmm. Such special complexities in pgstat.c are annoying. There is > a stupid thing I am wondering here. For the WAL stats, why couldn't > we place some calls of pgstat_prep_backend_pending() in strategic > places like XLogBeginInsert() to force all the allocation steps of the > pending entry to happen before we would enter the critical sections > when doing a WAL insertion? As far as I can see, there is a special > case with 2PC where XLogBeginInsert() could be called in a critical > section, but that seems to be the only one at quick glance. I've looked first at this idea over the week-end with a quick hack, and it did not finish well. And then it struck me that with a bit of redesign of the callbacks, so as the existing flush_fixed_cb and have_fixed_pending_cb are usable with variable-numbered stats, we should be able to avoid the exception your first version of the patch has introduced. Attached is a patch to achieve what I have in mind, which is more generic than your previous patch. I've built my stuff as 0002 on top of your 0001. One key choice I have made is to hide PendingBackendStats within pgstat_backend.c so as it is possible to enforce some sanity checks there. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-20T11:10:40Z
Hi, On Mon, Jan 20, 2025 at 03:34:41PM +0900, Michael Paquier wrote: > On Sat, Jan 18, 2025 at 05:53:31PM +0900, Michael Paquier wrote: > > Hmm. Such special complexities in pgstat.c are annoying. There is > > a stupid thing I am wondering here. For the WAL stats, why couldn't > > we place some calls of pgstat_prep_backend_pending() in strategic > > places like XLogBeginInsert() to force all the allocation steps of the > > pending entry to happen before we would enter the critical sections > > when doing a WAL insertion? As far as I can see, there is a special > > case with 2PC where XLogBeginInsert() could be called in a critical > > section, but that seems to be the only one at quick glance. > > I've looked first at this idea over the week-end with a quick hack, > and it did not finish well. Yeah, that would probably also mean moving the current WAL pending increments to the same "new" place (to be consistent) which does not seem great. > And then it struck me that with a bit of redesign of the callbacks, so Thanks! > as the existing flush_fixed_cb and have_fixed_pending_cb are usable > with variable-numbered stats, we should be able to avoid the exception > your first version of the patch has introduced. Attached is a patch > to achieve what I have in mind, which is more generic than your > previous patch. I've built my stuff as 0002 on top of your 0001. > Indeed. Another idea that I had would have been to create another callback, but I prefer your idea. === 1 I think that flush_pending_cb, flush_cb and have_pending_cb are now somehow confusing (one could think that have_pending_cb is only linked to flush_pending_cb). I think that it would be better to make the distinction based on "local/static" vs "dynamic memory" pending stats instead: I did so in v3 attached, using: .flush_dynamic_cb(): flushes pending entries tracked in dynamic memory .flush_static_cb(): flushes pending stats from static/global variable Also I reworded the comments a bit. === 2 - /* - * Clear out the statistics buffer, so it can be re-used. - */ - MemSet(&PendingBackendStats.pending_io, 0, sizeof(PgStat_PendingIO)); The inital intent was to clear *only" the pending IO stats, so that each flush (IO, WAL once implemented,...) could clear the pending stats it is responsible for. === 3 + /* + * Clear out the statistics buffer, so it can be re-used. + */ + MemSet(&PendingBackendStats, 0, sizeof(PgStat_BackendPending)); Not sure about this one, see above. I mean it is currently Ok but once we'll introduce the WAL part then it will not be correct depending of the flag value being passed. So, I did put back the previous logic in place (setting to zero only the stats the flush callback is responsible for) in v3 attached. === 4 + * Backend statistics counts waiting to be flushed out. We assume this variable + * inits to zeroes. These counters may be reported within critical sections so + * we use static memory in order to avoid memory allocation. + */ +static PgStat_BackendPending PendingBackendStats = {0}; I now think we should memset to zero to avoid any padding issues (as more structs will be added to PgStat_BackendPending). Oh and it's already done in pgstat_create_backend(), so removing the {0} assignement in the attached. === 5 + have_backendstats = false; I don't think setting have_backendstats to false in pgstat_flush_backend() is correct. I mean, it is correct currently but once we'll add the WAL part it won't necessary be correct if the flags != PGSTAT_BACKEND_FLUSH_ALL. So, using a pg_memory_is_all_zeros check on PendingBackendStats instead in the attached. > One key choice I have made is to hide PendingBackendStats within > pgstat_backend.c so as it is possible to enforce some sanity checks > there. Yeah, better, thanks! === 6 In passing, I realized that: " * Copyright (c) 2001-2025, PostgreSQL Global Development Group " in pgstat_backend.c is incorrect (fixing it in 0002). PFA: 0001: which is full rebase 0002: the Copyright fix .txt: the changes I've made on top of your 0002 (to not confuse the cfbot and to ease your review). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com -
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-20T12:11:16Z
On Mon, Jan 20, 2025 at 11:10:40AM +0000, Bertrand Drouvot wrote: > I think that it would be better to make the distinction based on "local/static" > vs "dynamic memory" pending stats instead: I did so in v3 attached, using: > > .flush_dynamic_cb(): flushes pending entries tracked in dynamic memory > .flush_static_cb(): flushes pending stats from static/global variable "static" and "dynamic" feel a bit off when used together. For "static", the stats are from a static state but they can be pushed to the dshash, as well, which is in dynamic shared memory. Hmm. Thinking more about that, I think that we should leave the existing "flush_pending_cb" alone. For the two others, how about "have_static_pending_cb" and "flush_static_cb" rather than "fixed"? It seems important to me to show the relationship between these two. > Not sure about this one, see above. I mean it is currently Ok but once we'll > introduce the WAL part then it will not be correct depending of the flag value > being passed. > > So, I did put back the previous logic in place (setting to zero only the stats > the flush callback is responsible for) in v3 attached. Hmm. I think that I'm OK with what you are doing here with the next parts in mind, based on this argument. > I don't think setting have_backendstats to false in pgstat_flush_backend() > is correct. I mean, it is correct currently but once we'll add the WAL part it > won't necessary be correct if the flags != PGSTAT_BACKEND_FLUSH_ALL. So, using a > pg_memory_is_all_zeros check on PendingBackendStats instead in the attached. Indeed. I got this part slightly wrong here. What you are doing with an all-zero check looks simpler in the long run. -- Michael
-
Re: per backend I/O statistics
Bertrand Drouvot <bertranddrouvot.pg@gmail.com> — 2025-01-20T13:26:55Z
Hi, On Mon, Jan 20, 2025 at 09:11:16PM +0900, Michael Paquier wrote: > On Mon, Jan 20, 2025 at 11:10:40AM +0000, Bertrand Drouvot wrote: > > I think that it would be better to make the distinction based on "local/static" > > vs "dynamic memory" pending stats instead: I did so in v3 attached, using: > > > > .flush_dynamic_cb(): flushes pending entries tracked in dynamic memory > > .flush_static_cb(): flushes pending stats from static/global variable > > "static" and "dynamic" feel a bit off when used together. For > "static", the stats are from a static state but they can be pushed to > the dshash, as well, which is in dynamic shared memory. Right, that's another way to find it confusing ;-). But if we keep focus on where the pending stats are stored, it is not. > Hmm. Thinking more about that, I think that we should leave the > existing "flush_pending_cb" alone. For the two others, how about > "have_static_pending_cb" and "flush_static_cb" rather than "fixed"? > It seems important to me to show the relationship between these two. Yeah, that works for me: done in v4 attached. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
-
Re: per backend I/O statistics
Michael Paquier <michael@paquier.xyz> — 2025-01-21T02:56:12Z
On Mon, Jan 20, 2025 at 01:26:55PM +0000, Bertrand Drouvot wrote: > Right, that's another way to find it confusing ;-). But if we keep focus > on where the pending stats are stored, it is not. The name of the callbacks can be tuned infinitely. I have split the renaming into its own patch, then the result looked fine after a second look so I have applied both things separately to unlock all the WAL patches. -- Michael