V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lsk569937453
V2EX  ›  程序员

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

  •  
  •   lsk569937453 · 2024-05-11 10:54:04 +08:00 · 13965 次点击
    这是一个创建于 371 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    103 条回复    2024-05-13 17:05:24 +08:00
    1  2  
    Karte
        1
    Karte  
       2024-05-11 10:57:15 +08:00   ❤️ 1
    1. 文件占用
    2. 内容覆盖
    Te11UA
        2
    Te11UA  
       2024-05-11 10:58:15 +08:00
    > 所以下载文件时,瓶颈是网络 IO 吧,操作文件 IO 的时间可以忽略不计了。所以是不是下载到一个文件中更优?

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

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

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

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

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

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

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

    话说回来到底啥软件会存碎片文件最后再合并
    lltlo
        18
    lltlo  
       2024-05-11 11:36:39 +08:00
    同一机器多线程下载没啥可玩的,有没有成熟的多机器同时下载同一个文件的工具?公司网络做了限制,每个终端有带宽有限,所以想用多台 pc 来下同一个文件的不同部分,最后合并起来,类似于分布式下载工具。
    github 上找了款 distributed-downloader ,有些小问题,自己改吧改吧,算是可以用,但是不太方便。
    augustheart
        19
    augustheart  
       2024-05-11 11:39:04 +08:00
    纯看写代码的怎么想。通常情况下,下到同一个文件中都是最优解。
    但是,在不知道最终文件多大但是又可以多线下载的时候(流媒体可能碰到),分块下载最后合并应该是一个相对稳妥的办法。
    MrKrabs
        20
    MrKrabs  
       2024-05-11 12:21:32 +08:00
    去问写程序的
    guanzhangzhang
        21
    guanzhangzhang  
       2024-05-11 13:15:19 +08:00   ❤️ 6
    因为好多人只管实现,不管细节地方
    多线程下载,他肯定会下意识想会有问题冲突占用问题,所以我多个文件合并就行了。
    而不是去想和搜搜看怎么多线程同时写一个文件互不影响。

    例如临时文件,很多人直接放/tmp 下,而不是使用 mktemp
    例如一个 daemon 进程,很多人和运维( ansible 部署 java 里)都是 nohub 启动,而不是写 systemd
    你指出来,他们就会💩叫”又不是不能用“
    huixia0010
        22
    huixia0010  
       2024-05-11 13:18:55 +08:00   ❤️ 1
    如果下载的是不清楚长度的流媒体直播流呢?
    nolog
        23
    nolog  
       2024-05-11 13:24:19 +08:00
    @guanzhangzhang #21 不懂就问,用 nohup 有什么不好的地方吗?
    Maerd
        24
    Maerd  
       2024-05-11 13:30:10 +08:00   ❤️ 1
    因为实现起来通常更简单,也更容易处理错误和恢复下载
    Ashe007
        25
    Ashe007  
       2024-05-11 13:30:10 +08:00 via iPhone
    说一个都没有关注的关键点:内存溢出,如果服务器剩余可用内存为 4 个 G ,文件为 5G 。拆分就是避免内存溢出的场景,因此大文件才需要分段上传/下载。
    如果文件是可预料的小,当然没必要拆分
    FranzKafka95
        26
    FranzKafka95  
       2024-05-11 13:33:52 +08:00
    @nolog nohub 当然没有 systemd 好,systemd 功能可高级多了
    Ashe007
        27
    Ashe007  
       2024-05-11 13:35:34 +08:00 via iPhone
    此外,还减轻了网络压力和内存压力,降低了系统负载
    monkeyWie
        28
    monkeyWie  
       2024-05-11 13:36:17 +08:00   ❤️ 2
    这个我作为 gopeed 下载的作者可以答一下,上面有 v 友其实也已经说的很对了,分多个临时文件下载再合并就是一种垃圾实现,没错就是说的 IDM ,预分配 + seek 写才是正确的高性能的对硬盘损耗最小的。
    aababc
        29
    aababc  
       2024-05-11 13:47:38 +08:00
    @guanzhangzhang 又学了点新知识,mktemp 这个还从来没用过
    cheng6563
        30
    cheng6563  
       2024-05-11 13:57:00 +08:00
    Windows 需要管理员权限才能预分配大文件空间吧。
    0312birdzhang
        31
    0312birdzhang  
       2024-05-11 14:03:29 +08:00
    完全可以,先根据 content-length 创建好文件大小,再分片写入(重写)就行了。同时写入一个文件和同时写入多个文件,对磁盘来说是一样的吧。
    guanzhangzhang
        32
    guanzhangzhang  
       2024-05-11 14:09:27 +08:00
    @nolog nohub 启动,进程意外退出就 g 了,systemd 有重试,cgroup ,前后顺序依赖,io 限制,条件启动,
    guanzhangzhang
        33
    guanzhangzhang  
       2024-05-11 14:10:12 +08:00
    @aababc 如果写单元测试,好多就是语言里库的 mktmp 啥的方法创建临时文件或者目录
    shuax
        34
    shuax  
       2024-05-11 14:13:25 +08:00   ❤️ 3
    也就只有 IDM 才这样吧。我再来个暴论,多线程也是不需要的,完全可以单线程实现多并发。
    lesismal
        35
    lesismal  
       2024-05-11 14:17:29 +08:00
    @kenvix
    如果写到多个文件, 每个文件可以自带上一个元信息, 即使任务中途失败导致下载器退出之类的, 以后还可以从上次下载的地方继续. 直接写入到目标文件, 没有这个元信息, 如果中途失败退出了, 下次只能从头来.
    对于大文件低带宽不稳定, 不能确保单次操作下载完的情况下, 直接写目标文件不划算;
    而即使是 10G 这种大文件, 本地多个分段文件做一次合并的开销和耗时也几乎可以忽略不计.

    另外, 分段下载如果对方响应的数据不是 trunked, 而是 content-length, 不同平台或许还可以利用 zero copy 优化避免先读取到内存再写入文件, 既减少应用层内存开销也提高速度, 多线程直接写入 queue 再写入目标文件的方式不好做这些. 不过这些本地 io 和只是读写 buffer 的内存开销本来也不大, 即使能做提升也不会太大.
    lisxour
        36
    lisxour  
       2024-05-11 14:25:33 +08:00
    省流版

    小文件分片:逻辑简单易实现,会多一点时间、性能消耗( 2024 年了,完全可以忽略)
    单文件:逻辑相对复杂点,要求对多线程 io 操作有一定了解,作为用户而言(我自己),没发现什么很明显的体验提升,迅雷、百度云就是单文件的,其实也就那样
    auroraccc
        37
    auroraccc  
       2024-05-11 14:36:33 +08:00
    是的,多文件合并还得花时间,不如直接把多个分片写到一个文件的不同 range 里
    lovezhangdada
        38
    lovezhangdada  
       2024-05-11 14:38:53 +08:00
    @monkeyWie
    老师,我想请教一下 aria2 和 gopeed 实现原理一样吗》?
    kenvix
        39
    kenvix  
       2024-05-11 15:09:38 +08:00   ❤️ 1
    @lesismal #35 关于续传,他没问我也就没说,实现上一般有一个 bitmap 控制文件写入情况,你说的所有问题用一个 bitmap 就能解决了。另外如果不想用 bitmap ,创建的时候指定文件类型为稀疏,然后直接询问系统哪些块是稀疏的,直接从稀疏块开始,也是可以的。
    kenvix
        40
    kenvix  
       2024-05-11 15:11:15 +08:00
    @Ashe007 #25 你直接把文件全量放到内存里?
    monkeyWie
        41
    monkeyWie  
       2024-05-11 15:18:41 +08:00
    @lovezhangdada 你指的是哪个实现原理?如果是指 http 下载的话基本是差不多,也就是我说的预分配 + seek 写,当然 aria2 是用的多线程 gopeed 用的多协程所以更省资源
    augustheart
        42
    augustheart  
       2024-05-11 15:23:50 +08:00
    @shuax 很难说。大部分情况下,多线程不会消失,只会转移。从调用者来看是单线程没啥问题
    monkeyWie
        43
    monkeyWie  
       2024-05-11 15:29:17 +08:00
    @shuax 这还真不是暴论,现代化的网络编程都是支持单线程高性能网络开发的(epoll 、eventloop 、协程)的,只能说现在载器还在用多线程技术的都是老古董
    AsAsSaSa
        44
    AsAsSaSa  
       2024-05-11 15:35:32 +08:00
    @huixia0010 直接持续追加就行,直播流只需要 1x 速度一般没多 TCP 链接的需求,而且你获取的基本一直是最末尾的数据,简单追加即可,真想多链接,每个 m4s 的请求带 content-length 就可以确定下一个分片该保存的开始位置。
    monkeyWie
        45
    monkeyWie  
       2024-05-11 15:36:21 +08:00
    @cheng6563 对的,但是不全对,windows 在没有管理员权限下也可以预分配只是比较慢,因为要做零填充,如果管理员模式就可以一瞬间分配好不管多大的容量
    Anarchy
        46
    Anarchy  
       2024-05-11 15:37:42 +08:00
    这个谈不上菜吧,这类代码很多场景只考虑带宽能不能跑满不在意文件 io 的,能快速写完代码就是最大优点了。
    augustheart
        47
    augustheart  
       2024-05-11 15:43:39 +08:00
    @monkeyWie 你分析的方向错了。下载软件是为了下载速度更快,而不是省资源。多线程下载是在历史中卷速度卷出来的。而在这个过程中,select 什么的东西从一开始就存在,这是 socket 编程的基础。
    TrembleBeforeMe
        48
    TrembleBeforeMe  
       2024-05-11 15:46:33 +08:00
    是的,所以我虽然买了 IDM 也不再使用了,改为用 imfile+aria2 下载辅助插件
    monkeyWie
        49
    monkeyWie  
       2024-05-11 15:48:47 +08:00
    @augustheart #47 有没有可能既省了资源,下载速度也没落下呢,新的编程技术出来就是为了解决历史的糟粕的,开 32 个线程并发下载 cpu 干冒烟了,然而开 256 个协程并发下载 cpu 表示毫无压力,并发数还高速度还更快
    augustheart
        50
    augustheart  
       2024-05-11 15:51:15 +08:00
    @monkeyWie 有没有可能 io 密集型的玩意开上 100 个 cpu 也谈笑风生呢?
    monkeyWie
        51
    monkeyWie  
       2024-05-11 15:56:23 +08:00
    @augustheart #50 那你有没有听说过 io 密集的时候并发高了一样能把 cpu 打挂,当然我这里指的是多线程+IO 这种古老的东西,然后如果你还要继续反驳的话就是你说的对
    augustheart
        52
    augustheart  
       2024-05-11 15:59:38 +08:00
    @monkeyWie 会的,当年万兆网卡直接把 cpu 干爆,然后?算了,我先来,你是对的
    Belmode
        53
    Belmode  
       2024-05-11 16:00:02 +08:00
    chrome 下载不就是写到一个.downloading 临时文件里的吗。
    yidinghe
        54
    yidinghe  
       2024-05-11 16:18:27 +08:00
    这类策略都是因为受到硬件环境限制而做出的。比如你可能觉得“下载文件时,瓶颈是网络 IO 吧”,其实对机械硬盘和 U 盘来说,瓶颈就在文件系统 IO 。

    所以对于多线程下载,一个应用采取何种策略,看作者愿意考虑多少场景。不要简单地看到就说作者菜。甚至还有的人会说“现在还要什么多线程下载”,这种人也是接触的场景比较少。当然我不知道你针对的是哪个应用,还是说你自己打算写一个。
    yidinghe
        55
    yidinghe  
       2024-05-11 16:19:06 +08:00
    @Belmode Chrome 是单线程
    Ashe007
        56
    Ashe007  
       2024-05-11 16:19:07 +08:00
    @kenvix 文件上传下载,应该是网络-->内存-->磁盘这一流程吧?我做上传的时候就是采用的分段上传,因此认为整个上传会导致其整个 size 占据内存空间
    kenvix
        57
    kenvix  
       2024-05-11 16:25:03 +08:00   ❤️ 1
    @Ashe007 #56 .......你要不学习下流的使用?
    kenvix
        58
    kenvix  
       2024-05-11 16:27:00 +08:00
    @Ashe007 #56 我看你似乎用 spring ,那也不应该像很多 php 用户不知道流的样子,常规的实现流式实现都只占用 buffer (例如 512KB )大小的内存
    augustheart
        59
    augustheart  
       2024-05-11 16:29:40 +08:00
    @yidinghe 我记得有多线程模式了(?)
    augustheart
        60
    augustheart  
       2024-05-11 16:30:38 +08:00
    @yidinghe 我不记得哪儿看帖有人说的。我个人很多年都是火狐了
    monkeyWie
        61
    monkeyWie  
       2024-05-11 16:33:28 +08:00
    @augustheart #60 是有的,但是要手动开起来,而且并不怎么好用
    lieh222
        62
    lieh222  
       2024-05-11 16:39:27 +08:00 via Android
    可能为了兼容各种文件系统,不确定目标目录挂载的 nfs ext 网盘之类文件系统可不可以这样操作文件
    0o0O0o0O0o
        63
    0o0O0o0O0o  
       2024-05-11 16:49:39 +08:00 via iPhone
    我想想怎么给它圆:可能有的 fs 不支持 seek ?
    Davic1
        64
    Davic1  
       2024-05-11 17:09:12 +08:00   ❤️ 1
    https://s3browser.com S3 broswer 从 AWS S3 上下载大文件,也是分成 N 个 100MB 的小东西下载,然后合并。
    silencelixing
        65
    silencelixing  
       2024-05-11 17:14:47 +08:00   ❤️ 1
    我觉得应该是数据一致性的问题:
    如果在下载过程中出现错误(例如网络中断),那么已经下载的部分可能会被破坏。如果所有数据都写入同一个文件,那么就需要重新下载整个文件。而如果数据被写入不同的文件,那么就只需要重新下载出现错误的那部分。

    简要描述:单文件下载,如果出错,那么出错的代价太大了;而分文件下载,可以减少这个代价。
    Ashe007
        66
    Ashe007  
       2024-05-11 17:33:04 +08:00
    @kenvix 感谢答疑,之前使用的是阿里的 oss 的依赖上传的文件,没有使用原生 Java 的流式上传
    wysnxzm
        67
    wysnxzm  
       2024-05-11 17:37:59 +08:00   ❤️ 2
    @Maerd #24 很多人都忽略或者有意识的跳过异常情况只考虑正常情况
    效率和安全在成本相同的情况下只能置换,不会凭空产生不会凭空消失
    augustheart
        68
    augustheart  
       2024-05-11 17:43:36 +08:00
    @silencelixing 单文件的设计在这个情况下一般都是带一个配置文件解决,比如迅雷和快车。
    yuzii
        69
    yuzii  
       2024-05-11 17:51:16 +08:00
    单文件会一次性申请较大的磁盘空间,下载暂停的时候多文件停下来不会占用太多磁盘空间
    我圆得如何
    LXGMAX
        70
    LXGMAX  
       2024-05-11 18:13:46 +08:00
    比特彗星不就是分段下进同一个文件
    msg7086
        71
    msg7086  
       2024-05-11 18:34:04 +08:00
    我就感叹一下没有见过网络蚂蚁和网际快车的年轻人。

    w568w
        72
    w568w  
       2024-05-11 18:47:14 +08:00 via Android   ❤️ 1
    @yuzii 现代文件系统基本都是懒分配:写多少用多少,并不是你申请 1GB 空间,硬盘上就会少 1GB 空间。

    所以还得再加个条件:远古的、不支持 prealloc 的文件系统。
    wangritian
        73
    wangritian  
       2024-05-11 18:59:33 +08:00
    别再线程了,全是 IO 任务
    nuffin
        74
    nuffin  
       2024-05-11 20:17:12 +08:00
    @0o0O0o0O0o 那还不如说他用的是磁带机 哈哈哈哈哈
    nuffin
        75
    nuffin  
       2024-05-11 20:20:43 +08:00
    @msg7086 自带一群蚂蚁咬木头的 BGM ,哈哈哈
    GrayXu
        76
    GrayXu  
       2024-05-11 20:35:43 +08:00
    @augustheart #68 这是正交的吧,多个小文件一样需要配置额外检错机制。主要是“如果所有数据都写入同一个文件,那么就需要重新下载整个文件” 这个论点就是错误的。
    GrayXu
        77
    GrayXu  
       2024-05-11 20:38:19 +08:00
    @ppllss #4 多线程就是分块下载的。。和几个文件并发没关系
    GrayXu
        78
    GrayXu  
       2024-05-11 20:39:35 +08:00
    @kenvix #5 你要不说我还真不知道哪个下载软件的逻辑是“分别下载到单独的文件然后再合并” 🤣🤣
    trzzzz
        79
    trzzzz  
       2024-05-11 21:27:08 +08:00
    用户用下载软件最终肯定是想看到 [一个] 文件,而不是多个小文件
    weeei
        80
    weeei  
       2024-05-11 21:32:41 +08:00
    主流的实现就是写在一个大文件里,为了避免频繁读写会使用内存缓存,缓存满了再写入磁盘,当然就赌不会丢数据了。
    trzzzz
        81
    trzzzz  
       2024-05-11 21:32:43 +08:00
    @Ashe007 试一下 [文件] -> [内存] -> [oss-sdk] 。你分段上传的 [源文件] 是分片好的吗,如果是已经切好片了你把 file 丢给 sdk 也没问题,它也会一点点传走
    mayli
        82
    mayli  
       2024-05-11 23:11:54 +08:00
    @kenvix 你以为这样的程序员是段子?他其实是认真的,就感觉没啥讨论下去的意义。
    mayli
        83
    mayli  
       2024-05-11 23:34:43 +08:00
    大部分程序员,可能对网络和文件系统接口都不熟。
    现代操作系统提供的网络基本上都不会出现传输错误,现代操作系统也都会提供 seek+随机写的功能。
    对于 preallocate 会有各种实现方式,不过提供的结果基本一致,也就是实现了随机写。另外,即使不依赖 seek ,也可以有 mmap 这样的方式实现随机写。
    再说从网络下载到磁盘,大部分操作系统也会提供 zero-copy 或者类似 pipe 的功能,即使没有,IO 操作时基本上也是使用一个固定 buffer ,比如 64k ,不会把全部内容放到内存再操作。
    再说一下状态恢复,类似数据库一样,分片的下载状态一般是单独存放,比如 aria 、flashget 或者迅雷,只有分片下载完成后再去更新状态,这样即使程序崩溃,也可以下次启动从恢复点续传。
    最后补充一个极端的例子,BT 下载每次传输单元是 16KB ,难不成要创建一堆 16KB 的文件,然后完成之后再合并?从文件系统的效率角度来说,从 socket 读并且单独写入一个大文件,这里可以只需要频繁调用 read(socket) + write(fd)。 但是如果是一堆小文件,你需要频繁创建和关闭文件,这两个操作在大部分操作系统,尤其是 HDD 上的文件系统,开销会非常大,你的顺序写操作会变成随机写,同时如果你的操作系统安装了杀毒软件,杀软也会在文件关闭时进行扫描,结果就是更慢了。

    一般程序员在软件设计和实现的时候,都会倾向于使用资源需求最小并且吞吐量高的方案。所以当小文件没有明显优势,而且特殊场景下资源开销和性能都有明显损耗的情况下,选择大文件是一个比较自然的方案。

    类似的需求还有比如数据库,就像如果网络客户端发送了一些 INSERT ,你是把他们写入小文件然后再合并呢,还是直接放到大文件中。这里的就会有和网络下载类似的权衡,当然也有不一样的地方。
    cybort
        84
    cybort  
       2024-05-12 02:23:49 +08:00 via Android
    不是所有文件系统都支持你预分配空间加稀疏存储的,你得前置写入一遍磁盘,给用户的感觉就是启动延迟。
    cybort
        85
    cybort  
       2024-05-12 02:27:38 +08:00 via Android
    那天找到一个远古的 bt 软件,就是下载成很多小块文件的。另外小水管时代每个小块下载都很慢,这样也方便单独做文件校验。
    msg7086
        86
    msg7086  
       2024-05-12 03:37:27 +08:00   ❤️ 1
    @w568w 你可能搞混了 preallocation 和 sparse file 。
    你说的写多少用多少是 sparse file ,而快速 allocation 是立即分配你申请的空间但不初始化成零。
    以前那种下载大文件要卡很久,不是因为申请空间慢,而是申请空间的时候需要清零所以慢。快速 alloc 本质上是跳过清零空间。(也意味着这种分配方式需要提权,因为跳过了清零,所以程序可以读到磁盘上原本他看不见的已删除数据。)

    为了减少文件碎片,肯定是一次性分配整个文件的空间更划算。
    lamquan
        87
    lamquan  
       2024-05-12 04:01:35 +08:00   ❤️ 1
    支持楼主,因为每次下载几十 G 的大文件,IDM 合并都慢死了,对磁盘读写消耗也大。
    guo4224
        88
    guo4224  
       2024-05-12 09:21:28 +08:00 via iPhone
    @huixia0010 这两种方式都不可以呀
    w568w
        89
    w568w  
       2024-05-12 10:56:01 +08:00 via Android
    @msg7086 谢谢提醒。你是对的,我确实弄混了。
    llsquaer
        90
    llsquaer  
       2024-05-12 11:18:37 +08:00
    @msg7086 我就觉得这个是当年的神器。不知为啥现在没了。不知道和 IDM 原理有区别么?都是分块下载
    msg7086
        91
    msg7086  
       2024-05-12 11:51:24 +08:00
    @llsquaer P2P 下载方式起来了以后这种就没什么用了。这些软件都是在 56k 网络的时候才有用,下一个文件要下几十分钟甚至几小时。现在网速是原来的一万倍,没意义了。
    msg7086
        92
    msg7086  
       2024-05-12 11:53:02 +08:00
    另外这软件还有自动拨号和下载完成自动挂断的功能,对拨号的用户实在是太友好了。
    IXTUS
        93
    IXTUS  
       2024-05-12 12:06:35 +08:00
    bt ?
    digimoon
        94
    digimoon  
       2024-05-12 12:12:03 +08:00
    没想到这么多年了 idm 还是那么菜
    pubby
        95
    pubby  
       2024-05-12 12:19:11 +08:00 via iPhone
    图省事吧,代码写起来简单,几个文件写入流,无脑 write 就行
    性能上没啥差别,尤其现在都用固态了
    jiezhi
        96
    jiezhi  
       2024-05-12 12:42:33 +08:00 via iPhone
    还一个除了本地文件系统是不是所有的文件系统单文件都支持多并发写入?
    我知道的 hdfs 是只支持追加和复写,不支持寻址写。
    trzzzz
        97
    trzzzz  
       2024-05-12 12:50:59 +08:00
    @jiezhi hdfs 复写也可以复写一段范围的数据吧
    wuxianliang
        98
    wuxianliang  
       2024-05-12 12:57:07 +08:00 via Android
    IDM 俗称单线程下载之王...
    Inn0Vat10n
        99
    Inn0Vat10n  
       2024-05-12 13:57:23 +08:00
    题外话,有些存储/driver 实现,并发读写多文件是要比并发读写单文件快的,比如英特尔的 AEP , 不过下载这个场景瓶颈大概率在网络 IO
    aeof
        100
    aeof  
       2024-05-12 20:49:22 +08:00   ❤️ 1
    编程小白,能帮忙看看实现有什么问题不: https://aeof.tech/posts/demo/multi-thread-downloader/
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2797 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 08:13 · PVG 16:13 · LAX 01:13 · JFK 04:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.