微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Windows上C ++的I / O性能非常不同

我是一个新用户,我的英语不太好,所以我希望能够清楚。 我们正在面临一个性能问题,尤其是当您试图扩大它们的大小时,会使用大文件(1GB或更多)。

无论如何…为了validation我们的感觉,我们尝试了以下(在Win 7 64Bit,4core,8GB RAM,用VC2008编译的32位代码

a)打开一个不存在的文件。 从1Mb插槽开始写入到1Gb。

现在你有一个1Gb的文件

现在在这文件随机放置10000个位置,find这个位置,并在每个位置写入50个字节,不pipe你写什么。

closures文件并查看结果。

创build文件的时间非常快(大约0.3“ ),写入10000次的时间总是很快(大约0.03” )。

非常好,这是初学者。

现在尝试别的…

TCP可调参数不会在数据传输速率中显示预期的结果

infiniband rdma穷人转会bw

在Windows上的Python。 为什么阅读文本比二进制慢8倍?

Windows fsync(Flushfilebuffers)性能与大文件

套接字的Mac OS X与Windows的Java慢

b)打开一个不存在的文件,寻找1Gb-1字节,只写1个字节。

现在你有另一个1Gb文件

按照与“a”相同的方式执行下一步骤,closures文件并查看结果。

创build文件的时间是你可以想象的更快(大约0.00009“ ),但写的时间是你不能相信的东西…. 关于90”!!!!!

b.1)打开一个不存在的文件,不要写任何字节。

像以前一样,夯实,寻求和写作,closures文件,看看结果。

写的时间长度都是一样的: 大约90“!

好的…这真是太神奇了。 但还有更多!

c)再次打开你在'a'时创build的文件,不要截断它…再次随机化10000个位置并像以前一样工作。 你跟以前一样快,大概0.03“写10000遍。

这听起来不错…尝试另一个步骤。

d)现在打开你创build的文件,在'b'的情况下,不要截断它…随机再次10000个位置,并像以前一样行事。 你一次又一次慢,但是时间缩短到… 45“!!也许,再试一次,时间会减less。

我真的好奇为什么…任何想法?

以下是我用来testing前面提到的代码的一部分(为了有一个干净的编译,我只是从一些源代码中剪切和粘贴,对不起)。

样本可以随机读取和写入,有序或反向sorting模式,但只写入随机顺序是最清晰的testing。

我们尝试了使用std :: fstream,但也直接使用CreateFile(),WriteFile()等等结果是一样的(即使std :: fstream实际上慢了一点)。

案例'a'的参数=> -f_tempdir_ casea.dat -n10000 -t -p -w

案例'b'的参数=> -f_tempdir_ caseb.dat -n10000 -t -v -w

案例'b.1'的参数=> -f_tempdir_ caseb.dat -n10000 -t -w

案例'c'的参数=> -f_tempdir_ casea.dat -n10000 -w

案例'd'的参数=> -f_tempdir_ caseb.dat -n10000 -w

运行testing(甚至其他),看看…

