由于在Delphi项目中,要频繁创建和释放大量小对象,因此担心有效率问题,于是打于GetMem.inc看看,发现FastMM对于小块内存作了很多工作,它预置了一组不同大小的内存池,当要创建一块内存时,FastMM找到大小最相近的内存池分配之,内存释放后回收到池中。这样的做法虽有小量内存浪费,但效率却是大大提高。
我决定做一个测试,看看效率研究如何:
const
cSize: Integer = 100;
cNum: Integer = 10000;
var
N, I: Integer;
P: array [0..9999] of Pointer;
Fre: Int64;
Count1, Count2: Int64;
Time: Double;
begin
QueryPerformanceFrequency(Fre);
QueryPerformanceCounter(Count1);
for I := 0 to 1000 - 1 do
begin
for N := 0 to cNum - 1 do
GetMem(P[N], cSize);
for N := 0 to cNum - 1 do
FreeMem(P[N]);
end;
QueryPerformanceCounter(Count2);
Time := (Count2 - Count1) / Fre;
Writeln(Format('Delphi2007 Release: %f', [Time]));
end.
上面例子中,循环1000次,每次循环分别创建和释放10000个100字节的内存块,运行结果如下:
Delphi2007 Release: 0.14我想起C++的Malloc,不知其效率如何,于是我又将Delphi的测试代码转换成C++,代码如下:
LARGE_INTEGER fre;
LARGE_INTEGER count1, count2;
double time;
QueryPerformanceFrequency(&fre);
const int cSize = 100;
const int cNum = 10000;
void* p[cNum];
QueryPerformanceCounter(&count1);
for (int i = 0; i < 1000; ++i)
{
for (int n = 0; n < cNum; ++n)
p[n] = malloc(cSize);
for (int n = 0; n < cNum; ++n)
free(p[n]);
}
QueryPerformanceCounter(&count2);
time = (count2.QuadPart - count1.QuadPart) / (double)fre.QuadPart;
printf("VC2008 Release: %f\n", time);
运行结果使我震惊,这真是龟速的malloc:
LARGE_INTEGER fre;
LARGE_INTEGER count1, count2;
double time;
QueryPerformanceFrequency(&fre);
const int cSize = 100;
const int cNum = 10000;
void* p[cNum];
FixedAlloc myAlloc(cSize);
QueryPerformanceCounter(&count1);
for (int i = 0; i < 1000; ++i)
{
for (int n = 0; n < cNum; ++n)
{
//p[n] = malloc(cSize);
p[n] = myAlloc.Alloc();
}
for (int n = 0; n < cNum; ++n)
{
//free(p[n]);
myAlloc.Free(p[n]);
}
}
QueryPerformanceCounter(&count2);
time = (count2.QuadPart - count1.QuadPart) / (double)fre.QuadPart;
printf("VC2008 Release: %f\n", time);
这次的结果很让我满意:
IsMultiThread := True;
QueryPerformanceCounter(Count1);
for I := 0 to 1000 - 1 do
begin
for N := 0 to cNum - 1 do
GetMem(P[N], cSize);
for N := 0 to cNum - 1 do
FreeMem(P[N]);
end;
QueryPerformanceCounter(Count2);
Time := (Count2 - Count1) / Fre;
Writeln(Format('Delphi2007 Release:%f', [Time]));
仅仅是把IsMultiThread打开,效果非常明显:
IsMultiThread := False;
InitializeCriticalSection(CS);
QueryPerformanceCounter(Count1);
for I := 0 to 1000 - 1 do
begin
for N := 0 to cNum - 1 do
begin
EnterCriticalSection(CS);
GetMem(P[N], cSize);
LeaveCriticalSection(CS);
end;
for N := 0 to cNum - 1 do
begin
EnterCriticalSection(CS);
FreeMem(P[N]);
LeaveCriticalSection(CS);
end;
end;
QueryPerformanceCounter(Count2);
Time := (Count2 - Count1) / Fre;
Writeln(Format('Delphi2007 Release:%f', [Time]));
DeleteCriticalSection(CS);
结果很糟糕: