我是新用户,我的英语不太好,所以我希望讲清楚。
当您尝试增大大文件的大小时,我们正面临着使用大文件(1GB或更大)的性能问题。
无论如何...为了验证我们的感受,我们尝试了以下操作(在Win 7 64Bit,4core,8GB Ram,用VC2008编译的32位代码上)
a)打开一个不存在的文件。从一开始就将其写入1Mb插槽中的1Gb。
现在您有了一个1Gb文件。
现在,在该文件中随机分配10000个位置,查找该位置并在每个位置写入50个字节,无论您写什么内容。
关闭文件并查看结果。
创建文件的时间相当快(大约0.3英寸),写入10000次的时间也一样(大约0.03英寸)。
很好,这是开始。
现在尝试其他...
b)打开一个不存在的文件,查找到1Gb-1byte并仅写1个字节。
现在您有了另一个1Gb文件。
按照情况“a”的相同步骤执行后续步骤,关闭文件并查看结果。
创建文件的时间是您可以想象的更快(大约0.00009英寸),但是写入时间却令人难以置信...。大约90英寸!!!!!
b.1)打开一个不存在的文件,不要写任何字节。
像以前一样,随机分组,查找和写入,关闭文件并查看结果。
写入时间很长,都是一样的:大约90英寸!!!!!
好的,这真是太神奇了。但是还有更多!
c)再次打开您创建的大小写为'a'的文件,不要截断它...再次随机分配10000个位置,并像以前一样操作。您的速度与以前一样快,可以写10,000次,约为0,03“。
听起来不错,请尝试其他步骤。
d)现在打开您创建的大小写为“b”的文件,不要截断...再次随机分配10000个位置,并像以前一样操作。您一次又一次地变慢,但是时间减少到... 45“!! 也许,再试一次,时间会减少。
我真的想知道为什么
任何的想法?
以下是我用来测试先前案例中告诉我的内容的代码的一部分(您必须更改一些方式才能进行干净的编译,抱歉,我只是从某些源代码中剪切并粘贴了内容)。
样本可以以随机,有序或逆序模式读取和写入,但仅以随机顺序写入是最清晰的测试。
我们尝试使用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
运行测试(甚至其他测试),然后查看...
// 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, 0, 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, 5, '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, 5, 'f') << " (Ave: " << xw::str::itoa(dWriteTime/stTimes, 10, 'f') << ")" << std::endl ;
if ( !bWriteOnly )
{
std::cout << "Read time is " << xw::str::itoa(dReadTime, 5, 'f') << " (Ave: " << xw::str::itoa(dReadTime/stTimes, 10, '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, 5, 'f') << " in " << xw::str::itoa(stCopySize) << " (Ave: " << xw::str::itoa(dWriteTime/stCopySize, 10, '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, 5, 'f') << " in " << xw::str::itoa(stCopySize) << " (Ave: " << xw::str::itoa(dReadTime/stCopySize, 10, '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, 5, 'f') << " in " << xw::str::itoa(stCopySize) << " (Ave: " << xw::str::itoa(dWriteTime/stCopySize, 10, '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, 5, 'f') << " in " << xw::str::itoa(stCopySize) << " (Ave: " << xw::str::itoa(dReadTime/stCopySize, 10, 'f') << ")" << std::endl ;
}
}// End
dTime = RealTime_Microsecs() ;
fFile.close() ;
std::cout << "Flush/Close Time is " << xw::str::itoa(RealTime_Microsecs()-dTime, 5, '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 ;
}
最佳答案
如果您不清除更改,并且有足够的可用内存来缓存它,那么您只是在测量内存的速度。
另外,请注意,某些文件系统支持“空洞”,即未分配的文件区域。如果文件系统具有这种支持(我不知道在Windows上是否有支持,但是可能),则对1G执行“搜索”然后写入1个字节的测试将创建一个文件,该文件主要是“漏洞” ,因此需要写入的块很少。
最后,您应该重复很多次测试,每次刷新整个缓存(在Windows中使用sysinternals工具无需重新启动就可以),并在其他空闲的计算机上运行,并且禁用任何可访问的AV软件。如果您发现演出有很大差异,则说明发生了奇怪的事情。
绝对确保在开始下一个测试之前,将先前测试完成的所有写入均完全刷新到磁盘上,否则将完全破坏您的数据。
最后,不要在VM上注意到任何性能数据。如果要获得一致的结果(即使您正在部署到VM中),请在真实硬件上进行所有性能测试。