TCMalloc是什么
TCMalloc全称Thread-Caching Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,用于替代系统的内存分配相关的函数(malloc、free,new,new[]等)。
它具有现代化内存分配器的基本特征:对抗内存碎片、在多核处理器能够 scale。据称,它的内存分配速度是 glibc2.3 中实现的 malloc的数倍,在不少开源项目中都有使用,例如在 Golang 中
就使用了类似的算法进行内存分配。
TCMalloc能解决什么问题
正是因为TCMalloc在内存分配方面的优异性能,使得它成为高并发服务内存管理的优秀解决方案,可以有效地解决内存碎片问题,
同时也可以大大降低多线程因为内存分配时的锁竞争方面的开销。
如何使用TCMalloc
在Ubuntu16.04上使用TCMALLOC
首先下载并安装工具包
$ sudo apt-get install google-perftools
对于已经编译好的程序,可以使用如下命令,让程序加载TCMalloc来大致测试一下程序性能的提升
$ LD_PRELOAD="/usr/lib/libtcmalloc.so.4"
在Windows平台上使用TCMALLOC
首先在官网下载并解压gperftools,下载地址为:https://github.com/gperftools/
启动编译
编译完成
使用方法
1. 修改三方库加载路径
2. 添加要加载的三方库 libtcmalloc_minimal.lib
3.添加启动符号 __tcmalloc
4.拷贝编译依赖的三方库到响应目录下
5.拷贝运行期依赖的三方库到响应目录下
6.编译成功!
测试一下
// test_tcmalloc.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
// 执行多少轮
#define MAX_SCALE (4000)
//每轮生成 2 4 8 16 32 64 126 256 512 1024 2048 4096 。。。。共16种规格的内存
#define MAX_SIZE 16
DWORD WINAPI worker(LPVOID lpThreadParameter) {
int iterations = MAX_SCALE;
void* ps[MAX_SCALE][MAX_SIZE];
while (iterations--) {
for (int i = 0; i < MAX_SIZE; i++) {
int size = (int)pow(2.0, i);
void * p = malloc(size);
memset(p, 0, size);
ps[iterations][i] = p;
}
}
iterations = MAX_SCALE;
while (iterations--) {
for (int i = 0; i < MAX_SIZE; i++) {
free(ps[iterations][i]);
}
}
return NULL;
}
int main()
{
int scale = 4;
cout << "start " << endl;
HANDLE* handles = new HANDLE[scale];
//cout << "HANDLE newed" << endl;
DWORD start = ::GetTickCount();
for (int i = 0; i < scale; i++) {
DWORD threadID(0);
handles[i] = CreateThread(0, 0, worker, NULL, NULL, &threadID);
DWORD dw = GetLastError();
}
WaitForMultipleObjects(scale, handles, true, INFINITE);
DWORD end = ::GetTickCount();
cout << "cost "<<end - start <<"ms"<< endl;
cout << "end" << endl;
getchar();
return 0;
}
msvcrt 4 threads
tcmalloc 4 threads
421ms=>219ms 可以看到,性能有较大的提升。
结语
TCMalloc使用起来侵入性较少(在Ubuntu系统上不具有侵入性),堆内存碎片优化效果明显,内存分配开销小,在服务端,客户端都会有不错的使用前景。