[php-src] PR #24385: ext/pdo_pgsql: Parse integer columns inline
| From: | brainexe | Date: | Sat, 17 Oct 2026 17:52:40 +0000 |
| Subject: | [php-src] PR #24385: ext/pdo_pgsql: Parse integer columns inline | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39522@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24385
Author: brainexe
After some more profiling of our heavy workload with tideway/perf etc in came up this optimization.
PostgreSQL sends
int2/int4/int8 values in text format as an
optional minus sign followed by digits. pgsql_stmt_get_col() converted each of them
with ZEND_ATOL(), i.e. strtoll(), which handles whitespace, signs, bases
and locales. In profiles of integer-heavy fetches, glibc's strtoll accounted for
up to 10% of the CPU time.
This PR parses those values inline. Values with more digits than always fit into a
zend_long (more than 18 on 64-bit, 9 on 32-bit), and anything that is not plain digits,
still go through ZEND_ATOL(), so the results are unchanged.
## Benchmark
fetchAll(PDO::FETCH_ASSOC) of 1M rows with 4 integer columns, compared to master
(perf stat, mean of 5 runs):
| | master | this PR | |
|---|---|---|---|
| instructions | 3232M | 2777M | −14% |
| cycles | 812M | 700M | −14% |
Mixed workloads gain less, depending on how many columns are integers. For example,
fetchAll of 10k rows with 11 columns, 2 of them integers, executes 2.3% fewer
instructions.
## Verification
- New test ext/pdo_pgsql/tests/fetch_integers.phpt (64-bit only) covers
int2, int4 and int8 at their limits and around the
18/19-digit threshold, including PHP_INT_MIN.
- Differential check against master: 200k rows of random
int2/int4/int8 values with 1–19 digits, both signs and the
extreme values. The fetched values and their types are identical.
- The ext/pdo and ext/pdo_pgsql test suites pass with native prepares.
With emulated prepares forced on, the same tests fail as on master.