When performing a large number of HTTP requests using PHP’s cURL extension, you might encounter a performance bottleneck: redundant DNS resolution. Every time a request is made, cURL needs to resolve the domain name, which adds extra time, especially when making multiple requests to the same domain. Fortunately, PHP provides a function called curl_share_init(), which allows you to share DNS caches and avoid this problem. This article will guide you through how to use it.
curl_share_init() is a function provided by the cURL extension that creates a shared handle. This shared handle can be used to share specific resources, such as DNS cache, cookies, SSL sessions, etc., between multiple cURL sessions.
When enabling shared DNS cache, multiple requests only need to resolve the domain name once, and subsequent requests can reuse the result, greatly reducing network latency.
Let’s explain how to use it with a simple example code:
<?php
// Create a cURL shared handle
$sh = curl_share_init();
<p>// Set the shared option to enable DNS sharing<br>
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);</p>
<p>$urls = [<br>
'<a rel="noopener" target="_new" class="" href="https://m66.net/api/data1">https://m66.net/api/data1</a>',<br>
'<a rel="noopener" target="_new" class="" href="https://m66.net/api/data2">https://m66.net/api/data2</a>',<br>
'<a rel="noopener" target="_new" class="" href="https://m66.net/api/data3">https://m66.net/api/data3</a>',<br>
];</p>
<p>foreach ($urls as $url) {<br>
$ch = curl_init();</p>
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Bind the shared handle
curl_setopt($ch, CURLOPT_SHARE, $sh);
// Execute the request
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch) . PHP_EOL;
} else {
echo 'Response: ' . $response . PHP_EOL;
}
// Close the cURL session
curl_close($ch);
}
// Close the shared handle
curl_share_close($sh);
?>
1. Create a Shared Handle
We create a shared handle $sh using curl_share_init().
2. Set Shared Resources
Using curl_share_setopt(), we specify that we want to share DNS data (CURL_LOCK_DATA_DNS).
3. Bind Shared Handle to Each cURL Session
In curl_setopt(), we associate the shared handle with the current cURL handle $ch using CURLOPT_SHARE.
4. Close the Handle
After all requests are completed, remember to release the shared handle using curl_share_close().
The shared handle must be closed after all requests have completed.
If the program runs multi-threaded or concurrent requests, be cautious of resource locking to prevent race conditions.
Sharing other resources like cookies or SSL data can also be done in the same way, just replace the CURL_LOCK_DATA_* constant.
For scenarios that involve many requests to the same domain, such as API aggregation, bulk scraping, or load testing, avoiding redundant DNS resolution can usually result in a 10% to 30% performance improvement, depending on DNS query speed and server latency. While not every scenario will see a huge improvement, it is a simple and almost cost-free optimization method.