[CurlOne] Synchronous request lifecycle completion (perform & getData)
Michael via curl-and-php <[email protected]> Thu, 30 Jul 2026 01:51:36 +0500
| Newsgroups | gmane.comp.web.curl.php |
|---|---|
| Message-ID | <CAMVeLLL3D7hwdavE_9GZ=fJ+5rXEo+JW7D94r2KbJx7yc04CBA@mail.gmail.com> |
--===============3310780164404734478== Content-Type: multipart/alternative; boundary="0000000000006a4d240657c62613" --0000000000006a4d240657c62613 Content-Type: text/plain; charset="UTF-8" Completion of the synchronous easy handle lifecycle requires calling perform() method (~curl_exec) to execute the transfer before getData() (~no analogue) can assemble and return the response body. Analysis vs. bundled ext/curl: The standard ext/curl extension included with PHP handles response bodies under CURLOPT_RETURNTRANSFER by coupling directly to PHP's engine-level smart_str API inside an internal write callback. As packet chunks arrive, smart_str repeatedly grows a single zend_string via erealloc. Upon completion, ownership of that allocation is handed directly to PHP userland with zero additional copying. CurlOne decouples from the core PHP smart_str module to remove engine dependencies. It implements payload buffering via a singly-linked list of 16-byte aligned heap chunks (curlDataChunk_t) appended during CURLOPT_WRITEFUNCTION. Assembly into a single contiguous php_string_t is deferred until getData() is called, while perform() resets buffer state ahead of subsequent transfers. Trade-offs: * Memory Allocation Strategy: Bundled ext/curl incurs transfer-time heap reallocations to keep data contiguous, achieving zero-copy retrieval. CurlOne trades transfer-time reallocation for predictable single-chunk allocations, paying the penalty of a secondary sequential memcpy pass across the list when constructing the final string in getData(). * libcurl Architectural Limits: Unlike its header iterator (curl_easy_nextheader()), libcurl offers no native internal payload accumulator. CurlOne must therefore retain a custom CURLOPT_WRITEFUNCTION callback, incurring per-packet function call churn and an intermediate copy. A native libcurl accumulation option would eliminate both this callback layer and the secondary assembly pass. Option Differences: * CURLOPT_WRITEFUNCTION / CURLOPT_WRITEDATA: Bound internally to CurlOne_responseSet(). Can be remapped to a userland callback with setDataReader(). * CURLOPT_RETURNTRANSFER: Omitted entirely from the option matrix; payload retrieval is explicitly managed via $client->getData(). --0000000000006a4d240657c62613 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">Completion of the synchronous easy handle lifecycle requir= es calling perform() method (~curl_exec) to execute the transfer before get= Data() (~no analogue) can assemble and return the response body.<br><br>Ana= lysis vs. bundled ext/curl:<br>The standard ext/curl extension included wit= h PHP handles response bodies under CURLOPT_RETURNTRANSFER by coupling dire= ctly to PHP's engine-level smart_str API inside an internal write callb= ack. As packet chunks arrive, smart_str repeatedly grows a single zend_stri= ng via erealloc. Upon completion, ownership of that allocation is handed di= rectly to PHP userland with zero additional copying.<br><br>CurlOne decoupl= es from the core PHP smart_str module to remove engine dependencies. It imp= lements payload buffering via a singly-linked list of 16-byte aligned heap = chunks (curlDataChunk_t) appended during CURLOPT_WRITEFUNCTION. Assembly in= to a single contiguous php_string_t is deferred until getData() is called, = while perform() resets buffer state ahead of subsequent transfers.<br><br>T= rade-offs:<br><br>* Memory Allocation Strategy: Bundled ext/curl incurs tra= nsfer-time heap reallocations to keep data contiguous, achieving zero-copy = retrieval. CurlOne trades transfer-time reallocation for predictable single= -chunk allocations, paying the penalty of a secondary sequential memcpy pas= s across the list when constructing the final string in getData().<br>* lib= curl Architectural Limits: Unlike its header iterator (curl_easy_nextheader= ()), libcurl offers no native internal payload accumulator. CurlOne must th= erefore retain a custom CURLOPT_WRITEFUNCTION callback, incurring per-packe= t function call churn and an intermediate copy. A native libcurl accumulati= on option would eliminate both this callback layer and the secondary assemb= ly pass.<br><br>Option Differences:<br><br>* CURLOPT_WRITEFUNCTION / CURLOP= T_WRITEDATA: Bound internally to CurlOne_responseSet(). Can be remapped to = a userland callback with setDataReader().<br>* CURLOPT_RETURNTRANSFER: Omit= ted entirely from the option matrix; payload retrieval is explicitly manage= d via $client->getData().</div> --0000000000006a4d240657c62613-- --===============3310780164404734478== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline -- curl-and-php mailing list [email protected] https://lists.haxx.se/mailman/listinfo/curl-and-php --===============3310780164404734478==--