// iotest.cpp : Defines the entry point for the console application. // #include <windows.h> #include <iostream> #include <set> #include <vector> #include "stdafx.h" double RealTime_Microsecs() { LARGE_INTEGER fr = {0,0}; LARGE_INTEGER ti = {0,0}; double time = 0.0; QueryPerformanceCounter(&ti); QueryPerformanceFrequency(&fr); time = (double) ti.QuadPart / (double) fr.QuadPart; return time; } int main(int argc,char* argv[]) { std::string sFileName ; size_t stSize,stTimes,stBytes ; int retval = 0 ; char *p = NULL ; char *pPattern = NULL ; char *pReadBuf = NULL ; try { // Default stSize = 1<<30 ; // 1Gb stTimes = 1000 ; stBytes = 50 ; bool bTruncate = false ; bool bPre = false ; bool bPreFast = false ; bool bOrdered = false ; bool bReverse = false ; bool bwriteonly = false ; // Comsumo i parametri for(int index=1; index < argc; ++index) { if ( '-' != argv[index][0] ) throw ; switch(argv[index][1]) { case 'f': sFileName = argv[index]+2 ; break ; case 's': stSize = xw::str::strtol(argv[index]+2) ; break ; case 'n': stTimes = xw::str::strtol(argv[index]+2) ; break ; case 'b':stBytes = xw::str::strtol(argv[index]+2) ; break ; case 't': bTruncate = true ; break ; case 'p' : bPre = true,bPreFast = false ; break ; case 'v' : bPreFast = true,bPre = false ; break ; case 'o' : bOrdered = true,bReverse = false ; break ; case 'r' : bReverse = true,bOrdered = false ; break ; case 'w' : bwriteonly = true ; break ; default: throw ; break ; } } if ( sFileName.empty() ) { std::cout << "Usage: -f<File Name> -s<File Size> -n<Number of Reads and Writes> -b<Bytes per Read and Write> -t -p -v -o -r -w" << std::endl ; std::cout << "-t truncates the file,-p pre load the file,-v pre load 'veloce',-o writes in order mode,-r write in reverse order mode,-w Write Only" << std::endl ; std::cout << "Default: 1Gb,1000 times,50 bytes" << std::endl ; throw ; } if ( !stSize || !stTimes || !stBytes ) { std::cout << "Invalid Parameters" << std::endl ; return -1 ; } size_t stBestSize = 0x00100000 ; std::fstream fFile ; fFile.open(sFileName.c_str(),std::ios_base::binary|std::ios_base::out|std::ios_base::in|(bTruncate?std::ios_base::trunc:0)) ; p = new char[stBestSize] ; pPattern = new char[stBytes] ; pReadBuf = new char[stBytes] ; memset(p,stBestSize) ; memset(pPattern,(int)(stBytes&0x000000ff),stBytes) ; double dTime = RealTime_Microsecs() ; size_t stcopySize,stSizetocopy = stSize ; if ( bPre ) { do { stcopySize = std::min(stSizetocopy,stBestSize) ; fFile.write(p,stcopySize) ; stSizetocopy -= stcopySize ; } while (stSizetocopy) ; std::cout << "Creating time is: " << xw::str::itoa(RealTime_Microsecs()-dTime,5,'f') << std::endl ; } else if ( bPreFast ) { fFile.seekp(stSize-1) ; fFile.write(p,1) ; std::cout << "Creating Fast time is: " << xw::str::itoa(RealTime_Microsecs()-dTime,'f') << std::endl ; } size_t stPos ; ::srand((unsigned int)dTime) ; double dReadTime,dWriteTime ; stcopySize = stTimes ; std::vector<size_t> inVect ; std::vector<size_t> outVect ; std::set<size_t> outSet ; std::set<size_t> inSet ; // Prepare vector and set do { stPos = (size_t)(::rand()<<16) % stSize ; outVect.push_back(stPos) ; outSet.insert(stPos) ; stPos = (size_t)(::rand()<<16) % stSize ; inVect.push_back(stPos) ; inSet.insert(stPos) ; } while (--stcopySize) ; // Write & read using vectors if ( !bReverse && !bOrdered ) { std::vector<size_t>::iterator outI,inI ; outI = outVect.begin() ; inI = inVect.begin() ; stcopySize = stTimes ; dReadTime = 0.0 ; dWriteTime = 0.0 ; do { dTime = RealTime_Microsecs() ; fFile.seekp(*outI) ; fFile.write(pPattern,stBytes) ; dWriteTime += RealTime_Microsecs() - dTime ; ++outI ; if ( !bwriteonly ) { dTime = RealTime_Microsecs() ; fFile.seekg(*inI) ; fFile.read(pReadBuf,stBytes) ; dReadTime += RealTime_Microsecs() - dTime ; ++inI ; } } while (--stcopySize) ; std::cout << "Write time is " << xw::str::itoa(dWriteTime,'f') << " (Ave: " << xw::str::itoa(dWriteTime/stTimes,10,'f') << ")" << std::endl ; if ( !bwriteonly ) { std::cout << "Read time is " << xw::str::itoa(dReadTime,'f') << " (Ave: " << xw::str::itoa(dReadTime/stTimes,'f') << ")" << std::endl ; } } // End // Write in order if ( bOrdered ) { std::set<size_t>::iterator i = outSet.begin() ; dWriteTime = 0.0 ; stcopySize = 0 ; for(; i != outSet.end(); ++i) { stPos = *i ; dTime = RealTime_Microsecs() ; fFile.seekp(stPos) ; fFile.write(pPattern,stBytes) ; dWriteTime += RealTime_Microsecs() - dTime ; ++stcopySize ; } std::cout << "Ordered Write time is " << xw::str::itoa(dWriteTime,'f') << " in " << xw::str::itoa(stcopySize) << " (Ave: " << xw::str::itoa(dWriteTime/stcopySize,'f') << ")" << std::endl ; if ( !bwriteonly ) { i = inSet.begin() ; dReadTime = 0.0 ; stcopySize = 0 ; for(; i != inSet.end(); ++i) { stPos = *i ; dTime = RealTime_Microsecs() ; fFile.seekg(stPos) ; fFile.read(pReadBuf,stBytes) ; dReadTime += RealTime_Microsecs() - dTime ; ++stcopySize ; } std::cout << "Ordered Read time is " << xw::str::itoa(dReadTime,'f') << " in " << xw::str::itoa(stcopySize) << " (Ave: " << xw::str::itoa(dReadTime/stcopySize,'f') << ")" << std::endl ; } }// End // Write in reverse order if ( bReverse ) { std::set<size_t>::reverse_iterator i = outSet.rbegin() ; dWriteTime = 0.0 ; stcopySize = 0 ; for(; i != outSet.rend(); ++i) { stPos = *i ; dTime = RealTime_Microsecs() ; fFile.seekp(stPos) ; fFile.write(pPattern,stBytes) ; dWriteTime += RealTime_Microsecs() - dTime ; ++stcopySize ; } std::cout << "Reverse ordered Write time is " << xw::str::itoa(dWriteTime,'f') << ")" << std::endl ; if ( !bwriteonly ) { i = inSet.rbegin() ; dReadTime = 0.0 ; stcopySize = 0 ; for(; i != inSet.rend(); ++i) { stPos = *i ; dTime = RealTime_Microsecs() ; fFile.seekg(stPos) ; fFile.read(pReadBuf,stBytes) ; dReadTime += RealTime_Microsecs() - dTime ; ++stcopySize ; } std::cout << "Reverse ordered Read time is " << xw::str::itoa(dReadTime,'f') << ")" << std::endl ; } }// End dTime = RealTime_Microsecs() ; fFile.close() ; std::cout << "Flush/Close Time is " << xw::str::itoa(RealTime_Microsecs()-dTime,'f') << std::endl ; std::cout << "Program Terminated" << std::endl ; } catch(...) { std::cout << "Something wrong or wrong parameters" << std::endl ; retval = -1 ; } if ( p ) delete []p ; if ( pPattern ) delete []pPattern ; if ( pReadBuf ) delete []pReadBuf ; return retval ; }

