PHP, while generally stateless by default, occasionally provides forms of “persistence” for connections, e.g. PDO::ATTR_PERSISTENT for persistent PDO connections.
Persistence allows PHP scripts to eliminate the overhead of establishing a connection on subsequent requests, which can improve performance and reliability.
curl
, a popular URL transfer library made available as a core extension in PHP, provides the ability to share data between curl handles via a “share” interface. The PHP extension supports this functionality in curl_share_init
and related functions.
The PHP extension does not, however, support persistent curl share handles. Connections (and DNS lookups, SSL session IDs, etc.) are only shared between handles within a single SAPI request.
This RFC proposes to add a new function, curl_share_init_persistent($id, $share_options)
, that will construct a persistent curl share handle.
When called, the function will first check the global memory within the SAPI worker for an existing curl share handle. If found, the function will return immediately.
If a curl share handle does not already exist, the function will construct a new one, apply the given share options, store it in global memory, and return it.
I had originally attempted to add a single new optional $persistent_id
parameter to curl_share_init
, and then to call curl_share_setopt
on the handle to set share options separately. Unfortunately I ran into https://github.com/curl/curl/pull/14696, where it seems that curl was re-initializing some of the share options in a way that broke functionality.
This issue meant that I needed to set the share options only once in userland, which is difficult or impossible to do. I decided to introduce a new function where the PHP extension could safely know if it needed to apply the share options or not.
At the time of writing the RFC I have come up with a new alternative: we could change the signature of curl_share_init
to curl_share_init(array|null $share_options, string|null $persistent_id)
. I don't have a strong opinion on either.
None expected.
Next PHP 8.x
release.
SAPIs will consume more memory proportional to the number of persistent curl share handles.
ext/curl
will have a new function.
None.
None.
None.
My first attempt at a pull request used the EG(persistent_list)
global variable, which uses “internal” (i.e. not directly exposed to userland) resources. I received feedback from @cmb69 that this was deprecated, but https://wiki.php.net/rfc/resource_to_object_conversion does not directly address internal resources. These are currently still used in places like PDO and streams, even when they return objects to userland.
Fortunately I was able to come up with an alternative implementation using ZEND_BEGIN_MODULE_GLOBALS
instead, but it's unclear whether this is a better approach. I don't have a strong opinion on which method of persistence I use, only that I'm able to implement persistence at all.
From @kocsismate:
I'm wondering if it would make sense to explicitly close persistent shares with curl_share_close? It's a no-op for regular shares, but it may be useful for persistent ones?
This vote would require a ⅔ majority:
Add curl share persistence in the next PHP 8.x |
---|
This vote would require a simple majority:
Method signature | |
---|---|
curl_share_init_persistent(string $id, array $share_options) | curl_share_init(?array $share_options, ?string $persistent_id) |
curl_share_init_persistent
: https://github.com/php/php-src/pull/15603