Skip to content
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

Upload performance is less impressive than download #1117

Open
jgmission opened this issue Feb 2, 2021 · 18 comments
Open

Upload performance is less impressive than download #1117

jgmission opened this issue Feb 2, 2021 · 18 comments

Comments

@jgmission
Copy link

I deployed one chat server and opened one chat client in different countries. I used this single client to profile download and upload performance. The download speed could reach about 15Mbps, which is OK. But the upload speed never reached 1Mbps. The server continued processing messages for some time after client finished sending all the messages. No message was lost on the server side. It seems there is some throttling for upload.

If there is throttling, where can I find out the code for throttling? If there is not, how can I improve the upload speed?

Thank you.

@PhilipRoman
Copy link
Collaborator

There are a lot of factors that could cause this. Does your server do any significant work in onMessage? If yes, try offloading the work to another thread using a blocking queue or an executor service (or just comment it out for sake of testing).

If that doesn't fix the issue, you should create a minimal example that demonstrates the issue and post it here so we can investigate it.

There shouldn't be any throttling done in this library.

@jgmission
Copy link
Author

jgmission commented Feb 3, 2021

Here is the example. I made minimal changes to ChatServer and ChatClient. If the server and client are in different countries, you will see the upload speed is less than 1Mbps. The sending call runs very quickly, but the messages are kept in memory on Client side and processed slowly.

example

I used WireShark to compare this example with some online speed test. It seems ChatClient gets ACK packets from ChatServer much more frequently than online speed test.

@PhilipRoman
Copy link
Collaborator

If my measurements are correct, the example sends 60 Mbps of websocket data, which is... a lot. Keep in mind that each message on console represents 120000 bytes sent.

The only way to see if the bottleneck is in this library is to check the TCP upload speed between both machines using something like iperf and compare it with websocket throughput.

For me, the TCP upload speed between my laptop and server is 14 Mbps while the websocket server can keep up with 6 Mbps.

@jgmission
Copy link
Author

Yes, console prints out one line per 100 send() calls, which send 120000 bytes. In my testing, the client console printed out the lines very quickly, which gave me the impression that the upload was very fast. But in fact, most messages were kept in memory by the client and the memory usage kept going up. The server received about 100 messages per second and the server console printed out the lines at a much slower speed - about one line per second. You can check out the screenshot of my testing.

Timestamp is printed out in console now after I made minor code change: example

perf

@PhilipRoman
Copy link
Collaborator

The send call on client side doesn't block. It creates the frame and pushes it to a linked blocking queue.

@jgmission
Copy link
Author

jgmission commented Feb 3, 2021

So the blocking queue is not consumed in a timely manner, is it? How can I improve the throughput?

@PhilipRoman
Copy link
Collaborator

Have you checked the actual TCP throughput? Are you sure you aren't simply limited by internet speed between the two machines?

@jgmission
Copy link
Author

jgmission commented Feb 3, 2021

If I remove line 817 (ostream.write(buffer.array(), 0, buffer.limit());) in WebSocketClient.java, the blocking queue is consumed fast enough. So it seems the bottleneck is in the Socket.

The upload speed of my internet connection is 500Mbps, and the download speed of the other machine is also hundreds of Mbps.

I run speed test in web browser and the upload speed is 300Mbps. Wireshark shows just one tcp connection to the server during upload testing.

@jgmission
Copy link
Author

I deployed a netty server, then used the same ChatClient, the upload speed was 30Mbps.

Everything is the same except the websocket server.

@PhilipRoman
Copy link
Collaborator

Okay, that sounds pretty bad. I'll try to profile the library and see what I can find.

@dpingg
Copy link

dpingg commented Jun 10, 2021

@PhilipRoman did you find anything? I also encounter this issue.

@dpingg
Copy link

dpingg commented Jun 11, 2021

It turns out for the client -> server message, the data needs to be masked (XOR), so the upload performance is not as good as download performance.

@MouseKing1993
Copy link

Has the problem been solved now

@soylomass
Copy link

Any news about this?

@PhilipRoman
Copy link
Collaborator

I have reproduced the issue. Still investigating the root cause.
Some observations:
sending kilobyte-sized messages results in exactly one write(2) syscall with slightly more than 1000 bytes.
When the server receives the upload, read(2) returns relatively small chunks - about 1400 bytes.
However when the client receives the download, read(2) returns much more data - 16kb per read.
This should not be enough to cause the huge difference in speed but I'm still not sure yet.
Neither server nor client are cpu bound.
It also happens on localhost, although the effect is less extreme.

@marci4 marci4 added the Server label May 25, 2022
@marci4
Copy link
Collaborator

marci4 commented May 25, 2022

@PhilipRoman you are looking for something like

socket.setReceiveBufferSize(WebSocketImpl.RCVBUF);
?

@marci4
Copy link
Collaborator

marci4 commented Jul 4, 2022

@claraccio
Copy link

Hello, has there been any update on this problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants