jemalloc 快速上手攻略
引言 - 赠送个 Cygwin (加精)
Cygwin 有它存在的合理性. 至少比 wine 好太多了. 它主要功能是在winds上面简易的模拟出linux环境, 比虚拟机
轻量一点点. 坑也不少, 难卸载, api模拟也只是粗模拟, 对于linux系统级别很多api使用不一致. 当然及其适合刚开始学
习linux开发同学尝试. linux 搞多了, 可能还真不一定比 winds 好. 否则也不会那么多程序员用起了 Mac X.
作为一名开发者, 语言层面可有鄙视链. 系统层面最好少点. 很容易被打脸. 切身体会. 每一个经历历史存活的
系统都是无数顶级门派, 大佬的逆天武学. 学的其一都能逆天 ~~~
搞回正题. 首先看下面两个链接.
Cygwin : http://www.cygwin.com/
apt-cyg : https://github.com/transcode-open/apt-cyg
第一个是软件实体, 下载下来能装x64就装x64. 第二个是 Cygwin 中 等同于 Ubuntu 中 apt-get, Centos中 yum...
Cygwin 安装过程注意点分享.
1. 过程中需要选择下载源, 默认第一个试试, 不行就挨个换换.
我这里选择了第一个也是有源的. 这个图片之前会让我们设置软件安装位置, 包的下载位置.
经验: 软件安装位置不要放在系统C盘. 我学生阶段默认安装到C盘. 后面就winds原生程序控制不了C盘了.
包下载位置和 setup-x86_64.exe 按照包同一级别最好
Cygwin 软件目录
| -> xxxx 这个位置
| -> setup-x86_64.exe
2. 点击下一步进入包的选择过程,
这个步骤选择你所有感兴趣的包. 例如 gcc new version , gdb, autoconf, autogen, gawk, grep, sed, unzip, tar 当然还有 vim ....
3. 随后下载安装等待个30-1h 就安装好了. 在桌面上面打开就ok!
开始我们的享受 ~~~
假如你想再按照其它插件, 继续点击第一步下载下来的 setup-x86_64.exe 继续进行上面的第二步操作.
4. 扩展操作, 没有 apt-get 总是不爽, 我们为我们的Cygwin 安装个
这里用的是 apt-cyg
cd wget https://github.com/transcode-open/apt-cyg/archive/master.zip unzip master.zip rm -rf master.zip cd apt-cyg-master install apt-cyg /bin # hello world apt-cyg apt-cyg --version
恭喜我们到这里基本搞定了 Cygwin 环境. 以后单纯在配置低的硬件下面学习再也不求人了.
扯一点, 假如高校需要教学生linux使用. 单纯的纯linux环境其实不一定太好. 因为费时费力, 进入核心还很麻烦. 因为linux版本
也很多. 倒不如直接进入一个好的模拟开发模块, 忽略版本. 那么实战开发中也难以纯linux办公. 缺的有点多 ~~ o(╥﹏╥)o
当然 - 真的 - 能学习Linux 真的很幸运. 程序开发中最美的结晶, 自由女神的象征 ~_~
前言 - jemalloc 搞起来
jemalloc 的介绍部分可以参照, 魅族CTO大佬的博客.
技术专辑:内存管理 : http://tinylab.org/memory-management-album-1/
我们这里只是科普实战篇, 如何在项目中跑起来. jemalloc 传说中最强最前沿的内存分配模型.
jemalloc github : https://github.com/jemalloc/jemalloc/
源码全部在上面我们找到release发布版本, 找个最新的下载下来. 随后编译使用了.
winds 跑起来 <-
首先看下面 jemalloc 中内嵌的说明
How to build jemalloc for Windows ================================= 1. Install Cygwin with at least the following packages: * autoconf * autogen * gawk * grep * sed 2. Install Visual Studio 2015 with Visual C++ 3. Add Cygwin\bin to the PATH environment variable 4. Open "VS2015 x86 Native Tools Command Prompt" (note: x86/x64 doesn't matter at this point) 5. Generate header files: sh -c "CC=cl ./autogen.sh" 6. Now the project can be opened and built in Visual Studio: msvc\jemalloc_vc2015.sln
通过引言, 我们安装好了 Cygwin. 后面都是人话. 我们都懂. 直接进入第6步
我这里采用 Best New CL 2017 编译 static 静态库的发布版本. 默认x64位.
扯一点题外话, 服务器开发尽量用静态库. 动态库部署调试安全都不太好. 通过才学会爱 ~
编译成功后, 找出来我们生成的内容. 例如我这里是 jemalloc-vc141-Release-static.lib 和自己找出来的 include
需要注意的是 记住将 strings.h 也添加进来.
核心, jemalloc 部署
a) 添加包含目录
项目右击 -> [属性] -> [VC++ 目录] -> [包含目录]
$(ProjectDir)
b) 添加引用库
项目右击 -> [属性] -> [VC++ 目录] -> [库目录]
$(ProjectDir)
项目右击 -> [属性] -> [链接器] -> [输入]
jemalloc-vc141-Release-static.lib
c) 添加预编译处理器
项目右击 -> [属性] -> [C/C++]-> [预处理器] -> [预处理器定义]
JEMALLOC_EXPORT=
JEMALLOC_STATIC
d 一些编译警告处理
项目右击 -> [属性] -> [C/C++] -> [常规] -> [调试信息格式] -> [程序数据库 (/Zi)]
项目右击 -> [属性] -> [C/C++] -> [高级] -> [编译为] -> [编译为C代码/TC]
项目右击 -> [属性] -> [C/C++] -> [代码生成] -> [运行库] -> [多线程/MT]
项目右击 -> [属性] -> [链接器] -> [常规] -> [启用增量链接] -> [否 (/INCREMENTAL:NO)]
项目右击 -> [属性] -> [链接器] -> [系统] -> [子系统] -> [控制台]
项目右击 -> [属性] -> [链接器] -> [命令行] -> /LTCG
[Release]
- [控制台]
| [否 (/INCREMENTAL:NO)]
| [程序数据库 (/Zi)]
其中备注一下, + 表示添加, - 表示减少, | 表示保持不变不用动.
到这里winds上面前戏真的做足了!!! 我们搞个下面代码测试一下
#include <stdio.h> #include <jemalloc/jemalloc.h> // // 测试 jemalloc hello world // int main(int argc, char * argv[]) { int * piyo = je_malloc(sizeof(int)); if (NULL == piyo) { puts("je_malloc sizeof int is error!"); return EXIT_FAILURE; } printf("piyo = %p, %d.\n", piyo, *piyo); je_free(piyo); piyo = je_calloc(2, sizeof (int)); if (NULL == piyo) { puts("je_calloc is error!\n"); return EXIT_FAILURE; } printf("piyo = %p, %d.\n", piyo, *piyo); piyo = je_realloc(piyo, sizeof(int)); if (NULL == piyo) { puts("je_realloc is error!\n"); return EXIT_FAILURE; } printf("piyo = %p, %d.\n", piyo, *piyo); je_free(piyo); return EXIT_SUCCESS; }
系统啪啪啪的奔跑起来了 ~
linux 部署
我这里采用的Ubuntu环境跑上面 main.c
cd ~/桌面
wget https://github.com/jemalloc/jemalloc/releases/download/5.0.1/jemalloc-5.0.1.tar.bz2 tar -jxvf jemalloc-5.0.1.tar.bz2 cd jemalloc-5.0.1
sudo apt-get install autogen autoconf
./autogen.sh
make -j2 sudo make install
sudo ldconfig
cd ../
rm -rf jemalloc-5.0.1 jemalloc-5.0.1.tar.bz2
注意安装 jemalloc 不要放在共享目录中. 例如可以放在桌面上. 因为安装过程中需要建立
ln -sf libjemalloc.so.2 lib/libjemalloc.so
软链在共享目录的分区情况下会出问题(因为我的Ubuntu 是在 VMWare 中, 共享目录无法软链).
那我们开始编译搞起
gcc -g -Wall -o main.out main.c -ljemalloc -DJEMALLOC_NO_DEMANGLE
到这里关于jemalloc的部署开发环境就已经搭建完毕.
当然了, 如果配置已经很ok. 可以不用加 -ljemalloc 因为已经在系统路径下面可以找见.
正文 - 实际中包装 jemalloc
jemalloc 库核心在于替换c runtime lib 的malloc. 为性能要求高的程序引入一层内存池加速和内存碎片的优化.
在实际项目开发中还需要封装一层. 请收看我下面的封装模块
stdext.h
#ifndef _H_STDEXIT #define _H_STDEXIT /* stdxxx.h 扩展库 主要功能 : 扩展内存分配 */ #include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <stdint.h> #include <stddef.h> #include <stdbool.h> // // free_ext - free 包装函数 // ptr : 通过下面函数分配的内存, 必须通过这个函数销毁 // return : void // extern void free_ext(void * ptr); // // malloc_ext - malloc 包装, 封装一些业务特性代码 // size : 分配的内存字节 // return : 返回可使用的内存地址. // extern void * malloc_ext(size_t size); // // calloc_ext - calloc 包装, 封装一些特殊业务 // num : 数量 // size : 大小 // return : 返回可用内存地址, 并且置0 // extern void * calloc_ext(size_t num, size_t size); // // realloc_ext - realoc 包装函数, 封装一些特殊业务 // ptr : 重新分配的内存首地址, NULL 等同于 malloc // size : 重新分配的内存大小 // return : 返回重新分配好的新地址内容 // extern void * realloc_ext(void * ptr, size_t size); // // 开启全局配置 free / malloc 功能 // #if !defined(_NO_STDEXT_) # undef free # undef malloc # undef calloc # undef realloc # define free free_ext # define malloc malloc_ext # define calloc calloc_ext # define realloc realloc_ext #endif #endif//_H_STDEXIT
系统级别的小包装,在需要的地方直接引入 #include <stdext.h> 其它代码还是 malloc free那样保持不变, 就使用起来了, 很方便.
stdext.c
实现层面非常粗暴, 没有引入内存cookie机制. 直接采用默认 Release new / delete 方式. 很直接很方便~
#include <stdio.h> #include <jemalloc/jemalloc.h> // // 编译导入 // gcc -I./structc/system 编译链接不了 -ljemalloc // #define _NO_STDEXT_ #include "stdext.h" // // free_ext - free 包装函数 // ptr : 通过下面函数分配的内存, 必须通过这个函数销毁 // return : void // inline void free_ext(void * ptr) { je_free(ptr); } // 简单错误信息打印 static inline void _ext(void * ptr, size_t size) { fprintf(stderr, "alloc error ptr = %p, size = %zu!\n", ptr, size); fflush(stderr); abort(); } // // malloc_ext - malloc 包装, 封装一些业务特性代码 // size : 分配的内存字节 // return : 返回可使用的内存地址. // inline void * malloc_ext(size_t size) { void * ptr = je_malloc(size); if (NULL == ptr) _ext(ptr, size); return ptr; } // // calloc_ext - calloc 包装, 封装一些特殊业务 // num : 数量 // size : 大小 // return : 返回可用内存地址, 并且置0 // inline void * calloc_ext(size_t num, size_t size) { void * ptr = je_calloc(num, size); if (NULL == ptr) _ext(ptr, num * size); return ptr; } // // realloc_ext - realoc 包装函数, 封装一些特殊业务 // ptr : 重新分配的内存首地址, NULL 等同于 malloc // size : 重新分配的内存大小 // return : 返回重新分配好的新地址内容 // inline void * realloc_ext(void * ptr, size_t size) { void * nptr = je_realloc(ptr, size); if (NULL == nptr) { je_free(ptr); // 可有可无, 内存模块已经是未定义行为的边缘了 _ext(ptr, size); } return ptr; }
这里需要注意一下. 上面所有代码至少保证了 winds, linux 使用正常. 而在linux gcc 环境有个坑就是.
单纯的用 gcc -I 导入头文件目录. 会诱发生成的stdext.o 没有引入 jemalloc 相关指向代码.
我的解决方案是重新编译, 去掉编译的 -I当前stdext.c 所在目录, 为stdext.o重新来一个.
更加核心的可以看这个项目, 一个围绕 c 数据结构搭建一套基础项目架构, 内嵌了jemalloc跨平台使用的细节部分.
structc : https://github.com/wangzhione/structc
到这里关于 jemalloc 完全攻略已经完毕. 扫盲基本 Over ~_~
后记 - 跑pc性能服务必备吧
错误是难免的欢迎指正. 修改 :)
一生何求 : http://music.163.com/#/m/song?id=65642&userid=16529894