| From: | Heikki Linnakangas <hlinnaka(at)iki(dot)fi> |
|---|---|
| To: | Jeevan Chalke <jeevan(dot)chalke(at)enterprisedb(dot)com>, ChenhuiMo <chenhuimo(dot)mch(at)qq(dot)com> |
| Cc: | pgsql-hackers <pgsql-hackers(at)postgresql(dot)org> |
| Subject: | Re: [PATCH] Speed up repeat() for larger counts |
| Date: | 2026-07-27 10:18:09 |
| Message-ID: | 84412f41-814f-4909-8776-ca0f9949ad96@iki.fi |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On 27/07/2026 10:31, Jeevan Chalke wrote:
> Hello ChenhuiMo,
>
> This is a really interesting optimization — doing memcpy() exponentially
> is a great idea for larger counts. My main use case for repeat() is
> generating large files and padding, where count is usually large, so
> this change helps exactly the workload I care about.
>
> That said, I'm not entirely sure how common this usage pattern is in
> general production workloads, so I was initially unsure whether the
> added complexity is worth it. Setting that aside, the performance gain
> for short strings repeated a large number of times is real, so I'm fine
> with getting this in.
Yeah, probably the most common case is something like repeat('x',
1000000). It might even be worth special-casing the single-byte case and
turn that into a single memset() call.
> A few things worth looking at:
>
> 1. The magic number 8 is unexplained. The naive-loop fallback threshold
> seems quite low — should it be closer to a few dozen, say 64? I
> benchmarked a range of thresholds and counts: the doubling approach
> turns out to beat the naive loop even at very small counts (as low as 2–
> 3), so 8 already looks like a reasonable cutoff; raising it to 64 would
> likely make counts in the 8–64 range slower, not faster. Regardless of
> the exact value chosen, the constant needs a comment explaining why it
> was picked.
>
> 2. Because of the exponential growth, CHECK_FOR_INTERRUPTS() granularity
> drops off logarithmically; the later doubling steps can copy hundreds of
> MB in a single memcpy that can't be interrupted partway through. Would
> it help to cap the chunk size, say at 64–100MB? I tested this: capping
> adds only a handful of extra memcpy calls even for very large repeats,
> and the overhead was within noise; so it looks like a cheap way to bound
> worst-case interrupt latency.
Beyond certain size, I'd guess it might even become slower, if the
string no longer fits in the L0 CPU cache for example. Also, if the
fast-path used a constant size, like 64 bytes, maybe the compiler could
optimize the memcpy() into a single SIMD instruction or something.
- Heikki
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Akshay Joshi | 2026-07-27 10:34:52 | Re: [PATCH] Add pg_get_table_ddl() to reconstruct CREATE TABLE statements |
| Previous Message | Tender Wang | 2026-07-27 09:48:22 | Re: Partition pruning can incorrectly exclude a RANGE default partition |