测试环境:
3个970Pro SSD组RAID后,用多种工具测试,读的速度都在7.5GB/秒左右,写的速度在6GB/秒左右。而且写的是随机内容,非0,共测试50G大小可排除缓存。
发现自己的程序在读取时性能不行,我就单独写了个测试demo,结果如下:
代码如下:
void Test1(bool bWriteTest, char* pBlock, wchar_t *pFile, ULONGLONG llFileSize, ULONGLONG llTotalTestByte, ULONGLONG llBlockByte)
{
const wchar_t* pFileOpt = L"rb";
if (bWriteTest)
pFileOpt = L"wb";
FILE* hFile = _wfopen(pFile, pFileOpt);
if (hFile == 0)
{
printf("待测试文件打开失败!\n");
}
else
{
setvbuf(hFile, NULL, _IONBF, 0);
setbuf(hFile, 0);
ULONGLONG llTotalTestedLen = 0;
ULONGLONG llLastTestedLen = 0;
DWORD t1 = timeGetTime();
while (llTotalTestedLen < llTotalTestByte)
{
if (bWriteTest)
{
size_t iWriteLen = fwrite(pBlock, 1, llBlockByte, hFile);
if (iWriteLen != iWriteLen)
{
printf("测试操作出错!\n");
break;
}
llTotalTestedLen += iWriteLen;
}
else
{
size_t iReadLen = fread(pBlock, 1, llBlockByte, hFile);
if (iReadLen != llBlockByte)
{
if (feof(hFile))
fseek(hFile, 0, SEEK_SET);
}
llTotalTestedLen += iReadLen;
}
DWORD t2 = timeGetTime();
DWORD t = t2 - t1;
if (t > 1000)
{
t1 = t2;
ULONGLONG llTotalTestedMB = llTotalTestedLen / 1024 / 1024;
ULONGLONG llCurrentTestedMB = (llTotalTestedLen - llLastTestedLen) / 1024 / 1024;
ULONGLONG llTestSpeed = llCurrentTestedMB * 1000 / t;
llLastTestedLen = llTotalTestedLen;
printf("Total %lld MB, %lld MB/s\r", llTotalTestedMB, llTestSpeed);
}
}
fclose(hFile);
}
}
我一直认为,读写大块速度才最高,因为我们最常见的复制大文件远比复制小文件速度快很多。而且大块可能在磁盘上连续的概率要高得多。
基于已有的20G文件的测试结果:
每次读写100MB时,读写速度才1.5GB/秒
每次读写10MB时,读写速度提高到3GB/秒
每次读写1MB时,读写速度提高到3.3GB/秒
这与我的预测完全不一样,越小的块速度越快。
另外,网上说CreateFileMapping方式会快很多,我又写了一套基于CreateFileMapping的函数,测试结果跟fread差别不大,代码就不列了。
又基于_open _read _write写了一套,效果基本跟fopen差不多。
又基于CreateFile,ReadFile,WriteFile写了一套,常规使用方法,效果基本跟fopen差不多。
后来又仔细阅读CreateFile相关API,发现加上FILE_FLAG_NO_BUFFERING和FILE_FLAG_SEQUENTIAL_SCAN,在读写时速度就能跑到满速了
但是:我写的是播放器,解码部分用的ffmpeg,还有其它一些第三方库,在播放某些8K级别素材时,需要极限的读取速度,我不大可能把第三方库全改成windows api调用。
请问:是否有基于fopen open等 c函数的代码,通过某些参数设置,让整个程序能跑满速?
另外:
我用procexplorer查看HDTune,在测试时线程显示就是 exe直接调用Ntdll.dll的zwReadFile。
为何我自己基于API写的程序,是我的ReadFile先调用到 KernelBase.dll的ReadFile,再调用到Ntdll.dll的zwReadFile啊?
HDTune不应该直接调用Kernel.dll的ReadFile吗?
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!