为什么这个“hello world”golang http例子在osx上放慢了速度

WampServer上的APC没有性能提升

用TSC(时间戳计数器)计算时间

Windows计时器分辨率与应用程序优先级与处理器调度

sockets乒乓表演

如果你没有冲洗这些变化,而且你有足够的免费内存来缓存它,那么你只是在测量你的内存的速度。

此外,请注意,某些文件系统支持“漏洞”,即未分配文件的区域。 如果文件系统有这样的支持(我不知道在Windows上有没有做,但是可能),那么对1G进行“寻找”的测试然后写入1个字节,将会创建一个大部分是“洞”的文件, ,因此需要写几块。

最后,你应该重复每一次测试和许多次,每次刷新整个缓存(这可以不使用sysinternals工具在Windows上重新启动),并且在禁用任何访问AV软件的空闲机器上运行。 如果您发现性能出现大的差异,就会发生一些奇怪的事情。

请确保在开始下一个测试之前,先前测试完成的任何写入操作完全刷新到光盘,否则将完全破坏您的数据。

最后,不要注意虚拟机上的性能数据。 如果你想要一致的结果(即使你正在部署到一个虚拟机),在真实的硬件上进行所有的性能测试。

这完全取决于磁盘缓存和文件系统结构。 如果数据已经在那里并且稍后刷新,一些读/写操作将只需要在高速缓存上操作。 其他操作必须在磁盘上运行,因为数据不在缓存中,速度会更慢。

文件系统中块的排列也会影响这些东西。 在极端情况下,将一个字节添加到GB文件可能会导致其中一部分被移动到磁盘上。 其他因素如碎片,块大小和读取/写入的方式都经过优化,缓存可能会导致您看到的效果

这可能取决于您正在使用的文件系统。 我对NTFS文件系统并不十分了解,但是许多FS优化了稀疏文件中的空白空间,其中空白空间被定义为没有任何内容写入的文件中的块。 请注意,这些位置的读取将返回0,但是没有写入任何内容

一个测试会在文件中创建并分配所有必需的块。 然后随机修改只是修改已经分配的磁盘块的内容。 其余的测试会创建文件,但从不真正写入文件,因此FS可能包含文件的大小,但不包含分配的块。 在这种情况下的测试必须寻找,从磁盘分配一个块到文件,初始化为0,然后写入数据。 如下所示,您可以在所有情况下检查从磁盘分配的实际空间。

第三块结果45“也可能与分配(快速写入)和未分配(慢速写入)块的平衡相关。

编辑:看来,NTFS确实有这种类型的稀疏文件优化。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