Open hamdallah90 opened 4 months ago
👋 Can you provide an Minimum Reproducible Example with plain JS to support you better?
node httpClientExample.mjs
Making 100 requests without Proxy... Total time without Proxy: 10058.17 ms Average time without Proxy: 100.57 ms
Making 100 requests with Proxy... Total time with Proxy: 45844.97 ms Average time with Proxy: 458.43 ms
this is the code
import { request, ProxyAgent, getGlobalDispatcher } from "undici";
import { createGunzip } from "zlib";
import { pipeline, Readable, Writable } from "stream";
import { promisify } from "util";
import { Buffer } from "buffer";
const pipelinePromise = promisify(pipeline);
const baseURL = "https://jsonplaceholder.typicode.com";
const proxyURL = "http://127.0.0.1:3128"; // Change this to your actual proxy URL
const timeout = 30000;
const numberOfRequests = 100;
async function fetchWithUndici(url, useProxy = false) {
const dispatcher = useProxy ? new ProxyAgent(proxyURL) : getGlobalDispatcher();
const { statusCode, headers, body } = await request(`${baseURL}${url}`, {
method: 'GET',
dispatcher,
headersTimeout: timeout
});
const responseBody = await getResponseBody(headers, body);
return { statusCode, headers, responseBody };
}
async function getResponseBody(headers, body) {
const buffers = [];
for await (const chunk of body) {
buffers.push(chunk);
}
const buffer = Buffer.concat(buffers);
if (headers['content-encoding'] === 'gzip') {
return decompressGzip(buffer);
}
return parseResponse(buffer);
}
function decompressGzip(buffer) {
const gunzip = createGunzip();
const decompressedBuffers = [];
return new Promise((resolve, reject) => {
pipelinePromise(
Readable.from([buffer]),
gunzip,
new Writable({
write(chunk, encoding, callback) {
decompressedBuffers.push(chunk);
callback();
}
})
)
.then(() => {
const decompressed = Buffer.concat(decompressedBuffers);
resolve(parseResponse(decompressed));
})
.catch(reject);
});
}
function parseResponse(buffer) {
const responseText = buffer.toString();
try {
return JSON.parse(responseText);
} catch {
return responseText;
}
}
async function measureRequests(useProxy) {
const times = [];
const startTotal = process.hrtime();
for (let i = 0; i < numberOfRequests; i++) {
const start = process.hrtime();
await fetchWithUndici("/posts/1", useProxy);
const end = process.hrtime(start);
const timeInMs = end[0] * 1000 + end[1] / 1e6;
times.push(timeInMs);
}
const endTotal = process.hrtime(startTotal);
const totalTime = endTotal[0] * 1000 + endTotal[1] / 1e6;
const averageTime = times.reduce((a, b) => a + b, 0) / times.length;
return { totalTime, averageTime };
}
(async () => {
console.log(`Making ${numberOfRequests} requests without Proxy...`);
const { totalTime: totalTimeWithoutProxy, averageTime: averageTimeWithoutProxy } = await measureRequests(false);
console.log(`Total time without Proxy: ${totalTimeWithoutProxy.toFixed(2)} ms`);
console.log(`Average time without Proxy: ${averageTimeWithoutProxy.toFixed(2)} ms`);
console.log(`Making ${numberOfRequests} requests with Proxy...`);
const { totalTime: totalTimeWithProxy, averageTime: averageTimeWithProxy } = await measureRequests(true);
console.log(`Total time with Proxy: ${totalTimeWithProxy.toFixed(2)} ms`);
console.log(`Average time with Proxy: ${averageTimeWithProxy.toFixed(2)} ms`);
})();
this is when using axios
node httpClientExample.mjs
Making 100 requests without Proxy... Total time without Proxy: 10229.93 ms Average time without Proxy: 102.29 ms
Making 100 requests with Proxy... Total time with Proxy: 20142.50 ms Average time with Proxy: 201.41 ms
This is when using axios with Promise.all
node httpClientExample.mjs Making 100 requests without Proxy... Total time without Proxy: 535.43 ms Average time without Proxy: 407.45 ms Making 100 requests with Proxy... Total time with Proxy: 628.32 ms Average time with Proxy: 428.96 ms
This is when using undici with Promise.all
❯ node httpClientExample.mjs Making 100 requests without Proxy... Total time without Proxy: 499.42 ms Average time without Proxy: 373.25 ms Making 100 requests with Proxy... Total time with Proxy: 16655.35 ms Average time with Proxy: 7610.46 ms
Looks like there is a bug somewhere, good spot!
What would be good is to have a complete way to reproduce your problem. I recommend you to create a repository and include everything, so we can reproduce this benchmark locally.
(yes, it should include a target server and the proxy).
Hello,
I'm experiencing a significant slowdown in request performance when using ProxyAgent with the undici library. The same requests without a proxy are much faster. Below are the details of my setup and the observed behavior.
Steps to Reproduce:
Thank you for your attention to this issue. Any insights or fixes would be greatly appreciated.
Best regards,