龜速的malloc和神速的FastMM

來源:互聯網
上載者:User

由於在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:
  VC2008 Release: 3.854
看來malloc並沒有對小記憶體作任何最佳化,所以在C++中要大量使用動態對象,是必須要小心的,否則很容易引起效能問題。找了一些替換的記憶體管理器,始終沒有辦法達到FastMM的水平,最快的也只是其一半的速度。
最後我用自己實現的一個受限的記憶體管理器測試,該管理器只能建立固定大小的記憶體塊,也是用池的方式緩衝記憶體塊,代碼如下:

  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);

這次的結果很讓我滿意:
  VC2008 Release: 0.0806
速度比FastMM快了近一倍,但這並不表示它比FastMM好,因為FastMM更加通用,且處理了很多其他的邏輯,如果FixedAlloc做得更完善一些,或許會和FastMM接近的。因此可見,對效率很敏感的程式,使用特有的記憶體管理器是必須的,否則讓龜速的malloc來處理,一切都是龜速。
進一步想,如果開啟多線程判斷,FastMM的效率不知如何,於是又有下面的測試代碼:

  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開啟,效果非常明顯:
  Delphi2007 Release:0.41 
足足比單線程模式慢了3倍,但是如果我自己來處理多線程的情況呢,結果又是如何呢:

  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);

結果很糟糕:
  Delphi2007 Release:0.71 
FastMM並不像Delphi7那樣,用臨界區來實現多安全執行緒,因此效率要比那個方案更高一些,FastMM確實不失為一個頂級的記憶體管理器。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.