Nginx内存池相关源码剖析(三)小块内存分配逻辑

在Nginx中,小块内存通常指的是那些大小相对较小、分配和释放频率较高的内存块。这些内存块由于数量众多、管理复杂,因此需要使用一种高效的内存管理机制来减少内存管理的开销和内存碎片的产生。

Nginx内存池通过一种预分配和复用的方式来管理小块内存。当需要分配小块内存时,内存池会首先检查是否已经有可用的内存块。如果有,则直接从中分配一个;如果没有,则根据预设的规则进行内存块的预分配。这种预分配的策略可以确保在需要时能够快速获取到内存块,避免了频繁的malloc和free操作带来的开销。 

ngx_palloc_small函数

分配小块内存空间

static ngx_inline void *
ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align) // align表示是否考虑内存对齐
{
    u_char      *m;
    ngx_pool_t  *p;

    p = pool->current; // 每次都从内存池中current块进行分配内存

    do {
        m = p->d.last; // 可分配内存的起始地址

        if (align) {
            m = ngx_align_ptr(m, NGX_ALIGNMENT); // 将m调整到 平台相关的ulong 的整数倍
        }

        if ((size_t) (p->d.end - m) >= size) { // 内存池空闲内存空间 >= 申请的内存空间
            p->d.last = m + size; // 向下偏移到新的可分配起始地址

            return m;
        }

        p = p->d.next; // 本块剩余空闲内存不够,则向后(小块内存池链上的下一块)寻找

    } while (p);

    // 找到末尾发现当前内存块链表的空闲内存不够用,则调用函数新分配一个内存块
    return ngx_palloc_block(pool, size); 
}

当前剩余空间够用的情况下,直接分配空闲内存的示意图:

ngx_palloc_block函数

当前剩余空间不够用的时候,开辟已一个新的内存块添加到(链接)内存池中,供小内存分配使用。

static void *
ngx_palloc_block(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    size_t       psize;
    ngx_pool_t  *p, *new;

    // 计算pool的带头信息的已使用内存的大小
    psize = (size_t) (pool->d.end - (u_char *) pool); 

    // 开辟内存对齐psize大小的内存块
    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); 
    if (m == NULL) {
        return NULL;
    }

    new = (ngx_pool_t *) m; // new指向新开辟块的起始地址

    new->d.end = m + psize; // 指向新块的末尾地址
    new->d.next = NULL;
    new->d.failed = 0;

    // m指向每块头信息ngx_pool_data_t之后的可用起始地址
    m += sizeof(ngx_pool_data_t); 

    // 调整对齐倍数,准备将m分配出去
    m = ngx_align_ptr(m, NGX_ALIGNMENT); 
    new->d.last = m + size; // 分配出size,指向新空闲地址

	// 对已有的成链的各块,若从current块开始分配内存失败多于4次
	// 说明current块的剩余可用内存很小了,认为很难再分配出去
	// 就将下一个块作为current块
    for (p = pool->current; p->d.next; p = p->d.next) {
        if (p->d.failed++ > 4) {
            pool->current = p->d.next;
        }
    }

    p->d.next = new; // 将内存块成链(尾插法)

    return m; // 返回新分配的给用户的地址
}

调用ngx_palloc_block函数分配新的内存块示意图:

总结——没有释放和回收逻辑

 值得注意的是,Nginx内存池没有提供小块内存的释放和回收的任何逻辑。这是由Nginx的工作环境所决定的。

nginx本质是http服务器,是一个短链接的服务器,客户端(浏览器)发起一个request请求,到达nginx服务器以后,处理完成,nginx给客户端返回一个response响应,http服务器就主动断开tcp连接。即使http 1.1 keep-avlie可以保持60s,但也只是60s。http服务器(nginx)返回响应以后,需要等待60s,60s之内客户端又发来请求,重置这个时间,否则60s之内没有客户端发来的响应,nginx就主动断开连接,此时nginx可以调用ngx_reset_pool重置内存池了,等待下一次该客户端的请求。

所以没有小内存的释放逻辑也是合乎其工作方式,因为每个内存池在一段时间内一定会被reset成空内存池,加上小内存释放逻辑反而可能会降低服务器性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/551476.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Reka团队打造前沿多模态语言模型,展现卓越性能

eka,一家新兴的人工智能公司,近期推出了一系列强大的多模态语言模型 - Reka Core、Reka Flash和Reka Edge。这些模型不仅能处理和推理文本,还能够灵活应对图像、视频和音频等多种输入,在各项测试中表现出色,在某些指标…

AI光芯登上Science,开启算力新纪元

智能光芯片“太极”:清华大学的科技壮举,开启算力新纪元 在科技的浩瀚星海中,每一次创新都是对未知世界的探索和征服。近日,清华大学电子工程系与自动化系的联合团队,凭借其深厚的科研实力和创新精神,研发出…

OpenCV4.10使用形态运算提取水平线和垂直线

