From 09f718e6132f0aa8f8fd3851200ee3c7a025c520 Mon Sep 17 00:00:00 2001 From: alterego655 <824662526@qq.com> Date: Sat, 18 Oct 2025 15:24:35 +0800 Subject: [PATCH v1] The SnapBuildPurgeOlderTxn function previously used an suboptimal\nmethod to remove old XIDs from the committed.xip array. It allocated\na temporary workspace array, copied the surviving elements into it, and\nthen copied them back. This incurred the overhead of memory allocation\nand multiple data copies.\n\nRefactors the logic to use a standard two-pointer, in-place compaction algorithm. \nThis approach filters the array in a single pass with no additional memory allocation, \nmaking it more efficient in both CPU and memory usage. --- src/backend/replication/logical/snapbuild.c | 22 ++++----------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 98ddee20929..b2e1d41f32a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -863,39 +863,25 @@ static void SnapBuildPurgeOlderTxn(SnapBuild *builder) { int off; - TransactionId *workspace; int surviving_xids = 0; /* not ready yet */ if (!TransactionIdIsNormal(builder->xmin)) return; - /* TODO: Neater algorithm than just copying and iterating? */ - workspace = - MemoryContextAlloc(builder->context, - builder->committed.xcnt * sizeof(TransactionId)); - - /* copy xids that still are interesting to workspace */ + /* Use in-place compaction to remove xids < xmin */ for (off = 0; off < builder->committed.xcnt; off++) { - if (NormalTransactionIdPrecedes(builder->committed.xip[off], - builder->xmin)) - ; /* remove */ - else - workspace[surviving_xids++] = builder->committed.xip[off]; + if (!NormalTransactionIdPrecedes(builder->committed.xip[off], + builder->xmin)) + builder->committed.xip[surviving_xids++] = builder->committed.xip[off]; } - /* copy workspace back to persistent state */ - memcpy(builder->committed.xip, workspace, - surviving_xids * sizeof(TransactionId)); - elog(DEBUG3, "purged committed transactions from %u to %u, xmin: %u, xmax: %u", (uint32) builder->committed.xcnt, (uint32) surviving_xids, builder->xmin, builder->xmax); builder->committed.xcnt = surviving_xids; - pfree(workspace); - /* * Purge xids in ->catchange as well. The purged array must also be sorted * in xidComparator order. -- 2.51.0