mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Add pg_memory_is_all_zeros() in memutils.h
This new function tests if a memory region starting at a given location for a defined length is made only of zeroes. This unifies in a single path the all-zero checks that were happening in a couple of places of the backend code: - For pgstats entries of relation, checkpointer and bgwriter, where some "all_zeroes" variables were previously used with memcpy(). - For all-zero buffer pages in PageIsVerifiedExtended(). This new function uses the same forward scan as the check for all-zero buffer pages, applying it to the three pgstats paths mentioned above. Author: Bertrand Drouvot Reviewed-by: Peter Eisentraut, Heikki Linnakangas, Peter Smith Discussion: https://postgr.es/m/ZupUDDyf1hHI4ibn@ip-10-97-1-34.eu-west-3.compute.internal
This commit is contained in:
@ -89,10 +89,8 @@ PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags)
|
|||||||
{
|
{
|
||||||
PageHeader p = (PageHeader) page;
|
PageHeader p = (PageHeader) page;
|
||||||
size_t *pagebytes;
|
size_t *pagebytes;
|
||||||
int i;
|
|
||||||
bool checksum_failure = false;
|
bool checksum_failure = false;
|
||||||
bool header_sane = false;
|
bool header_sane = false;
|
||||||
bool all_zeroes = false;
|
|
||||||
uint16 checksum = 0;
|
uint16 checksum = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -126,18 +124,9 @@ PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check all-zeroes case */
|
/* Check all-zeroes case */
|
||||||
all_zeroes = true;
|
|
||||||
pagebytes = (size_t *) page;
|
pagebytes = (size_t *) page;
|
||||||
for (i = 0; i < (BLCKSZ / sizeof(size_t)); i++)
|
|
||||||
{
|
|
||||||
if (pagebytes[i] != 0)
|
|
||||||
{
|
|
||||||
all_zeroes = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_zeroes)
|
if (pg_memory_is_all_zeros(pagebytes, (BLCKSZ / sizeof(size_t))))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "utils/memutils.h"
|
||||||
#include "utils/pgstat_internal.h"
|
#include "utils/pgstat_internal.h"
|
||||||
|
|
||||||
|
|
||||||
@ -30,7 +31,6 @@ void
|
|||||||
pgstat_report_bgwriter(void)
|
pgstat_report_bgwriter(void)
|
||||||
{
|
{
|
||||||
PgStatShared_BgWriter *stats_shmem = &pgStatLocal.shmem->bgwriter;
|
PgStatShared_BgWriter *stats_shmem = &pgStatLocal.shmem->bgwriter;
|
||||||
static const PgStat_BgWriterStats all_zeroes;
|
|
||||||
|
|
||||||
Assert(!pgStatLocal.shmem->is_shutdown);
|
Assert(!pgStatLocal.shmem->is_shutdown);
|
||||||
pgstat_assert_is_up();
|
pgstat_assert_is_up();
|
||||||
@ -39,7 +39,8 @@ pgstat_report_bgwriter(void)
|
|||||||
* This function can be called even if nothing at all has happened. In
|
* This function can be called even if nothing at all has happened. In
|
||||||
* this case, avoid unnecessarily modifying the stats entry.
|
* this case, avoid unnecessarily modifying the stats entry.
|
||||||
*/
|
*/
|
||||||
if (memcmp(&PendingBgWriterStats, &all_zeroes, sizeof(all_zeroes)) == 0)
|
if (pg_memory_is_all_zeros(&PendingBgWriterStats,
|
||||||
|
sizeof(struct PgStat_BgWriterStats)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pgstat_begin_changecount_write(&stats_shmem->changecount);
|
pgstat_begin_changecount_write(&stats_shmem->changecount);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "utils/memutils.h"
|
||||||
#include "utils/pgstat_internal.h"
|
#include "utils/pgstat_internal.h"
|
||||||
|
|
||||||
|
|
||||||
@ -29,8 +30,6 @@ PgStat_CheckpointerStats PendingCheckpointerStats = {0};
|
|||||||
void
|
void
|
||||||
pgstat_report_checkpointer(void)
|
pgstat_report_checkpointer(void)
|
||||||
{
|
{
|
||||||
/* We assume this initializes to zeroes */
|
|
||||||
static const PgStat_CheckpointerStats all_zeroes;
|
|
||||||
PgStatShared_Checkpointer *stats_shmem = &pgStatLocal.shmem->checkpointer;
|
PgStatShared_Checkpointer *stats_shmem = &pgStatLocal.shmem->checkpointer;
|
||||||
|
|
||||||
Assert(!pgStatLocal.shmem->is_shutdown);
|
Assert(!pgStatLocal.shmem->is_shutdown);
|
||||||
@ -40,8 +39,8 @@ pgstat_report_checkpointer(void)
|
|||||||
* This function can be called even if nothing at all has happened. In
|
* This function can be called even if nothing at all has happened. In
|
||||||
* this case, avoid unnecessarily modifying the stats entry.
|
* this case, avoid unnecessarily modifying the stats entry.
|
||||||
*/
|
*/
|
||||||
if (memcmp(&PendingCheckpointerStats, &all_zeroes,
|
if (pg_memory_is_all_zeros(&PendingCheckpointerStats,
|
||||||
sizeof(all_zeroes)) == 0)
|
sizeof(struct PgStat_CheckpointerStats)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pgstat_begin_changecount_write(&stats_shmem->changecount);
|
pgstat_begin_changecount_write(&stats_shmem->changecount);
|
||||||
|
@ -800,7 +800,6 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info,
|
|||||||
bool
|
bool
|
||||||
pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
|
pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
|
||||||
{
|
{
|
||||||
static const PgStat_TableCounts all_zeroes;
|
|
||||||
Oid dboid;
|
Oid dboid;
|
||||||
PgStat_TableStatus *lstats; /* pending stats entry */
|
PgStat_TableStatus *lstats; /* pending stats entry */
|
||||||
PgStatShared_Relation *shtabstats;
|
PgStatShared_Relation *shtabstats;
|
||||||
@ -815,11 +814,9 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
|
|||||||
* Ignore entries that didn't accumulate any actual counts, such as
|
* Ignore entries that didn't accumulate any actual counts, such as
|
||||||
* indexes that were opened by the planner but not used.
|
* indexes that were opened by the planner but not used.
|
||||||
*/
|
*/
|
||||||
if (memcmp(&lstats->counts, &all_zeroes,
|
if (pg_memory_is_all_zeros(&lstats->counts,
|
||||||
sizeof(PgStat_TableCounts)) == 0)
|
sizeof(struct PgStat_TableCounts)))
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
if (!pgstat_lock_entry(entry_ref, nowait))
|
if (!pgstat_lock_entry(entry_ref, nowait))
|
||||||
return false;
|
return false;
|
||||||
|
@ -189,4 +189,21 @@ extern MemoryContext BumpContextCreate(MemoryContext parent,
|
|||||||
#define SLAB_DEFAULT_BLOCK_SIZE (8 * 1024)
|
#define SLAB_DEFAULT_BLOCK_SIZE (8 * 1024)
|
||||||
#define SLAB_LARGE_BLOCK_SIZE (8 * 1024 * 1024)
|
#define SLAB_LARGE_BLOCK_SIZE (8 * 1024 * 1024)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if a memory region starting at "ptr" and of size "len" is full of
|
||||||
|
* zeroes.
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
pg_memory_is_all_zeros(const void *ptr, size_t len)
|
||||||
|
{
|
||||||
|
const char *p = (const char *) ptr;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (p[i] != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* MEMUTILS_H */
|
#endif /* MEMUTILS_H */
|
||||||
|
Reference in New Issue
Block a user