在vc6里,CStdioFile类的release版也使用了buffer的,但是很明显它的代码比我的还多,但效率却和我自己写的效率差不多。
我使用的是 _write 和 _comment 之类的IO函数。
请高手帮忙看看代码可以怎么优化能使它超过CstdioFile。
完整代码贴在我的blog里,链接:
http://blog.csdn.net/boythl/archive/2008/08/27/2835994.aspx
谢谢大虾们!!!
我使用的是 _write 和 _comment 之类的IO函数。
请高手帮忙看看代码可以怎么优化能使它超过CstdioFile。
完整代码贴在我的blog里,链接:
http://blog.csdn.net/boythl/archive/2008/08/27/2835994.aspx
谢谢大虾们!!!
low level file IO要自己管理系统的句柄等,效率并不高。
_write算是哪一级或哪一类的函数?
谢谢
C run-time I/O( fopen ... )
low level file I/O( _open ... )
C++ run-time I/O( ostream ... )
win32 file I/O( CreateFile ... )
Direct I/O ( Driver ... )其中最底层是驱动层的文件系统,直接操作扇区。
之上就是API了win32 file I/O。
而C run-time I/O、low level file I/O、C++ run-time I/O都是对API的包装,代码稍有不同,
效率也稍有不同你可以参考Crt的源码就知道了.
所以直接用CreateFile如果写的好的话,效率应该能够满足要求了。至于win下io的书好像没什么,这种内容基本都是简单介绍。
我再尝试下。 有结果再贴出来。
但我发现debug版的CStdiofile写起来很慢。写个80M的东西得很久。我想自己写一个,效率要超过cstdiofile。我的描述够了吧?
基本上是几个字符几个字符写的。
任务管理器里的io写出是几K几K的增加。
另外,通常应用程序不会在短时间内执行这么多次写文件操作的,不清楚你怎么有这样的应用。
所以我就怀疑是太多次的写操作导致的效率低下。
另,因为该库用到的其他库只有debug版,目前也只能发布debug版,所以我只能在debug版中测试效率。
因此,我考虑能不能自己写个带缓冲的写文件类,来提高写的效率。
我用WriteFile API写文件时
HasOverlappedIoCompleted(m_pOverLapped)
判断异步写磁盘是否完成,但一直是false,能告诉我怎么回事吗?
WriteFile返回成功int nFlag = FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED/*异步IO*/ /*| FILE_FLAG_WRITE_THROUGH*/ | FILE_FLAG_NO_BUFFERING; if (INVALID_HANDLE_VALUE ==
(this->m_Handle = CreateFile(lpszFileName, GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ, NULL, nCreateFlag, nFlag, NULL))
)//文件打开失败
{
this->m_Handle = NULL;
return FALSE;
}if (WriteFile(this->m_Handle, this->m_Buffer, dwLen,
&m_dwByteWrittern, m_pOverLapped))
{
if (m_pOverLapped->Offset + dwLen <= 0xFFFFFFFF)
{
m_pOverLapped->Offset += dwLen;
}
else
{
m_pOverLapped->OffsetHigh++;//高位加1
m_pOverLapped->Offset += (dwLen - 0xFFFFFFFF);
}
}请帮我看看代码有问题吗?
{
Sleep(10); //这一句是否有必要?
}
发出两个WriteFile命令,100byte偏移位的写和50byte偏移位的写,不管他们谁先写应该都没问题吧?
每次WriteFile之前给m_pOverLapped->Offset赋值。
如果WriteFile返回失败,用GetLastError取错误码,如果是ERROR_IO_PENDING说明没有错误。
WriteFile后直接返回,最好不要立即修改m_pOverLapped->Offset,不确定对操作是否会有影响。
FlushFileBuffers是多余的。
等待操作完成可以在循环中Sheep(0),以降低CPU使用率,也可以等待事件。
使用FILE_FLAG_NO_BUFFERING标志时,每次写入文件的位置和数据长度必须是磁盘扇区大小(通常是512)的整数倍。
虽然msdn上说了每次数据量要是vector的整数倍,但我没注意到最后一次不是,是680000,512的1328.125倍。
取消FILE_FLAG_NO_BUFFERING就ok了。那请问高手,若用FILE_FLAG_NO_BUFFERING最后的数据应该怎么write呢?我的buffer是512的整数倍,将后面的buffer用0复位然后writefile整个buffer?那岂非有冗余数据?一般应该怎么做呢?
内存复制耗时很少,相对磁盘操作来说可以忽略不计。可能是你的缓冲区开得太大,导致等待时间过长,降低了效率。
r.Format("buffer:%ld file:%ld", d1, d2);
AfxMessageBox(r);
昨天d1和d2反了。不好意思。^_^今天发现,用了FILE_FLAG_WRITE_THROUGH效率会降低,不用FILE_FLAG_NO_BUFFERING就是说使用系统缓存将和CStdiofile时间相近。debug版下大致:
714M数据耗时分别是20289和47000;
476M数据耗时分别是13344和26735,
238M数据耗时分别是4961和11633;release版和debug版相似,时间只少了一点点,可见耗时基本都在IO上。