【问题标题】:Which is faster, writing raw data to a drive, or writing to a file?将原始数据写入驱动器或写入文件哪个更快?
【发布时间】:2009-11-04 06:22:45
【问题描述】:

我需要将数据写入驱动器。我有两个选择:

  1. 写入原始扇区。(_write(handle, pBuffer, size);)
  2. 写入文件 (fwrite(pBuffer, size, count, pFile);)

哪种方式更快?

我希望原始扇区写入函数 _write 更有效。但是,我的测试结果失败了! fwrite 更快。 _write 花费更长的时间。

我已经粘贴了我的 sn-p;也许我的代码是错误的。你能帮我吗?无论哪种方式我都可以,但我认为原始写入更好,因为驱动器中的数据似乎至少是加密的......

#define SSD_SECTOR_SIZE 512
int g_pSddDevHandle = _open("\\\\.\\G:",_O_RDWR | _O_BINARY, _S_IREAD | _S_IWRITE);
TIMER_START();
while (ulMovePointer < 1024 * 1024 * 1024)
{
    _write(g_pSddDevHandle,szMemZero,SSD_SECTOR_SIZE);
    ulMovePointer += SSD_SECTOR_SIZE;
}
TIMER_END();
TIMER_PRINT();
FILE * file = fopen("f:\\test.tmp","a+");
TIMER_START();
while (ulMovePointer < 1024 * 1024 * 1024)
{
    fwrite(szMemZero,SSD_SECTOR_SIZE,1,file);
    ulMovePointer += SSD_SECTOR_SIZE;
}
TIMER_END();
TIMER_PRINT();

【问题讨论】:

  • 写入原始数据根本没有加密——它只是让用户感到困惑......
  • +1 用于分析。 (虽然这个问题在我头上)
  • 致 bdonlan:我只是希望它看起来像被加密......对用户不可见
  • 您还使用 CRT 而不是 Win32 API 进行文件写入。显然缓冲是问题的一部分——文件写入被缓冲,原始磁盘写入没有。也就是说,使用 _write 意味着 write 调用在写入数据之前无法返回。使用带有 OVERLAPPED 结构的 WriteFileEx 可以让您排队更多的写入,这应该或可能导致更高的吞吐量(在原始 dis 和文件写入)情况下。
  • 但是在Linux中类似的功能是什么,thanx

标签: c++ c windows


【解决方案1】:

可能是因为直接写入没有缓冲。当您调用fwrite 时,您正在执行缓冲写入,这在大多数情况下往往会更快。本质上,每个FILE* 处理程序都有一个内部缓冲区,当它变满时会定期刷新到磁盘,这意味着您最终会进行更少的系统调用,因为您只会以更大的块写入磁盘。

换句话说,在您的第一个循环中,您实际上是在每次迭代期间将 SSD_SECTOR_SIZE 字节写入磁盘。在您的第二个循环中,您不是。您只是将 SSD_SECTOR_SIZE 字节写入内存缓冲区,根据缓冲区的大小,只会在每第 N 次迭代时刷新一次。

【讨论】:

    【解决方案2】:

    在 _write() 情况下,SSD_SECTOR_SIZE 的值很重要。在 fwrite 情况下,每次写入的大小实际上是 BUFSIZ。为了获得更好的比较,请确保底层缓冲区大小相同。

    但是,这可能只是差异的一部分。

    在 fwrite 情况下,您正在测量将数据放入内存的速度。您还没有将 stdio 缓冲区刷新到操作系统,也没有要求操作系统将其缓冲区刷新到物理存储。为了更准确地比较,您应该在停止计时器之前调用 fflush()。

    如果您真的关心将数据放入磁盘而不是仅仅将数据放入操作系统缓冲区,则应确保在停止计时器之前调用 fsync()/FlushFileBuffers()。

    其他明显区别:

    • 驱动器不同。我不知道有什么不同。

    • 写入设备的语义不同于写入文件系统的语义;允许文件系统延迟写入以提高性能,直到明确告知不要这样做(例如,使用标准句柄,调用 FlushFileBuffers());直接写入设备不一定以这种方式优化。另一方面,文件系统必须进行额外的 I/O 来管理元数据(块分配、目录条目等)

    我怀疑您看到了关于数据实际进入磁盘的速度的不同政策。原始磁盘性能可能非常快,但您需要大量写入,最好是多个并发未完成的操作。您还可以通过在打开句柄时使用正确的选项来避免缓冲区复制。

    【讨论】:

    • 结果是 fwrite 比 _write 快 10 倍... SSD_SECTOR_SIZE 是 512
    • 如果在每次调用 fwrite 后调用 fflush(),性能应该大致相同。但是,正如 janm 所提到的,这里还涉及其他变量,例如操作系统缓存。
    • 如果你真的关心性能,我会尝试更大的写入,比如一次 1MB。或者甚至只是一次调用 write 函数,然后调用 flush 函数。现代驱动器不写入扇区,而是写入磁道。为了获得准确的比较,您应该刷新缓冲区。
    • 同步非常重要,如果您写入的总量远小于总内存,因为操作系统可能永远不会真正写入数据,直到程序终止之后很久。您可以使用 FlushFileBuffers 强制数据实际命中磁盘:msdn.microsoft.com/en-us/library/aa364439%28VS.85%29.aspx
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-19
    • 1970-01-01
    相关资源
    最近更新 更多