我正在制作一个程序,可以下载一堆不同的项目。我的语言具有廉价的并发性,所以我首先想到我可以一次下载它们。问题是using concurrency you don't have is bad。如果我尝试一次性下载它们,用户必须等到所有这些之后才能获得它们。
假设您正在下载10个可以以7 mb / s的速度下载的项目,并且您的下载速度为20 mb / s。程序应该开始只下载第一个三个项目,并且只有在旧项目完成并且有带宽时才开始下载新项目。另请注意,一般情况下,项目的下载速度不同。
如果我有一些编程方式来检查网络饱和度,这很容易(只需检查它是否在产生新线程之前已经饱和。)
答案 0 :(得分:1)
正如评论中指出的那样,你做得不够好,无法做出任何保证。但是,假设你想要尽力而为。
这个问题分为两部分:
通过限制从套接字读取的速率,可以在用户空间程序中大致控制所消耗的带宽。 TCP / IP堆栈将通知连接的另一端,该队列正在维护您的应用程序已满,并且将不再发送任何其他内容。实现该速率限制的便捷方式是使用token buckets。
快速令牌桶实施:
int bucket = 0;
start_thread({ while(transfer_in_progress) {
bucket += bytes_per_second_limit;
sleep(1);
});
while(transfer_in_progress) {
bytesread = read(socket, buffer, min(bucket, buffersize), );
bucket -= bytesread;
}
如果bytes_per_second_limit
大致设置为可用带宽(以字节/秒表示),则应该以连接允许的速度读取。如果连接速度更快,您将被限制为bytes_per_second_limit
。如果连接较慢,那么bucket
将永远增长,速度与速度限制和可用带宽之间的差异成比例。
哼!
如果您运行另一个主题,并密切注意bucket
,您可以注意两个条件:
bucket
始终为0,则可用带宽更多,您可以增加bytes_per_second_limit
,可能会受到您最近对可用带宽的最佳猜测(来自#2)的限制。或者开始额外下载。bucket
大于您上次查看的时间,并且数据点的最后几秒显示为持续增长(可能是线性回归;无论您喜欢什么),那么增长率表示为字节/秒是为了使您的下载速率与可用带宽相匹配,您可以减少多少bytes_per_second_limit
。所有这一切的问题在于无法保证您的带宽保持不变。线程监控bucket
可能会在提高速率和限制速率之间来回反弹。我建议您在进行速率限制更改之前,先平均至少10或20秒。