多线程分段下载文件时,为什么不下载到同一个大文件中?而是要分别下载到单独的文件然后再合并。

206 天前
 lsk569937453

https://gist.github.com/lsk569937453/e0496754cf3ebe740a33a7759516015e

我自己写了个 demo ,假设开 50 个线程下载,每个线程下载时间为 10s 钟,可以看到最后写入文件的时间才 1s 不到。

所以下载文件时,瓶颈是网络 IO 吧,操作文件 IO 的时间可以忽略不计了。所以是不是下载到一个文件中更优?

11598 次点击
所在节点    程序员
103 条回复
Karte
206 天前
1. 文件占用
2. 内容覆盖
Te11UA
206 天前
> 所以下载文件时,瓶颈是网络 IO 吧,操作文件 IO 的时间可以忽略不计了。所以是不是下载到一个文件中更优?

这一句话不是前后冲突吗
kenvix
206 天前
没有为什么,就是写代码的太菜,连 pre-allocate+seek 都不会
ppllss
206 天前
感觉是利用网速吧。很多时候 1 个文件下载就 100KB/s 那么要下载好久。分多个文件,每个文件 100KB/s 不是更快了?

为什么 1 个文件下载就 100KB/s 不清楚呀。带宽几百 M 下载一个文件我也没有跑满
kenvix
206 天前
实际上除了 IDM 主流下载器都是不需要合并的
huixia0010
206 天前
动动脑子啊,万一其中一片数据出问题要重下的时候,你一个文件里怎么搞?
kenvix
206 天前
@huixia0010 #6 动动脑子啊,你说的这种问题分多个文件就能解决?
jifengg
206 天前
首先,迅雷、FDM ,都是下载到同一个大文件里的。
这种方式,首先需要申请这个文件的空间,也就是你刚开始下载 10g 的文件,立刻就要在硬盘里创建 10g 的文件。
然后,写数据是一个持续的过程,多线程需要自己调度好文件占用的问题。你 demo 是等 10 秒后一次性写入。
分段需要处理临时文件,各有优劣,看自己更熟悉哪种方式了。
AceDogs
206 天前
文件分开可以解决更多普遍的问题,而且文件名是天生的索引信息,支持的功能更广泛。
单一文件在在特定情况下确实很好,比如知道文件总大小 等等。个人感觉好像单一文件的优势不是特别多。
结合一下也是一种方案, 用较小的缓冲区不断下载, 同时完成的数据合并入大文件中。实现方案各有优缺点。
yazinnnn0
206 天前
感觉下载到一个大文件没啥优势呢
tool2dx
206 天前
@ppllss http/tcp 单线程下载有两个大问题,一个是掉包,另一个是延迟。任何一个有问题,下载速度就会断崖式下跌。

当年 TCP 设计有问题,才会出现 BBR 那种内核补丁。
kenvix
206 天前
@jifengg #8 我以前做过多线程下载器,关于文件分配,直接向 OS 申请预分配一块存储空间就行了,预写入 10G 那是 HDD 时代老 Windows 的东西。关于线程调度,直接开个 BlockingQueue<<Index, ByteBuffer>>然后由专门的 Writer 负责写就行了,其他下载线程只需要负责把下到的 block(比如设定每个 block 为 512K)挂到 queue 上就完事

IDM 那种分文件下载再合并,对于大文件下载来说是不可接受的开销。除了菜逼我不知道还有什么理由会这样做
lsk569937453
206 天前
@yazinnnn0 省去了合并文件的时间以及删除临时文件的时间。代码上更简洁了。。。
lsk569937453
206 天前
@huixia0010 有一个分片出问题,那么重新下载这个分片,然后文件 seek 到指定的位置,重写那个分片就可以了。
Karte
206 天前
多线程多文件时是由下载线程写入到文件中. 如果是多线程单文件则是由单独的线程负责写入.

多线程多文件设计简单, 下载完直接写入. 最后由最后一个线程负责文件合并.

多线程单文件则是高阶写法, 需要控制写入的位置之类的.

别一口一个菜逼, 都是从菜鸟过来的. 只有适合的方案, 没有完美的设计.
mayli
206 天前
一般都是写到一个大文件吧,下载到单独文件,相当于 IO 两次,除了某些场景下,现在的 OS 对于这个没有特殊差别。
但是对于真的大文件,比如 10GB 以上的,你这种写两遍的操作会占用两倍的磁盘空间,而且对于 HDD ,一边读一边写会巨慢。
所以,这么做,单纯的是菜(不会 seek )。
IvanLi127
206 天前
只要有写文件的缓冲区,往一个大文件里写正常是更优解,毕竟事后合并文件的话磁盘 IO 还得吃一波。

话说回来到底啥软件会存碎片文件最后再合并
lltlo
206 天前
同一机器多线程下载没啥可玩的,有没有成熟的多机器同时下载同一个文件的工具?公司网络做了限制,每个终端有带宽有限,所以想用多台 pc 来下同一个文件的不同部分,最后合并起来,类似于分布式下载工具。
github 上找了款 distributed-downloader ,有些小问题,自己改吧改吧,算是可以用,但是不太方便。
augustheart
206 天前
纯看写代码的怎么想。通常情况下,下到同一个文件中都是最优解。
但是,在不知道最终文件多大但是又可以多线下载的时候(流媒体可能碰到),分块下载最后合并应该是一个相对稳妥的办法。
MrKrabs
206 天前
去问写程序的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1039715

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX