diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 0555b02a8d..c8ce084def 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -4617,18 +4617,24 @@ KnownAssignedXidsCompress(bool force) { /* * If we can choose how much to compress, use a heuristic to avoid - * compressing too often or not often enough. + * compressing too often or not often enough. "Compress" here means + * simply moving the values to the beginning of the array, so is + * not as complex or costly as typical data compression algorithms. * - * Heuristic is if we have a large enough current spread and less than - * 50% of the elements are currently in use, then compress. This - * should ensure we compress fairly infrequently. We could compress - * less often though the virtual array would spread out more and - * snapshots would become more expensive. + * Heuristic is if less than 50% of the elements are currently in + * use, then compress. This ensures time to take a snapshot is + * bounded at S=2N, using the same notation from earlier comments, + * which is essential to avoid limiting scalability with high N. + * Previously, we prevented compression until S=4M, ensuring that + * snapshot speed would be slow and scale poorly with many CPUs. + * + * As noted earlier, compression is O(S), so now O(2N), while frequency + * of compression is now O(1/N) so that as N varies, the algorithm + * balances nicely the frequency and cost of compression. */ int nelements = head - tail; - if (nelements < 4 * PROCARRAY_MAXPROCS || - nelements < 2 * pArray->numKnownAssignedXids) + if (nelements < 2 * pArray->numKnownAssignedXids) return; } @@ -4924,8 +4930,10 @@ KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, for (i = 0; i < nsubxids; i++) KnownAssignedXidsRemove(subxids[i]); - /* Opportunistically compress the array */ - KnownAssignedXidsCompress(false); + /* Opportunistically compress the array, every N commits */ + if (TransactionIdIsValid(xid) && + ((int) xid) % 8 == 0) + KnownAssignedXidsCompress(false); } /*