-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: poor outgoing network performance on Mac #20062
fix: poor outgoing network performance on Mac #20062
Conversation
Thanks for taking the time to open a PR!
|
@moyara-twilio Thanks for opening this issue, we are always looking to optimize improvements to the performance of Cypress. The system-tests here failing is unrelated to your work and related to #20075 just for context. |
Hello team! Any feedback or update on this? |
I verified with my old macbook that 10.14 Mojave does not have this issue. |
Would be curious your thoughts @flotwig |
Hello, any update? this would improve developer experiences significantly in local development for MacOS users. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @moyara @moyara-twilio, thank you for opening a PR. Sorry it's taken so long to get to this one.
So it seems like the main change here is to always send servername
when we are making an HTTPS request. Is that understanding correct? Can you confirm that this issue only happens with HTTPS, not HTTP? Trying to understand what the core issue is and how this fixes it.
Hi @flotwig , it does not matter whether http or https. It seems like net.connect and immediate close triggers the issue. And this is MacOS specific. I specified more details in nodejs/node#41699.
|
@moyara-twilio we would like to have a little more information about exactly what is going on here. We have tried on Macs on our side and couldn't reproduce this issue. We tried monkey patching dns.lookup to return the exact addresses that you have in your logs and we still could not reproduce. I was wondering if you could try a couple of things to help us narrow down the exact root cause in your exact set up. In the existing code without your change, could you:
|
@ryanthemanuel hmm interesting. I tried 4 different Mac from my colleagues and confirmed all happen. const Url = require('url')
const net = require('net');
const tls = require('tls');
const https = require('https');
const url = "https://www.google.com"
// Does not matter port or host in net.connect
console.time('1.1.1.1')
net.connect({ port: 443, host: '1.1.1.1' }, function () {
console.timeLog('1.1.1.1', 'connected')
this.end();
}).on('close', () => {console.timeLog('1.1.1.1', 'closed')});
console.time(url)
https.request(Url.parse(url), (res) => {
console.timeLog(url, 'response')
res.on('data', () => {
console.timeLog(url, 'data');
})
}).on('socket', (socket) => {
console.timeLog(url, 'connected')
socket.on('lookup', () => console.timeLog(url, 'lookup'))
}).end();
When .destroy() and use tls.connect()
It still happened even put the https.request() in onConnect callback right after .end() as well. |
Added some more logs in connect.ts export function byPortAndAddress (hostname: string, port: number, address: net.Address) {
// https://nodejs.org/api/net.html#net_net_connect_port_host_connectlistener
return new Bluebird<net.Address>((resolve, reject) => {
const onConnect = () => {
console.timeLog('https://www.google.com', 'onConnect to', address);
client.end()
resolve(address)
}
let client = net.connect({ port, host: address.address }, onConnect)
client.on('error', reject)
client.on('close', () => {
console.timeLog('https://www.google.com', 'closed', address);
});
})
}
for more information |
@moyara I just updated to MacOS 12.2.1 and I'm still not seeing the issue (see below). I'll reach out to a few colleagues tomorrow to see if they can reproduce on their setup. I'm sure there's something different going on between our setups. Out of curiosity, what are your DNS settings?
|
@ryanthemanuel I have no specific DNS setting. I could reproduce it using my old Macbook(Big Sur). But another Mac with 10.14 Mojave does not have this issue in the same network.
I'll also ask people outside my company to see if it only happens for the company laptops. |
OK turned out that my company wide software |
@moyara we'd be good with replacing the call to client.end() with client.destroy(). Can you make sure and add a test that covers that scenario? |
48751dd
to
8448db2
Compare
@ryanthemanuel update the PR. Please review :) |
Looking forward to see this fix merged in. This issue has bothered me for a very long time. |
@moyara-twilio @moyara thank you for the contribution and thank you for working with us to isolate the root of this issue :) |
Released in This comment thread has been locked. If you are still experiencing this issue after upgrading to |
User facing changelog
Fixed poor network issue in MacOS on initial requests when using VMware CBCloud.
Additional details
I have been experiencing tests hangs when run cypress locally and always timed out. Digging into the issue, finally narrowed down
net.connect
makes super slow when http agent makes requests.This eventually turned out that NodeJS bug in MacOS. I have reported in nodejs/node#41699 for more details.
In Cypress, when outgoing requests happen, http agent first lookup DNS records and find out the fasted IP family.
https://github.com/cypress-io/cypress/blob/develop/packages/network/lib/connect.ts#L24
When there are 4 hosts in a DNS record like www.google.com, it tries 4 net.connect() for the hosts which eventually makes 4x slower than usual request without net.connect() in my experiment.
Simplified sample code to reproduce the issue from https://github.com/cypress-io/cypress/blob/develop/packages/server/lib/request.js#L434
before fix
After fix
How has the user experience changed?
I have observed http requests hangs or pending status initially and randomly fails with timeout. Once the website has 3rd party dependencies such as Segment, Heap, Google Analytics etcs, it all goes slow for the net.connect issue and finally made the tests unreliable.
I verified with my colleagues that it works and this improves network performance significantly running tests in MacOS. This would solve most problem with timeouts or flakiness due to tests hang for Mac users.
Also verified the issue does not happen in Debian and Centos. Have not verified in Windows and Mac M1 chips.
PR Tasks
cypress-documentation
?type definitions
?cypress.schema.json
?