Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Match user's TCP sending speed  (Read 5683 times)

0 Members and 1 Guest are viewing this topic.

watarok

  • Newbie
  • *
  • Posts: 9
    • View Profile
Match user's TCP sending speed
« on: July 30, 2014, 04:11:36 am »
I wish to send some arbitrary amount of data across a TCP connection. I expect that there will be a problem wherein the size of the chunks of data will be too large or the frequency at which they're sent will be too great, resulting in a backup of data being sent.

For example (pseudo):
sf::TcpSocket socket;
// connect socket
while(!endOfData) {
    socket.send(/*a chunk of data*/);
    // get next chunk of data
}
 

Now if data is being queued for sending faster than the socket can actually send it off, there will be a backlog of data that hasn't really been sent. I therefore want to reduce the speed at which it is sent.

My solution:
sf::TcpSocket socket;
// connect socket
while(!endOfData) {
    sf::Socket::Status status = sf::Socket::NotReady;
    while(status == sf::Socket::NotReady) {
        status = socket.send(/*a chunk of data*/);
    }
    // get next chunk of data
}
 

This now tries to send the same data until the status returned isn't sf::Socket::NotReady. This seems like the logical solution, but I'm not sure that this is the actual status returned in this situation (when the socket's buffer isn't empty).

How can I regulate the sending speed of a TcpSocket to match the user's system? Furthermore, is it also possible/recommended to match the receiver's download speed as well?



PS: The examples above are not meant as actual implementations, but rather only serve to demonstrate the problem.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Match user's TCP sending speed
« Reply #1 on: July 30, 2014, 03:30:43 pm »
What are you trying to achieve? TCP already has flow control and congestion control through various built-in mechanisms. You don't need to worry about "sending too much data at once". You just send the data, and eventually it will reach the other end. TCP will always try to saturate the route from your host to the remote host. This means it will automatically choose the right throughput that matches the slowest link along that route.

Any application that has some form of a "speed limit" generally provides it so you can throttle the data transmission rate below the maximum that you would otherwise be capable of. If it is unset, or set to "unlimited" it will just transmit at maximum.

The fact that you can't queue up 10GB of data in a single call and wait for it to get sent has less to do with the protocol itself and more to do with the fact that operating system buffers aren't infinitely large. Even if you could buffer that much data, there might be other reasons why a call might block (NotReady is the same as "would block"), so assuming that it blocks because you sent too much in one go is also incorrect. In general, the operating system and underlying network will provide a best effort service, with no guarantees.

If your issue is that you don't want to have to store the data to be sent while waiting for the buffers to empty, then I have to tell you that you are out of luck. Most of the time when transferring large blocks of data, they are either read from disk or kept in memory as long as the transfer is active. If it is generated on the fly, you can throttle generation based on whether your own buffer (not the operating system buffer) has space to accommodate new data or not. Either way, you will have to provide data whenever the operating system is able to accept new data.

