編寫伺服器程式時,需要頻繁的申請和釋放記憶體,長時間執行會產生大量的記憶體碎片,這就導致即使當前系統中的閒置記憶體還足夠多,但也無法申請到大的連續可用的記憶體塊,因為此時的實體記憶體已經千瘡百孔像個馬蜂窩。此外,在高併發的情況下頻繁的malloc/free也是一筆額外的cpu負擔。

如何解決記憶體碎片呢?

在這裡給大家安利一個舉手之勞的好辦法——重啟應用

如果是客戶端程式,可以通過退出重啟的方式解決記憶體碎片的問題;不過對於伺服器應用而言這樣操作的風險比較大,但如果覺得自己命硬也不妨嘗試一下。

不好意思上面寫錯了,重新安利一下。

通常情況下伺服器程式會在內部實現一套自己的記憶體分配和管理機制,用於解決記憶體碎片和速度的問題。比如分散式快取服務memcached就是用Slab Allocator來分配和管理記憶體。但對於大部分應用而言,自己單獨造輪子的成本還是比較高的,一旦管理不善,可能會引入更多的問題。如果有現成的開源記憶體管理庫可用,是再好不過的。相較於memcached,另一個快取記憶體redis就是拿來主義直接使用開源的記憶體管理庫,內部集成了google的tcmalloc和jemalloc。redis的windows版本是用的是jemalloc庫。

說了這麼多廢話,迴歸正題,如何呼叫jemalloc庫,本案例使用的是x86靜態庫。

一、下載地址

1、jemalloc各種庫下載地址

2、jemalloc標頭檔案下載地址

如下圖:

請根據個人胃口下載不同的jemalloc庫,但include.zip必須要下載。

二、開發環境準備

開發環境:vs2017或vs2015

1、建立一個控制檯工程test_jemalloc

確保有main函式啊!

2、配置include目錄

下載 include.zip到指定目錄,並解壓拷貝到test_jemalloc工程下。

如果不是在當前工程下,則需要寫好絕對路徑。

3、配置前處理器

因為本案例使用的是靜態庫,則需要在配置中加入如下巨集定義(如果使用的是動態庫則無需配置)。

JEMALLOC_EXPORT=

JEMALLOC_STATIC

三、測試原始碼


#include <stdio.h>
#include <time.h> // for clock()
#include <assert.h>
#include "jemalloc/jemalloc.h" // “配置屬性”->“C/C++”->“常規”->“附加包含目錄” //#define USE_JEMALLOC // 過載malloc/free
#ifdef USE_JEMALLOC
#define malloc(size) je_malloc(size)
#define calloc(count,size) je_calloc(count,size)
#define realloc(ptr,size) je_realloc(ptr,size)
#define free(ptr) je_free(ptr)
#endif // 當前使用的是jemalloc靜態庫
#ifdef _DEBUG
#pragma comment(lib,"jemalloc-x86-Debug-static.lib")
#else
#pragma comment(lib,"jemalloc-x86-Release-static.lib")
#endif int main()
{
int i = 0;
int iCount = 50000;
int iSize = 1000; // malloc
clock_t cStart = ::clock();
for (i = 0; i < iCount; i++)
{
void* pMem = malloc(iSize);
assert(pMem);
free(pMem);
}
clock_t cSpan1 = ::clock() - cStart; // jemalloc
cStart = ::clock();
for (i = 0; i < iCount; i++)
{
void* pMem = je_malloc(iSize);
assert(pMem);
je_free(pMem);
}
clock_t cSpan2 = ::clock() - cStart; printf("malloc span time = %d, jemalloc span time = %d\r\n", cSpan1, cSpan2); printf("press any key exit......\r\n");
getchar();
return 0;
}

感謝您的閱讀!