[CurlOne] Reducing the Churn of Optionation
Michael via curl-and-php <[email protected]>
| Newsgroups | gmane.comp.web.curl.php |
|---|---|
| Message-ID | <CAMVeLLJUpbFge+2u1MUitdPqJ_kd+hWUqG5s=9-OPS11Z4Qx2g@mail.gmail.com> |
Call Chain Overhead in Monolithic Option Routing
------------------------------------------------
Due to a monolithic design where all application
protocols are bundled into a single library, libcurl
options carry significant execution depth by default.
Supposed for bulk assignment, options are set
one-by-one, byte-by-byte with a deep dive into the
call stack.
Setting CURLOPT_POSTFIELDS illustrates this
traversal:
curl_easy_setopt
└─ Curl_vsetopt
└─ setopt_cptr
├─ setopt_cptr_proxy
├─ setopt_cptr_ssl
├─ setopt_cptr_ssh
├─ setopt_cptr_ftp
└─ setopt_cptr_http_mqtt
This path requires 8 function calls merely to pass
a single pointer. Disabling proxy, ssl, ssh, and
ftp reduces the chain to 4 calls—an evident benefit
of trimming the monolith.
-------------------------------------------------------
Extension Architecture and Gatekeeping Requirements
---------------------------------------------------
Any extension interfacing with libcurl requires a
dispatcher similar to Curl_vsetopt. Mapping userland
glue-code types to native C types requires
categorizing options into distinct type groups. Standard
C applications simply invoke top-level APIs, but
language extensions must gatekeep option flow from
userland. This involves filtering options abstracted via
dedicated helpers, such as those handling data payloads,
headers, or execution callbacks.
Using Curl_vsetopt as the basis for a custom setter
like CurlOne_setUserOption while calling
curl_easy_setopt under the hood further increases call
depth and execution churn. The simplest alternative is
removing static visibility from internal setopt helpers
and calling them directly:
setopt_long
setopt_slist
setopt_pointers
setopt_cptr
setopt_func
setopt_offt
setopt_blob
This pattern becomes achievable when the extension is
compiled directly alongside the library. Making
CurlOne_setUserOption inline eliminates 2 call frame
overhead steps per option.
A long-term solution requires modularity and clean
data structures, though monolithic codebases lean toward
a large inline dispatcher featuring a centralized
switch statement. This setup benefits from dedicated
inline helpers for fast-path internal assignments when
the option identity is known at compile time.
-------------------------------------------------------
Implementation Differences: Blob and List Handlers
---------------------------------------------------
For blob options, standard ext/curl coerces arguments
to strings and passes CURL_BLOB_COPY, forcing libcurl
to allocate and copy memory. In contrast, CurlOne
fails on non-string inputs, avoids CURL_BLOB_COPY
entirely, and increments the userland string reference
count to preserve lifetime without duplication.
For string lists, CurlOne avoids curl_slist_append
allocations by storing values in a custom array
structure. Standard ext/curl relies on maintaining
both libcurl linked lists and Zend engine arrays
simultaneously.
-------------------------------------------------------
Bypassing Call Churn in Telemetry Retrieval
-------------------------------------------
The same architectural pattern applies to CURL info
queries. Extensions must build upon lower-level
Curl_getinfo internals rather than calling the
public curl_easy_getinfo entry point. Converting native
types to userland types requires masking through
CURLINFO_TYPEMASK. Calling curl_easy_getinfo from
getter wrappers introduces redundant call layers,
whereas exposing internal static helpers eliminates
unnecessary dispatch churn.
--
curl-and-php mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/curl-and-php