Trying to calibrate your send calls to the network bandwidth is not a good idea, especially since it can fluctuate quite rapidly in some scenarios, and result in constant recalibration which doesn't result in any benefit whatsoever. Just keep trying to send whenever you can and don't worry about the throughput.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Match user's TCP sending speed
« Reply #2 on: July 30, 2014, 04:16:41 pm »
Quote
Either way, you will have to provide data whenever the operating system is able to accept new data.
I think that's what he wants, being "notified" whenever he can send more data to the socket. And I'm pretty curious too to know whether this is possible with the current SFML API.
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Match user's TCP sending speed
« Reply #3 on: July 30, 2014, 04:25:34 pm »
Well... that is more or less the idea of I/O Completion Ports on Windows... although in the end they function exactly the same way as kqueue or epoll on UNIX-based systems. You will always have to poll for completion of the operation, the difference is what and how you poll. I'm pretty sure that there is no callback mechanism for this as that would have a huge impact on performance (having to switch from kernel to user mode etc.) and the existing facilities are already fast enough. Ironically... periodically checking over and over again is faster than being told once when the operation is completed, but that's just the way it is.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Match user's TCP sending speed
« Reply #4 on: July 30, 2014, 07:47:02 pm »
So there's nothing he can do with SFML, right?
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Match user's TCP sending speed
« Reply #5 on: July 30, 2014, 09:02:16 pm »
There's nothing he can do in general... not only with SFML :P.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Match user's TCP sending speed
« Reply #6 on: July 30, 2014, 11:04:32 pm »
With the OS specific functions you mentioned, he could at least know when the OS is ready to accept more data.
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Match user's TCP sending speed
« Reply #7 on: July 30, 2014, 11:25:24 pm »
Just like what sf::SocketSelector does? ;D There really is nothing better that I know of than some form of polling, and SFML uses the most basic one, but the rest are just the same.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Match user's TCP sending speed
« Reply #8 on: July 31, 2014, 08:00:10 am »
Quote
Just like what sf::SocketSelector does?
...for reading, not writing. sf::SocketSelector doesn't use the "write" FD_SET in select.
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Match user's TCP sending speed
« Reply #9 on: July 31, 2014, 10:04:03 am »
Hmm... right. I forgot that sf::SocketSelector only checks for reading. I guess checking for writing would be useful as well for cases like this.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Match user's TCP sending speed
« Reply #10 on: July 31, 2014, 11:06:53 am »
Yes, we could think about adapting sf::SocketSelector accordingly. We'd have to slightly modify the API, so that the caller can know whether the socket is ready for reading or writing (like an additional argument to ready()).
Laurent Gomila - SFML developer

watarok

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Match user's TCP sending speed
« Reply #11 on: August 01, 2014, 02:11:42 am »
There's nothing he can do in general... not only with SFML :P.
Hmm, that's unfortunate. I suppose I could just implement a modest limit and hope it works on most systems. Or leave it to be user-defined.

Yes, we could think about adapting sf::SocketSelector accordingly...
Well, I'm glad I was able to do my bit for SFML's (potential) development. :)

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Match user's TCP sending speed
« Reply #12 on: August 01, 2014, 02:37:48 am »
Hmm, that's unfortunate. I suppose I could just implement a modest limit and hope it works on most systems. Or leave it to be user-defined.
The whole point of this thread was to explain that such a limit is pointless unless it serves to help the user save throughput for other purposes. Enforcing exactly the same limit on different systems therefore makes little to no sense, since not everybody will have the same throughput available for use anyway, and every user will have their reasons for wanting to limit it or not.

In the dark ages of throttling, users would often rely on third-party applications to artificially fake congestion to the application every time it would go over the limit, thus causing it to lower it's throughput and gradually make its way back to the limit. This was not ideal because it causes some mechanisms built into TCP to not function optimally and doesn't even work for UDP, since it has no flow or congestion control built into it. Application developers started to realize that users might not want to transfer at full speed any more, since nowadays you would have enough to perform multiple tasks simultaneously and without a sophisticated form of QoS, bulk data transfers would just interfere with interactive applications. Back during the 56K and ISDN days, nobody would ever think of performing multiple internet related tasks at the same time. You would start a download and come back hours later and hope it completed successfully.

What you must understand is that limiting the data transfer rate is done as a convenience for the user. Building your application on the basis of a fixed transfer rate is not a good idea and will probably not function as expected on some systems. You have to assume that by default, the user would want to transfer at maximum speed and write your code to accommodate for that. As such, as I already mentioned earlier, providing this feature is something left for later. You should focus on actually transferring the data efficiently first, regardless of at what speed.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

watarok

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Match user's TCP sending speed
« Reply #13 on: August 02, 2014, 07:22:24 am »
The whole point of this thread was to explain that such a limit is pointless...
Actually the point was to avoid overflowing the user's socket buffer with data. :P

What you must understand is that limiting the data transfer rate is done as a convenience for the user.
It was my plan to implement this to avoid taking over the user's bandwidth. But you're right that this is not a critical feature. I should focus instead on sending data in the first place. :-\

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Match user's TCP sending speed
« Reply #14 on: August 02, 2014, 03:24:55 pm »
The whole point of this thread was to explain that such a limit is pointless...
Actually the point was to avoid overflowing the user's socket buffer with data. :P
Generally, that's not something you need to worry about.