tcmalloc

Linux(服务器编程):36---C/C++内存池设计(仿Nginx内存池设计)

二次信任 提交于 2020-08-04 11:15:20
一、内存池概述 服务器会频繁地对内存进行申请和释放,频繁地操作将带来如下的缺点: 服务器性能降低,因为需要频繁地申请和释放内存 内存碎片化多 等等...... 市场上开源的比较好用的内存池有: tcmalloc:MySQL使用的 jemalloc:Tomcat使用的 Nginx也有一套自己的内存池(本文就是仿照Nginx的内存池设计的) 二、内存池设计 因为内存页的大小为4K,因此在设计内存池的时候,我们将认为: <4k的内存:称为小内存块 >4K的内存:称为大内存快 struct mp_large_s(大内存块结构) 当我们申请的内存大于4K时,就会申请一个大的内存块,这个结构体就是大内存结构 该结构不是真正存储内存的,真正的内存是由其alloc成员所指向的 如上结构图所示(蓝色部分): alloc:指向真正的大内存块地址 next:指向下一个struct mp_large_s结构的指针 //大内存块节点 struct mp_large_s { void *alloc; //指向该大内存快的实际存储区域 struct mp_large_s *next; //指向下一块大内存快 }; struct mp_node_s(大内存块结构) 当我们申请的内存小于4K时,就会申请一个小的内存块,这个结构体就是小内存结构 与struct mp_large_s结构一样,该结构不是真正存储内存的

Go是如何生活在内存条里的【译】

坚强是说给别人听的谎言 提交于 2020-04-28 04:29:27
原文: A visual guide to Go Memory Allocator from scratch (Golang) 当我第一次开始试图了解 Go 的内存分配器时,觉得它真令人抓狂。所有的所有都像是神秘的黑盒子。而由于几乎每一个技术魔法都隐藏在抽象之下,因此,你需要层层剥开才能理解它。 因此,在这篇博文中,我们将就做这件事。你想学习关于 Go 内存分配器的所有东西吗?那么,阅读这篇文章算是对了。 物理内存和虚拟内存 每一个内存分配器都需要使用由底层操作系统管理的虚拟内存空间。我们来看看它是如何工作的。 上图为物理内存单元的一个简单说明(并非精确表示) 单个内存单元的大大简化概述: 地址线(晶体管作为开关)提供对电容器(数据到数据线) 的访问。 当地址线有电流流动时(显示为红色),那么数据线可以写入电容器,因此,电容器充电,存储的逻辑值为“1”。 当地址线没有电流流动时(显示为绿色),那么数据线 不可以写入电容器,因此,电容器未充电,存储的逻辑值为“0”。 当 CPU 需要从 RAM“读取”值时,电流会沿着“地址线”发送(关闭开关)。如果电容器正处于充电状态,那么电流则沿着“数据线”向下流动(值为 1);否则,没有电流流过数据线,故而电容器保持不带电状态(值为 0)。 (上图为物理内存单元与 CPU 交互方式的简单说明) 数据总线: 在 CPU 和物理内存之间传输数据。

Redis核心原理与应用实践

◇◆丶佛笑我妖孽 提交于 2020-04-16 11:09:16
【推荐阅读】微服务还能火多久?>>> Redis核心原理与应用实践 在很多场景下都会使用Redis,但是到了深层次的时候就了解的不是那么深刻,以至于在面试的时候经常会遇到卡壳的现象,学习知识要做到系统和深入,不要把Redis想象的过于复杂,和Mysql一样,是个读取数据的软件。 有一个理解是Redis是key value缓存服务器,更多的优点在于对value的操作更加丰富。 安装 yum install redis #yum安装 brew install redis # brew安装 redis-cli Redis 基础数据结构 Redis 有 5 种基础数据结构,分别为:string (字符串)、list (列表)、set (集合)、hash (哈希) 和 zset (有序集合)。 string (字符串) Redis 的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配,如图中所示,内部为当前字 符串实际分配的空间 capacity 一般要高于实际字符串长度 len。当字符串长度小于 1M 时, 扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。需要注意的是 字符串最大长度为 512M。 键值对 set name codehole get name 批量键值对

pgoneproxy使用tcmalloc来管理内存

非 Y 不嫁゛ 提交于 2020-03-01 17:35:41
pgoneproxy本身是使用glib来进行操作的,故有部分的内存管理功能。glib中提供了g_slice_alloc,g_slice_alloc0,g_slice_new, g_slice_new0, g_slice_free1,g_slice_free来进行内存的管理。通过这些函数来申请内存时,是根据大小到内存池或者调用系统内存分配函数来申请内存的。 但是pgoneproxy中使用了大量的g_new0,g_new,g_free函数,这些函数通过glib代码可以知道是通过直接调用系统函数来分配内存的。故会大量的调用系统的malloc以及free函数。在运行时可以通过perf top来观察得到下面的情况: 从上面中可以看到_int_malloc,_int_free函数占有很大的比例。这些函数应该就是直接调用glibc中malloc函数以及free函数导致的。目前想把这个情况给优化掉,故采用了Google的tcmalloc。在链接时链接了/usr/local/lib/libtcmalloc_minimal.a静态库。这样可以通过tcmalloc来管理内存的申请,从而减少glibc中malloc,free函数的调用,从而减少系统函数的调用。 增加tcmalloc后,perf top的结果如下所示: 从上面的样本可以看到没有了_int_malloc,_int_free函数了

启动MySQL如何加载Jemalloc