返回:OpenCV系列文章目录(持续更新中......) 上一篇:OpenCV的查找命中或未命中 下一篇:OpenCV4.9图像金字塔-CSDN博客 目标 在本教程中,您将学习如何: 应用两个非常常见的形态运算符(即膨胀和…

【贪心 堆 】3081. 替换字符串中的问号使分数最小

算法可以发掘本质,如: 一,若干师傅和徒弟互有好感,有好感的师徒可以结对学习。师傅和徒弟都只能参加一个对子。如何让对子最多。 二,有无限多1X2和2X1的骨牌,某个棋盘若干格子坏了,如何在没有坏…

OpenHarmony社交分享类APP开发实战

介绍 本示例是一个社交分享类APP,搭建了不同的页面向用户提供获取社交信息等能力。为了减少频繁权限弹窗对用户的干扰,同时提供更小的授权范围,使用了安全控件做临时授权场景。当用户实际点击了某种类型的安全控件时,会由系统弹出…

Golang 开发实战day11 - Pass By Value

🏆个人专栏 🤺 leetcode 🧗 Leetcode Prime 🏇 Golang20天教程 🚴‍♂️ Java问题收集园地 🌴 成长感悟 欢迎大家观看,不执着于追求顶峰,只享受探索过程 Golang 开发实战day11 - 按值…

SpringCloud中的nacos配置中心分析

一、概述 nacos可以作为配置管理使用,为各个微服务之间提供统一的配置中心,方便管理所有服务的配置。 二、什么是配置中心? 配置中心:一般SpringBoot项目都使用在resources下创建类似application.yml之类的配置文件来管理整个项目…

微信生态洗牌,私域拥抱公域的逐步试探

一直被人们奉为“私域神器”的微信,如今,变化越来越大了,微信的几次更新,透露出很多不一样的信息,在微信的很多使用场景中,都逐渐在向平台化公域流量分发的方向发展,不断的尝试从私域走向公域&a…

2024年【起重机械指挥】考试题及起重机械指挥复审模拟考试

题库来源:安全生产模拟考试一点通公众号小程序 起重机械指挥考试题是安全生产模拟考试一点通总题库中生成的一套起重机械指挥复审模拟考试,安全生产模拟考试一点通上起重机械指挥作业手机同步练习。2024年【起重机械指挥】考试题及起重机械指挥复审模拟…

社科院与新加坡社科大学工商管理博士——在职读博行而不辍,未来可期

在职读博,对于许多人来说,既是一种挑战,也是一种机遇。它要求我们在繁忙的工作之余,还要抽出时间来深入研究学术,不断提升自己的专业素养。然而,正是这种行而不辍的精神,让我们能够在职业生涯中…

C++类和对象:构造函数,析构函数,拷贝构造

文章目录 1.类的6个默认成员函数2. 构造函数2.1 概念2.2 特性 3.析构函数3.1 概念3.2 特性 4.拷贝构造 1.类的6个默认成员函数 一个类中什么都不写,就是空类。而空类实际上有成员,当一个类中什么都不写时,编译器会生成六个对应默认成员函数。…

解读我国最新网络安全运维与数据处理安全规范:强化数字化时代安全基石

近日,全国网络安全标准化技术委员会秘书处公布了一系列重要的网络安全与数据安全相关技术规范草案,包括《网络安全技术 网络安全运维实施指南》、《网络安全技术 信息系统灾难恢复规范》以及《数据安全技术 政务数据处理安全要求》。这些规范旨在应对当前…

JavaScript权威指南(第7版) 笔记 - 第 7 章 数组

能用代码说清楚的,绝不多废话!!!!!! Linux创始人Linus的名言:Talk is cheap,show me the code ! ,博主技术博文会精心给出能说明问题的范例代码!…

安装 k8s集群的问题:默认容器运行时从 Docker 改为 Containerd

安装 k8s集群的问题:默认容器运行时从 Docker 改为 Containerd 1、背景2、容器运行时从 Docker 改为 Containerd2.1、安装 Containerd:2.2、生成 Containerd 的配置文件2.3 、创建 /etc/crictl.yaml 文件2.4 、配置 Containerd 服务开机自启 &#x1f49…

算法与数据结构要点速学——排序算法

排序算法 所有主要的编程语言都有一个内置的排序方法。假设并说排序成本为 O(n*log n),通常是正确的,其中 n 是要排序的元素数。为了完整起见,这里有一个图表,列出了许多常见的排序算法及其完整性。编程语言实现的算法各不相同&a…

【GDB调试技巧】提高gdb的调试效率

目录 🌞gdb的启动 🌞gdb技巧 🌼1. gdb小技巧汇总 🌼2. 打印输出指定地址的值 🌼3. 查看当前执行到哪行代码代码内容 3.1 方式一:info line 结合 list 。 3.2 方式二:f 3.3 方式三&#…

WebGIS面试题(第五期)

WebGIS面试题(第五期) 以下题目仅为部分题目,全部题目在公众号{GISer世界},答案仅供参考 1、Cesium的核心组件有哪些? Cesium的核心组件包括Viewer、Scene、Model、Geometry、Material和Camera等。其中,…

Latex(从入门到入土)1

第一章:初识Latex 1、安装Latex,当然可以安装官方的开放版本,也可以去找找别人发的资源。我这里只介绍我的学习经过。如果想下载最新的软件资源,我这里推荐微信公众号:软件智库,通过号主提供的网址是可以下…

基于大数据的全国热门景点数据可视化分析系统

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文将介绍如何使用Python中的Pandas库进行数据挖掘,并结合Flask Web框架实现一个旅游景点数据分析系统。该系统将包括以下功能模块:热门景点概况、景点星级与评分分析、景…

Docker 学习笔记(十):Centos7 中 Docker 部署 Redis 集群,打包 SpringBoot 微服务

一、前言 记录时间 [2024-4-17] 系列文章简摘: Docker 学习笔记(六):挑战容器数据卷技术一文通,实战多个 MySQL 数据同步,能懂会用,初学必备 Docker 学习笔记(七)&#x…