From d9011a17edca0915401c3a658947a35f0b8e338f Mon Sep 17 00:00:00 2001 From: Chenhui Mo Date: Tue, 16 Jun 2026 11:28:06 +0800 Subject: [PATCH] speed up repeat() for larger counts Use the existing linear copy path for small repeat counts, but switch to a doubling copy strategy for larger ones. This reduces the number of memcpy() calls needed to build the result string, improving repeat() performance for larger counts while preserving the existing behavior for small counts. --- src/backend/utils/adt/oracle_compat.c | 28 +++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index 5b0d098bd07..bb20c502576 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -1150,7 +1150,6 @@ repeat(PG_FUNCTION_ARGS) text *result; int slen, tlen; - int i; char *cp, *sp; @@ -1171,11 +1170,36 @@ 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 (count < 8) + { + int i; + for (i = 0; i < count; i++) + { + memcpy(cp, sp, slen); + cp += slen; + CHECK_FOR_INTERRUPTS(); + } + } + else { + int curcount = 1; memcpy(cp, sp, slen); cp += slen; CHECK_FOR_INTERRUPTS(); + + while (curcount < count) + { + int chunk = Min(curcount, count - curcount); + + memcpy(cp, VARDATA(result), chunk * slen); + cp += chunk * slen; + curcount += chunk; + CHECK_FOR_INTERRUPTS(); + } } PG_RETURN_TEXT_P(result); -- 2.43.0