≯℡__Kan透↙ 提交于 2020-02-27 18:14:42
作者:叶金荣,知数堂联合创始人 如何加载Jemalloc。 有时候,我们想采用Jemalloc代替glibc自带的lib库,或者如果想启用TokuDB引擎,则就必须启用Jemalloc才行了。 如果通过搜索引擎找到如何加载Jemalloc方法时,可能会看到像下面这种建议: #修改my.cnf文件 [mysqld_safe]配置区间,加上Jemalloc选项[mysqld_safe]thp-setting = nevermalloc-lib = /usr/lib64/libjemalloc.so 实际上这种做法现在已经不能用了。尤其是从MySQL 5.7版本开始,已经默认不使用 mysqld_safe 来启动了,可以改用下面的方法: #在启动mysqld之前,执行命令export LD_PRELOAD=/lib64/libjemalloc.so#然后再正常启动mysqld即可,例如/usr/local/mysql/bin/mysqld --default-file=/mysql/mysql-8.0/my.cnf & LD_PRELOAD是个环境变量,用于动态库的加载,动态库加载的优先级最高。 一般情况下,其加载顺序为: LD_PRELOAD>LD_LIBRARY_PATH => /etc/ld.so.cache => /lib => /usr/lib

【巨杉数据库SequoiaDB】巨杉Tech | 巨杉数据库的并发 malloc 实现

江枫思渺然 提交于 2020-02-25 19:39:31
本文由巨杉数据库北美实验室资深数据库架构师撰写,主要介绍巨杉数据库的并发malloc实现与架构设计。 原文为英文撰写,我们提供了中文译本在英文之后。 SequoiaDB Concurrent malloc Implementation Introduction In a C/C++ application, the dynamic memory allocation function malloc(3) can have a significant impact on the application’s performance. For multi-threaded applications such as a database engine, a sub-optimal memory allocator can also limit the scalability of the application. In this paper, we will discuss several popular dynamic memory allocator, and how SequoiaDB addresses the dynamic memory allocation problem in its database engine. dlmalloc/ptmalloc The GNU C

Compiling Python 2.6.6 and need for external packages wxPython, setuptools, etc… in Ubuntu

耗尽温柔 提交于 2020-01-20 07:13:41
问题 I compiled Python 2.6.6 with google-perf tools (tcmalloc) library to eliminate some of the memory issues I was having with the default 2.6.5. After getting 2.6.6 going it seems to not work becuase I think having issues with the default 2.6.5 install in Ubuntu. Will none of the binaries installed from the software channel like wxPython and setuptools work properly with 2.6.6. Do these need to be recompiled? Any other suggestions to get it working smoothly. Can I still set 2.6.5 as default

Compiling Python 2.6.6 and need for external packages wxPython, setuptools, etc… in Ubuntu

独自空忆成欢 提交于 2020-01-20 07:13:26
问题 I compiled Python 2.6.6 with google-perf tools (tcmalloc) library to eliminate some of the memory issues I was having with the default 2.6.5. After getting 2.6.6 going it seems to not work becuase I think having issues with the default 2.6.5 install in Ubuntu. Will none of the binaries installed from the software channel like wxPython and setuptools work properly with 2.6.6. Do these need to be recompiled? Any other suggestions to get it working smoothly. Can I still set 2.6.5 as default

深入了解tcmalloc(一):windows环境下无缝拦截技术初探

三世轮回 提交于 2019-12-26 02:07:58
概述: 又到了一个总结提炼的阶段,这次想具体聊聊游戏引擎中使用的内存管理模块tcmalloc组件的使用心得。项目的前期曾经遇到过内存瓶颈,特别是windows系统下的客户端程序在经历长时间运行之后会出现内存占用率很高疑似泄漏的现象,排查了很久都没有找到原因,甚至一度无法定位问题出自游戏脚本层还是引擎层,后来在引擎中链接了tcmalloc组件,通过实时dump程序的内存信息最终找出了泄漏的元凶。tcmalloc的另一个优势就是通过高效率内存分配来提高游戏运行时性能,不得不说在使用tcmalloc之后,整个游戏的稳定性和效率都有了很大的提升。为了今后更有效和稳定地使用tcmalloc组件,就在这里深入剖析一下这个神器。Tcmalloc是 Google Perftools 中的一个组件,提供一整套高效健壮的内存管理方案,比传统glibc的内存分配和释放要快数倍;其次,基于tcmalloc之上的heapprofiler可以实时dump程序中heap的使用信息,是一个很好的检测内存泄漏的辅助工具;同时tcmalloc的使用又是极其方便,只需要在编译时增加一个链接选项,就可以无缝拦截(patch)原生操作系统运行库中的内存分配和释放接口,而无需修改已经完成的项目工程代码,大大减少移植整合的成本。 在windows平台下,tcmalloc可以通过静态库或者动态库(DLL)的形式嵌入到工程里面

Why tcmalloc don't print function name, which provided via dlopen

≡放荡痞女 提交于 2019-12-11 10:39:48
问题 I have next some project: main.cpp #include <iostream> #include <cstddef> #include <dlfcn.h> int main() { void* handle = dlopen("./shared_libs/libshared.so", RTLD_LAZY); if (NULL == handle) { std::cerr << "Cannot open library: " << dlerror() << '\n'; return -1; } typedef int (*foo_t)(const std::size_t); foo_t foo = reinterpret_cast<foo_t>(dlsym(handle, "foo")); const char* dlsym_error = dlerror(); if (dlsym_error) { std::cerr << "Cannot load symbol 'foo': " << dlsym_error << '\n'; dlclose