From 55d0b2adb204999a293ab1075c3af28cbf5d57e4 Mon Sep 17 00:00:00 2001 From: sohardforaname Date: Wed, 26 Aug 2026 23:20:38 +0800 Subject: [PATCH] Speed up repeat() for larger counts Build repeated strings by reusing and doubling the portion of the result already produced, reducing the number of memcpy() calls. Use memset() for single-byte input strings. --- src/backend/utils/adt/oracle_compat.c | 35 ++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index 7422a454397..602ac1a4bcb 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -1165,7 +1165,7 @@ repeat(PG_FUNCTION_ARGS) text *result; int slen, tlen; - int i; + int curcount; char *cp, *sp; @@ -1186,10 +1186,37 @@ repeat(PG_FUNCTION_ARGS) SET_VARSIZE(result, tlen); cp = VARDATA(result); sp = VARDATA_ANY(string); - for (i = 0; i < count; i++) + + if (count == 0 || slen == 0) + PG_RETURN_TEXT_P(result); + + if (slen == 1) + { + memset(cp, *sp, count); + CHECK_FOR_INTERRUPTS(); + PG_RETURN_TEXT_P(result); + } + + memcpy(cp, sp, slen); + cp += slen; + CHECK_FOR_INTERRUPTS(); + + curcount = 1; + + /* + * Reuse the portion of the result already produced, doubling the number + * of copies on each iteration until the requested count is reached. + * + * chunk is never greater than curcount, so the source and destination + * ranges of memcpy() do not overlap. + */ + while (curcount < count) { - memcpy(cp, sp, slen); - cp += slen; + int chunk = Min(curcount, count - curcount); + + memcpy(cp, VARDATA(result), chunk * slen); + cp += chunk * slen; + curcount += chunk; CHECK_FOR_INTERRUPTS(); } -- 2.43.0