- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我一直在努力寻找最快的方法来编写文件复制例程,以将大文件复制到 RAID 5 硬件上。
平均文件大小约为 2 GB。
有 2 个窗口框(都运行 win2k3)。第一个框是源,大文件所在的位置。第二个盒子有一个 RAID 5 存储。
http://blogs.technet.com/askperf/archive/2007/05/08/slow-large-file-copy-issues.aspx
上面的链接清楚地解释了为什么 windows copy、robocopy 和其他常见的复制实用程序会降低写入性能。因此,我编写了一个 C/C++ 程序,它使用带有 NO_BUFFERING
和 WRITE_THROUGH
标志的 CreateFile、ReadFile 和 WriteFile API。该程序模拟ESEUTIL.exe,从某种意义上说,它使用2个线程,一个读一个写。读取器线程从源读取 256 KB 并填充缓冲区。一旦填充了 16 个这样的 256 KB block ,写入器线程就将缓冲区中的内容写入目标文件。如您所见,写入线程一次性写入 8MB 的数据。该程序分配了 32 个这样的 8MB block ...因此,写入和读取可以并行进行。ESEUtil.exe 的详细信息可以在上面的链接中找到。注意:我正在处理使用 NO_BUFFERING
时的数据对齐问题。
我使用了 ATTO 等基准测试实用程序,发现我们的 RAID 5 硬件在写入 8MB 数据 block 时的写入速度为每秒 44MB。这大约是每分钟 2.57 GB。
但我的程序每分钟只能达到 1.4 GB。
谁能帮我确定问题出在哪里?是否有比 CreateFile
、ReadFile
、WriteFile
更快的 API 可用?
最佳答案
您应该使用异步 IO 以获得最佳性能。即使用 FILE_FLAG_OVERLAPPED
打开文件并使用 WriteFile 的 LPOVERLAPPED
参数。使用 FILE_FLAG_NO_BUFFERING
可能会也可能不会获得更好的性能。你必须测试才能看到。
FILE_FLAG_NO_BUFFERING
通常会为您提供更一致的速度和更好的流式传输行为,并且它可以避免您可能不再需要的数据污染您的磁盘缓存,但总体而言不一定更快。
您还应该测试每个 IO block 的最佳大小。根据我的经验,一次复制 4k 文件和一次复制 1Mb 文件之间存在巨大的性能差异。
在我过去(几年前)对此进行的测试中,我发现低于 64kB 的 block 大小主要由开销决定,并且总吞吐量继续提高, block 大小增加到大约 512KB。如果对于今天的驱动器,您需要使用大于 1MB 的 block 大小来获得最大吞吐量,我不会感到惊讶。
您当前使用的数字似乎是合理的,但可能不是最佳的。此外,我相当确定 FILE_FLAG_WRITE_THROUGH 会阻止使用磁盘缓存,因此会降低您的性能。
您还需要注意,使用 CreateFile/WriteFile 复制文件不会复制元数据,例如时间戳或 NTFS 上的备用数据流。您将不得不自己处理这些事情。
实际上用您自己的代码替换 CopyFile
是一项相当多的工作。
附录:
我应该提一下,当我在 WindowsNT 3.0 上使用软件 Raid 0 尝试这个时(大约 10 年前)。速度对缓冲区内存中的对齐非常敏感。事实证明,当时 SCSI 驱动程序必须使用一种特殊的算法来从分散/聚集列表中执行 DMA,而 DMA 超过 16 个物理内存区域 (64Kb)。为了获得保证的最佳性能,需要物理上连续的分配——这是只有驱动程序才能请求的东西。这基本上是当时流行芯片组的 DMA Controller 中的一个错误的解决方法,不太可能仍然是一个问题。
但是 - 我仍然强烈建议您测试从 32kb 到 32Mb 的 2 block 大小的所有幂,看看哪个更快。您可能会考虑进行测试,看看某些缓冲区是否始终比其他缓冲区更快 - 这并非闻所未闻。
关于c++ - 提高高速文件复制的写入速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2025694/
我有这个代码 var myChart = new FusionCharts("../themes/clean/charts/hbullet.swf", "myChartId", "400", "75
既然写入是立即进行的(复制到内核缓冲区并返回),那么使用 io_submit 进行写入有什么好处? 事实上,它 (aio/io_submit) 看起来更糟,因为您必须在堆上分配写入缓冲区并且不能使用基
我正在使用 mootool 的 Request.JSON 从 Twitter 检索推文。收到它后,我将写入目标 div 的 .innerHTML 属性。当我在本地将其作为文件进行测试时,即 file:
最终,我想将 Vertica DB 中的数据抓取到 Spark 中,训练机器学习模型,进行预测,并将这些预测存储到另一个 Vertica DB 中。 当前的问题是确定流程最后部分的瓶颈:将 Spark
我使用 WEKA 库编写了一个 Java 程序, 训练分类算法 使用经过训练的算法对未标记的数据集运行预测 将结果写入 .csv 文件 问题在于它当前写出离散分类结果(即算法猜测一行属于哪个类别)。我
背景 - 我正在考虑使用 clickonce 通过 clickonce(通过网站)部署 WinForms 应用程序。相对简单的应用程序的要素是: - 它是一个可执行文件和一个数据库文件(sqlite)
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
我正在读取 JSON 文件,取出值并进行一些更改。 基本上我向数组添加了一些值。之后我想将其写回到文件中。当我将 JSONArray 写回文件时,会被写入字符串而不是 JSONArray 对象。怎样才
我为两个应用程序使用嵌入式数据库,其中一个是服务器,另一个是客户端。客户端应用程序。可以向服务器端发送获取数据请求以检索数据并显示在表格(或其他)中。问题是这样的:如何将获取的数据保存(写入)到页面文
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
从问题得出问题:找到所有 result = new ArrayList(); for (int i = 2; i >(i%8) & 0x1) == 0) { result.add(i
由于某种原因,它没有写入 CSV。谁能明白为什么它不写吗? def main(): list_of_emails = read_email_csv() #read input file, cr
关闭。 这个问题是 not reproducible or was caused by typos 。它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能在这里出现,
我目前正在开发一个保存和加载程序,但我无法获得正确的结果。 编写程序: #include #include #define FILENAME "Save" #define COUNT 6 type
import java.io.*; public class Main2 { public static void main(String[] args) throws Exception {
我需要使用预定义位置字符串“Office”从所有日历中检索所有 iOS 事件,然后将结果写入 NSLog 和 UITextView。 到目前为止,这是我的代码: #import "ViewCo
我正在尝试将 BOOL 值写入 PFInstallation 中的列,但会不停地崩溃: - (IBAction)pushSwitch:(id)sender { NSUserDefaults *push
我以前在学校学过一些简单的数据库编程,但现在我正在尝试学习最佳实践,因为我正在编写更复杂的应用程序。写入 MySQL 数据库并不难,但我想知道让分布式应用程序写入 Amazon EC2 上的远程数据库
是否可以写回到ResourceBundle?目前我正在使用 ResourceBundle 来存储信息,在运行时使用以下内容读取信息 while(ResourceBundle.getBundle("bu
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我是一名优秀的程序员,十分优秀!