-
-
Notifications
You must be signed in to change notification settings - Fork 613
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes #121.
- Loading branch information
Showing
5 changed files
with
73 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package torrent | ||
|
||
import ( | ||
"context" | ||
"io" | ||
"time" | ||
|
||
"golang.org/x/time/rate" | ||
) | ||
|
||
type rateLimitedReader struct { | ||
l *rate.Limiter | ||
r io.Reader | ||
} | ||
|
||
func (me rateLimitedReader) Read(b []byte) (n int, err error) { | ||
if err := me.l.WaitN(context.Background(), 1); err != nil { | ||
panic(err) | ||
} | ||
n, err = me.r.Read(b) | ||
if !me.l.ReserveN(time.Now(), n-1).OK() { | ||
panic(n - 1) | ||
} | ||
return | ||
} |
d4cbdc5
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.
@anacrolix Check rate limit when reading data from socket. This will not only affect reading
Piece
message, but also affect readingRequest
and other messages. I think it's not a good idea limiting read data from socket without distinguishing message.d4cbdc5
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.
I considered this, but realised the following:
Ultimately the user wants to limit bandwidth usage, not actual data rates. But by targeting data rates, they hope that processing and latency of control messages are optimal. Optimal control message flow occurs when control messages can be given priority over data messages, which currently does not occur. By rate limiting when Piece messages, instead of the entire message stream, the only improvement is to maybe read a handful of control messages that have been jammed between the current Piece, and the next, the improvement drowned out by the sheer size of data messages. The implementation is also much more complex.
Note however the situation is reversed with uploading, which is something we control. There we can improve the latency of control messages to the remote peer, by not filling our outbound queue too quickly, or somehow prioritizing the control messages without invalidating the order of the messages we send. We don't want to rate limit the entire upload stream there, as control messages have critical impact on future uploads and downloads.
Simplicity and performance are the highest goals here.