curl / Mailing Lists / curl-and-php / Single Mail
Buy commercial curl support. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder Daniel himself.

[CurlOne] Synchronous request lifecycle completion (perform & getData)

From: Michael via curl-and-php <curl-and-php_at_lists.haxx.se>
Date: Thu, 30 Jul 2026 01:51:36 +0500

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().


-- 
curl-and-php mailing list
curl-and-php_at_lists.haxx.se
https://lists.haxx.se/mailman/listinfo/curl-and-php
Received on 2026-07-29