我应该使用Python或Assembly进行超快速复制程序

时间:2010-06-06 01:54:06

标签: python assembly

作为一个维护问题,我需要定期(每年3-5次)复制一个存储库,该存储库现在有超过2000万个文件,总磁盘空间超过1.5TB。我目前正在使用RICHCOPY,但已尝试过其他人。 RICHCOPY似乎是最快的,但我不相信我接近我的XP机器能力的极限。

我正在使用我在汇编语言艺术中所读到的内容编写程序来复制我的文件。我的另一个想法是开始学习如何在Python中使用多线程来复制。

我正在考虑在大会中这样做的想法,因为它看起来很有趣,但是虽然我的时间并不是非常珍贵但是我想要了解我是否会看到足够的收益是非常宝贵的在复制速度。我假设我会,但我开始真正学习编程18个月,它仍然或多或少是一个爱好。因此,我可能会遗漏一些解释性语言发生的基本概念。

任何观察或经验都将受到赞赏。请注意,我不是在寻找任何代码。我已经在Python 2.6中编写了一个基本的复制程序,它不比RICHCOPY慢。我正在寻找一些能让我更快速的观察。现在,我花了50多个小时从磁盘复制到Drobo,然后从Drobo复制到磁盘。我有一个LogicCube,当我只是复制磁盘但有时我需要从磁盘转到Drobo或反过来。我想,鉴于我可以在七小时内使用LogicCube扇形复制一个3/4满2 TB的驱动器,我应该能够使用Assembly接近它,但我不知道这是否有效。 (是的,有时无知是幸福)

我需要加快速度的原因是我有两到三个周期,在复制过程中发生了一些事情(五十小时是很长一段时间,期望世界保持不动),这导致我不得不抄袭副本并重新开始。例如,上周,水管在我们的建筑物下面断裂并缩短了电力。

感谢早期回复,但我不认为这是I / O限制。我没有通过网络,驱动器插入我的母板与sata连接,我的Drobo插入Firewire端口,我的想法是两个连接应该允许更快的传输。

实际上我不能使用扇区副本,除了从单个磁盘到Drobo。由于Drobo文件结构很神秘,因此它无法正常工作。我不科学的观察是,从一个内部磁盘到另一个磁盘的复制并不比从Drobo到内部磁盘的复制速度快。

我受硬件约束,我买不起10K转2TB的驱动器(如果他们甚至制造它们)。

您建议使用文件同步解决方案。但这并不能解决我的问题。首先,我玩的文件同步解决方案首先构建了一个地图(为了更好的术语),我有太多的小文件,所以他们窒息。我使用RICHCOPY的原因之一是它立即开始复制,它不使用内存来构建地图。其次,几周前我的三个Drobo备份中有一个失败了。我的规则是,如果我有备份失败,其他两个必须保持离线,直到新的建立。因此,我需要从我使用LogicCube的三个备份单驱动器副本中复制一个。

在一天结束时,我必须在一个驱动器上有一个好的副本,因为这是我提供给我的客户。因为我的客户有各种各样的系统,我在SATA驱动器上交付给他们。

我从某人那里租了一些云空间,我的数据也存储在最深的备份中,但是如果离开那里就很贵。

13 个答案:

答案 0 :(得分:43)

复制文件是一个I / O绑定过程。你不太可能看到在程序集中重写它有任何加速,甚至多线程也可能只会导致事情变慢,因为同时请求不同文件的不同线程将导致更多的磁盘搜索。

使用标准工具可能是最好的方法。如果有任何要优化的内容,您可能需要考虑更改文件系统或硬件。

答案 1 :(得分:8)

减速有两个地方:

  • 每个文件的副本比磁盘副本慢很多(你可以克隆100%的每个扇区的数据)。特别适用于20mm文件。除非您从克隆文件切换到克隆原始磁盘数据,否则无法使用调整最多的程序集修复该程序集。在后一种情况下,是的,大会确实是你的票(或C)

  • 简单地存储20mm文件并递归查找它们在Python中可能效率较低。但这更有可能是找到更好的算法的功能,并且不可能通过汇编显着改进。另外,这不会是50小时的主要贡献者

总结 - 如果您进行原始磁盘扇区复制,程序集将有所帮助,但如果您进行文件系统级复制则无效。

答案 2 :(得分:8)

正如其他答案所提到的(+1标记),在复制文件时,磁盘i / o是瓶颈。你使用的语言不会产生太大的影响。你如何布置你的文件将有所作为,你如何传输数据将有所作为。

你提到过复制到DROBO。你的DROBO是如何连接的?看看这个graph of connection speeds

让我们看一下您可以通过某些线路类型获得的最大复制率:

  • USB = 97天(1.5 TB / 1.5 Mbps)。 Lame,至少你的表现不是这个坏。
  • USB2.0 = ~7小时(1.5 TB / 480 Mbps)。也许是LogicCube?
  • 快速SCSI = ~40小时(1.5 TB / 80 Mbps)。也许你的硬盘速度快?
  • 100 Mbps以太网= 1.4天(1.5 TB / 100 Mbps)。

