每3秒测量一次吞吐量,增幅超过15%才允许增加一个连接——这是我为下载管理器设计的自适应探测机制,也是1.3版本中我最引以为傲的部分。但就是这个从不报错、看似负责的算法,却让每一次下载都在无形中损失了本可榨取的速度。最终,我亲手删掉了它。
问题出在探测逻辑对“没有提升”的单一解读上。在一台100Mbps宽带下从快速CDN拉取文件时,4个连接就能轻松跑满带宽。当第5个连接建立后,吞吐量不再出现可测量的增长——不是因为服务器拒绝,而是本地链路已经没油水可挖。探测程序读出一条平直的曲线,就断定当前连接数的天花板是4,并永远停止爬升。
![]()
真正的致命伤在于这之后的沉默。如果随后有另一个下载结束、网络重新连接或者其他进程释放了带宽,链路明明空出了余量,可那个早已停下来的探测循环不会再知道。它永久地返回一个偏小的数字,每个后续下载都只能以4连接起步,却又表现得一切“正常”。这种失败没有错误日志,也没有性能警告——它只是安静地让你每次都比该有的速度慢一截。
新版设计抛弃了爬坡探测。现在下载启动时立刻打开全部有效线程,每个线程发出SYN的间隔错开100毫秒,避免触发中间盒的滥用保护。爬坡没了,探针也没了。退避机制仍然保留,但改由正向信号驱动,而不再依赖“什么都没有”的反馈。降级策略会在三种情况下将工作线程数减半:连续失败次数达到阈值,或者一个主机同时出现多个失败线程——最关键的是最后一条,它能区分服务器刻意拒绝部分连接,还是本机WiFi断开导致全体一并失败。
如果不加上这个区分条件,一次3秒的网络闪断就会在后台静默地为那个无辜的服务器写死一个人数上限。而现在,学习到的上限有效期只有7天,也能从设置页手动清除,哪怕在中断期间误学了上限,也会自行恢复。说到底,我把这件事又学了一遍:一个控制回路如果把“我什么都没测到”等同于“什么都没有”,那么它永远会趋向做得更少。当你的唯一反馈信号是现象缺失时,你根本就没有反馈。
收尾时还顺手解决了一个关联问题。之前MacGet会把支持分段下载的文件切成比工作线程数更多的片段(每段目标8MB,最多256个片段),这样完成某个片段的线程能抢下一个待处理的片段,而不是空等。但当所有片段都分配完毕,释放出来的线程就无事可抢,整个下载只得被拖在最后那个最慢的片段上。现在,如果无片可抢,空闲线程就会把当前还在下载中的最大片段一分为二,取走后半段——这基本就是把BitTorrent的终局模式搬到了HTTP分段上。分割下限设为1MB,免得为了几十KB的碎片又搭上一次TCP握手和HTTP往返。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.