因此,根据您的问题的限制,您可能无法做得更好。但您可能希望开始执行原始磁盘复制(如Unix's dd),这应该比文件系统级复制快得多(它更快,因为没有随机磁盘寻找目录遍历或碎片文件)。

要使用dd,您可以将Linux启动到您的计算机上(或者使用cygwin?)。请参阅this page for referencethis one about backing up from windows using a live-boot of Ubuntu

如果要在RAID上组织1.5 TB数据,可能会加快复制速度(因为磁盘将并行读取),并且(取决于配置)它将具有保护您免受驱动器故障的好处。

答案 3 :(得分:5)

我不认为在汇编中写它会帮助你。如果您受处理器约束并且认为您可以做比编译器更聪明的事情,那么在汇编中编写例程可以帮助您。但是在网络副本中,你将受到IO约束,所以在这里或那里刮一个循环几乎肯定不会有所作为。

我认为这里的真实规则是,在考虑优化之前,最好先了解您的流程以了解您在哪些方面花费时间。

答案 4 :(得分:4)

我不相信它会使您使用哪种语言可辨别出来。这里的瓶颈不是你的应用程序,而是磁盘性能。

仅仅因为语言被解释,并不意味着其中的每一个操作都很慢。举个例子,可以肯定的是,Python中的低级代码会调用汇编(或编译)代码进行复制。

类似地,当您使用Java编写集合和其他库时,主要是编译C,而不是解释Java。

您可以做一些事情来可能加快这个过程。

  • 购买速度更快的硬盘(10K RPM,而不是7.5K或更短的延迟,更大的缓存等)。
  • 在两个物理磁盘之间复制可能比在单个磁盘上复制(由于磁头移动)更快。
  • 如果您正在通过网络进行复制,请暂存它。换句话说,将其快速复制到另一个本地磁盘,然后通过网络从那里缓慢。
  • 您也可以以不同的方式进行演出。如果你每晚(或甚至每周)运行一次以使副本保持最新(仅复制已更改的文件)而不是一年三次,那么你将不会发现自己需要复制大量数据。< / LI>
  • 此外,如果您正在使用网络,请在存储库所在的框中运行它。您不希望将所有数据从远程磁盘复制到另一台PC,然后再返回另一个远程磁盘。

您可能还需要小心使用Python。我可能会弄错(毫无疑问,如果我误解了这个数字,Pythonistas会让我直截了当)但我有一个模糊的回忆,它的线程可能无法充分利用多核CPU。在这种情况下,您最好使用另一种解决方案。

您最好坚持使用当前的解决方案。我怀疑一个专门的复制程序已经尽可能地优化,因为这是他们做的

答案 5 :(得分:2)

没有理由在汇编中编写复制程序。问题在于涉及的IO数量不是CPU。此外,python中的复制功能已由专家用C语言编写,你不会在汇编程序中自行编写更快的速度。

最后,线程也无济于事,尤其是在python中。继续使用Twisted或者只使用Python 2.6中的新multiprocessing module并启动一个进程池来执行复制。完成工作后,为自己省去了很多折磨。

答案 6 :(得分:2)

在对复制应用程序提出质疑之前,您很可能会质疑数据路径。什么是理论上的限制,你取得了什么成果?有哪些潜在的瓶颈?如果存在单个数据路径,则可能无法通过并行化存储任务来获得显着提升。你甚至可能会加剧它。异步I / O带来的大部分好处都来自块级 - 低于文件系统的级别。

您可以做的一件事就是提升I / O,从源和存储到目标部分取消。假设源和目标是单独的实体,您可以理论上将该过程的时间减半。但标准工具是否已经在做这个?

哦 - 在Python和GIL上 - 通过I / O绑定执行,GIL真的不是那么糟糕的惩罚。

答案 7 :(得分:2)

RICHCOPY已经在并行复制文件了,我希望唯一的方法就是与文件系统上床,以便最大限度地减少磁盘I / O ,特别是寻求。我建议您尝试ntfsclone,看看它是否符合您的需求。如果没有,我的下一个建议就是平行ntfsclone

在任何情况下,直接使用磁盘上的文件系统布局在C中最简单,而不是Python,当然也不是汇编。特别是因为您可以使用NTFS 3G项目中的C代码开始使用。此代码旨在实现可靠性和易移植性,而非性能,但它仍然可能是最简单的入门方式。

  

我的时间非常宝贵,以至于我想知道我是否会在复印速度上看到足够的收益。

没有。或者更准确地说,在您目前掌握的系统编程水平上,实现显着的速度改进将非常昂贵。您要求的是非常专业的专业知识。虽然我自己有实现文件系统的经验(比NTFS,XFS或ext2简单得多),但我不会解决这个问题。我会雇用它。


脚注:如果您有权访问Linux机器,请找出可以获取目标驱动器的原始写入带宽:

time dd if=/dev/zero of=/dev/sdc bs=1024k count=100

将为您提供以最快的方式顺序写入100MB的时间。这将为您提供硬件可能性的绝对限制。 如果不了解dd的手册页,请不要尝试此操作! dd代表“销毁数据”。 (实际上它代表“复制和转换”,但cc已被采用。)

Windows程序员可能会指向Windows的等效测试。

答案 8 :(得分:1)

是的,这里的瓶颈不在于复制软件本身的执行,而在于磁盘访问。

降低等级并不意味着你会有更好的表现。举一个open()和fopen()API的简单例子,其中open更低级别更直接,fopen()是系统open()函数的库包装。

但实际上fopen具有更好的性能,因为它增加了缓冲并优化了许多原始open()函数中没有完成的东西。

在汇编级别实现优化比在python中实现更加困难和效率低。

答案 9 :(得分:1)

在大约50小时内,1.5 TB的吞吐量为(1,5 * 1024 ^ 2)MB /(50 * 60 ^ 2)s = 8,7 MB / s。理论上100 mbit / s的带宽应该可以达到12,5 MB / s。在我看来,你的火线连接是一个问题。您应该查看升级驱动程序,或升级到更好的firewire / esata / usb界面。

那就是说,你应该考虑获取文件同步解决方案,而不是python /汇编问题。不必一次又一次地复制数据。

答案 10 :(得分:0)

正如已经说过的,这里不是用来发挥作用的语言;对于计算来说,组件可以很酷或很快,但是当处理器必须“说话”到外围设备时,这些限制就是这样的。在这种情况下,速度是由您的硬盘速度给出的,这是一个限制,您几乎不能更改您的高清并等待将来更好的高清,但也可以通过数据在磁盘上组织的方式,即通过文件系统。 AFAIK,大多数使用过的文件系统都没有经过优化,无法快速处理大量“小”文件,而是针对“少量”大文件进行了优化。

因此,更改您正在使用的文件系统可以提高复制速度,只要它更适合您的情况(当然高清限制仍适用!)。如果你想“品尝”你的高清真实限制,你应该尝试一个“逐个扇区”的副本,将你的源高清的确切图像回复给dest高清。 (但是这个选项有一些要注意的地方)

答案 11 :(得分:0)

因为我发布了一些问题,所以我一直在讨论一些问题,我首先想到的是,不要争论,但那些发布了我不受约束的回复的人只是部分正确。寻求时间是约束。长期以来测试各种选项我用I-7处理器和功能相当强大/功能的主板构建了一台新机器,然后使用了我正在使用的相同的两个驱动器,之后我注意到速度相当显着的增加。我还注意到,当我移动大文件(一千兆字节左右)时,我会获得超过50 mb / s的持续传输速度,并且在移动小文件时速度会显着下降。我认为速度差异是由于无序磁盘相对于复制程序读取目录结构以确定要复制的文件的方式。

我认为需要做的是 1:读取MFT并按扇区从外部到内部进行分类    (这意味着我必须弄清楚多盘磁盘是如何工作的) 2:分析并分离所有连续文件和非连续文件。我会处理    首先是连续文件,然后返回处理非连续文件 3:开始从外到内复制连续文件 4.完成复制非连续文件后,默认情况下它们最终会在内部复制    盘子的环和它们将是连续的。 (我想说明的是    经常进行碎片整理并且我的文件/目录中只有不到1%是碎片化的但是    2000万的1%仍然是200K

为什么这比运行复制程序更好。

  1. 运行复制程序时,程序将使用一些内部排序机制来确定复制顺序。 Windows使用字母(或多或少)我想其他人做类似的事情,但订单可能 - 不是(在我的情况下可能不是)符合文件最初放在磁盘上的方式,这是我最重要的因素影响复制速度。

  2. 扇区复制的问题是它没有修复任何东西,因此当我跨磁盘大小迁移并添加数据时,我最终会遇到新问题。

  3. 如果我这样做,我应该能够检查文件头和eof记录并做一些内务处理。 CHKDSK是一个伟大的计划,但有点愚蠢。当我确实得到文件/文件夹损坏时,很难确定丢失的内容,通过构建我自己的复制程序,我可以包含一个维护周期,当我想在复制期间对文件运行一些测试时,我可以调用它。这可能会减慢它的速度,但我并不是很想,因为CPU会比移动或写入文件更快地移动文件。即使它在运行时减慢一些,至少我得到一些控制(也许理解是 在一个不完美的世界中总会出现问题的更好的词。

  4. 我可能不必在A中这样做,我一直在四处寻找播放(阅读)MFT的方法,甚至还有Python工具,请参阅http://www.integriography.com

答案 12 :(得分:0)

都不是。如果要利用OS功能来加速I / O,则需要使用一些最容易在C(或C ++)中访问的专用系统调用。你不需要知道很多C来编写这样的程序,但你真的需要知道系统调用接口。

很可能,您可以通过使用现有工具或调整操作系统来编写任何代码来解决问题,但如果您确实需要编写工具,则C是最直接的方法。