Rumah pembangunan bahagian belakang tutorial php 浅谈PHP源码三十一:PHP内存池中的堆(heap)层基础

浅谈PHP源码三十一:PHP内存池中的堆(heap)层基础

Jun 29, 2018 am 09:50 AM

这篇文章主要介绍了关于浅谈PHP源码三十一:PHP内存池中的堆(heap)层基础,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

浅谈PHP源码三十一:PHP内存池中的堆(heap)层基础

【概述】
PHP的内存管理器是分层(hierarchical)的。这个管理器共有三层:存储层(storage)、堆(heap)层和 emalloc/efree 层。在PHP源码阅读笔记三十:PHP内存池中的存储层中介绍了存储层,存储层通过 malloc()、mmap() 等函数向系统真正的申请内存,并通过 free() 函数释放所申请的内存。存储层通常申请的内存块都比较大,这里申请的内存大并不是指storage层结构所需要的内存大,只是堆层通过调用存储层的分配方法时,其以段的格式申请的内存比较大,存储层的作用是将内存分配的方式对堆层透明化。
在存储层之上就是今天我们要了解的堆层。堆层一个调度层,它与上面的emalloc/efree层交互,将通过存储层申请到的大块内存,进行拆分,按需提供。在堆层中有其一套内存的调度策略,这个整个PHP内存分配管理的核心区域。

以下的所有分享都是基于ZEND_DEBUG未打开的情况。
首先看下堆层所涉及到的结构:
【结构】

 /* mm block type */typedef struct _zend_mm_block_info {
size_t _size;/* block的大小*/
size_t _prev;/* 计算前一个块有用到*/} zend_mm_block_info; 
 typedef struct _zend_mm_block {
zend_mm_block_info info;} zend_mm_block; typedef struct _zend_mm_small_free_block {/* 双向链表 */
zend_mm_block_info info;
struct _zend_mm_free_block *prev_free_block;/* 前一个块 */
struct _zend_mm_free_block *next_free_block;/* 后一个块 */} zend_mm_small_free_block;/* 小的空闲块*/ typedef struct _zend_mm_free_block {/* 双向链表 + 树结构 */
zend_mm_block_info info;
struct _zend_mm_free_block *prev_free_block;/* 前一个块 */
struct _zend_mm_free_block *next_free_block;/* 后一个块 */ struct _zend_mm_free_block **parent;/* 父结点 */
struct _zend_mm_free_block *child[2];/* 两个子结点*/} zend_mm_free_block; 
 
 struct _zend_mm_heap {
int                 use_zend_alloc;/* 是否使用zend内存管理器 */
void               *(*_malloc)(size_t);/* 内存分配函数*/
void                (*_free)(void*);/* 内存释放函数*/
void               *(*_realloc)(void*, size_t);
size_t              free_bitmap;/* 小块空闲内存标识 */
size_t              large_free_bitmap;  /* 大块空闲内存标识*/
size_t              block_size;/* 一次内存分配的段大小,即ZEND_MM_SEG_SIZE指定的大小,默认为ZEND_MM_SEG_SIZE   (256 * 1024)*/
size_t              compact_size;/* 压缩操作边界值,为ZEND_MM_COMPACT指定大小,默认为 2 * 1024 * 1024*/
zend_mm_segment    *segments_list;/* 段指针列表 */
zend_mm_storage    *storage;/* 所调用的存储层 */
size_t              real_size;/* 堆的真实大小 */
size_t              real_peak;/* 堆真实大小的峰值 */
size_t              limit;/* 堆的内存边界 */
size_t              size;/* 堆大小 */
size_t              peak;/* 堆大小的峰值*/
size_t              reserve_size;/* 备用堆大小*/
void               *reserve;/* 备用堆 */
int                 overflow;/* 内存溢出数*/
int                 internal;#if ZEND_MM_CACHE
unsigned int        cached;/* 已缓存大小 */
zend_mm_free_block *cache[ZEND_MM_NUM_BUCKETS];/* 缓存数组/
#endif
zend_mm_free_block *free_buckets[ZEND_MM_NUM_BUCKETS*2];/* 小块空闲内存数组 */
zend_mm_free_block *large_free_buckets[ZEND_MM_NUM_BUCKETS];/* 大块空闲内存数组*/
zend_mm_free_block *rest_buckets[2];/* 剩余内存数组 */ };
Salin selepas log masuk

对于heap结构中的内存操作函数,如果use_zend_alloc为否,则使用malloc-type 内存分配,此时所有的操作就不经过堆层中的内存管理,直接采用malloc等函数。

compact_size的大小默认为 2 * 1024 * 1024(2M),如果有设置变量ZEND_MM_COMPACT则为此指定大小,如果内存的峰值超过这个值,则会调用storage的compact函数,只是这个函数现在的实现为空,可能在后续的版本中添加。

reserve_size为备用堆的大小,默认情况下为ZEND_MM_RESERVE_SIZE,其大小为(8*1024)
*reserve为备用堆,其大小为reserve_size,其用作内存溢出时报告错误用。

【关于USE_ZEND_ALLOC】
环境变量 USE_ZEND_ALLOC 可用于允许在运行时选择 malloc 或 emalloc 内存分配。使用 malloc-type 内存分配将允许外部调试器观察内存使用情况,而 emalloc 分配将使用 Zend 内存管理器抽象,要求进行内部调试。
[zend_startup() -> start_memory_manager() -> alloc_globals_ctor()]

static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC){
char *tmp;
alloc_globals->mm_heap = zend_mm_startup(); 
tmp = getenv("USE_ZEND_ALLOC");
if (tmp) {
alloc_globals->mm_heap->use_zend_alloc = zend_atoi(tmp, 0);
if (!alloc_globals->mm_heap->use_zend_alloc) {/* 如果不使用zend的内存管理器,同直接使用malloc函数*/
alloc_globals->mm_heap->_malloc = malloc;
alloc_globals->mm_heap->_free = free;
alloc_globals->mm_heap->_realloc = realloc;
}
}}
Salin selepas log masuk

【初始化】

[zend_mm_startup()]
初始化storage层的分配方案,初始化段大小,压缩边界值,并调用zend_mm_startup_ex()初始化堆层。

[zend_mm_startup() -> zend_mm_startup_ex()]
【内存对齐】
在PHP的内存分配中使用了内存对齐,内存对齐计算显然有两个目标:一是减少CPU的访存次数;第二个就是还要保持存储空间的效率足够高。

 # define ZEND_MM_ALIGNMENT 8 #define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1) 
 #define ZEND_MM_ALIGNED_SIZE(size)(((size) + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK) 
 #define ZEND_MM_ALIGNED_HEADER_SIZEZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block))
 #define ZEND_MM_ALIGNED_FREE_HEADER_SIZEZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block))
Salin selepas log masuk

PHP在分配块的内存中,用到内存对齐,如果所需要的内存的大小的低三位不为0(不能为8整除),则将低三位加上7,并~7进行与操作,即对于大小不是8的整数倍的内存大小补全到可以被8整除。
在win32机器上,一些宏对应的数值大小为:
ZEND_MM_MIN_SIZE=8
ZEND_MM_MAX_SMALL_SIZE=272
ZEND_MM_ALIGNED_HEADER_SIZE=8
ZEND_MM_ALIGNED_FREE_HEADER_SIZE=16
ZEND_MM_MIN_ALLOC_BLOCK_SIZE=8
ZEND_MM_ALIGNED_MIN_HEADER_SIZE=16
ZEND_MM_ALIGNED_SEGMENT_SIZE=8

如果要分配一个大小为9个字节的块,则其实际分配的大小为ZEND_MM_ALIGNED_SIZE(9 + 8)=24

【块的定位】
所分配的内存的右边的两位是用来标记内存的类型。
其大小的定义为#define ZEND_MM_TYPE_MASK ZEND_MM_LONG_CONST(0×3)

如下所示代码为块的定位

 #define ZEND_MM_NEXT_BLOCK(b)ZEND_MM_BLOCK_AT(b, ZEND_MM_BLOCK_SIZE(b))
 #define ZEND_MM_PREV_BLOCK(b)ZEND_MM_BLOCK_AT(b, -(int)((b)->info._prev & ~ZEND_MM_TYPE_MASK)) 
 #define ZEND_MM_BLOCK_AT(blk, offset)((zend_mm_block *) (((char *) (blk))+(offset)))
 #define ZEND_MM_BLOCK_SIZE(b)((b)->info._size & ~ZEND_MM_TYPE_MASK)#define ZEND_MM_TYPE_MASKZEND_MM_LONG_CONST(0x3)
Salin selepas log masuk

当前块的下一个元素,即为当前块的头位置加上整个块(去掉了类型的长度)的长度。
当前块的上一个元素,即为当前块的头位置减去前一个块(去掉了类型的长度)的长度。
关于前一个块的长度,在块的初始化时设置为当前块的大小与块类型的或操作的结果。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

浅谈PHP源码三十:PHP内存池中的存储层

浅谈PHP源码二十九:关于接口的继承

浅谈PHP源码二十八:关于类结构和继承

Atas ialah kandungan terperinci 浅谈PHP源码三十一:PHP内存池中的堆(heap)层基础. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Pembalakan PHP: Amalan Terbaik untuk Analisis Log PHP Pembalakan PHP: Amalan Terbaik untuk Analisis Log PHP Mar 10, 2025 pm 02:32 PM

Pembalakan PHP adalah penting untuk memantau dan menyahpepijat aplikasi web, serta menangkap peristiwa kritikal, kesilapan, dan tingkah laku runtime. Ia memberikan pandangan yang berharga dalam prestasi sistem, membantu mengenal pasti isu -isu, dan menyokong penyelesaian masalah yang lebih cepat

Bekerja dengan Data Sesi Flash di Laravel Bekerja dengan Data Sesi Flash di Laravel Mar 12, 2025 pm 05:08 PM

Laravel memudahkan mengendalikan data sesi sementara menggunakan kaedah flash intuitifnya. Ini sesuai untuk memaparkan mesej ringkas, makluman, atau pemberitahuan dalam permohonan anda. Data hanya berterusan untuk permintaan seterusnya secara lalai: $ permintaan-

Curl dalam PHP: Cara Menggunakan Pelanjutan PHP Curl dalam API REST Curl dalam PHP: Cara Menggunakan Pelanjutan PHP Curl dalam API REST Mar 14, 2025 am 11:42 AM

Pelanjutan URL Pelanggan PHP (CURL) adalah alat yang berkuasa untuk pemaju, membolehkan interaksi lancar dengan pelayan jauh dan API rehat. Dengan memanfaatkan libcurl, perpustakaan pemindahan fail multi-protokol yang dihormati, php curl memudahkan execu yang cekap

Respons HTTP yang dipermudahkan dalam ujian Laravel Respons HTTP yang dipermudahkan dalam ujian Laravel Mar 12, 2025 pm 05:09 PM

Laravel menyediakan sintaks simulasi respons HTTP ringkas, memudahkan ujian interaksi HTTP. Pendekatan ini dengan ketara mengurangkan redundansi kod semasa membuat simulasi ujian anda lebih intuitif. Pelaksanaan asas menyediakan pelbagai jenis pintasan jenis tindak balas: Gunakan Illuminate \ Support \ Facades \ http; Http :: palsu ([ 'Google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =>

12 skrip sembang php terbaik di codecanyon 12 skrip sembang php terbaik di codecanyon Mar 13, 2025 pm 12:08 PM

Adakah anda ingin memberikan penyelesaian segera, segera kepada masalah yang paling mendesak pelanggan anda? Sembang langsung membolehkan anda mempunyai perbualan masa nyata dengan pelanggan dan menyelesaikan masalah mereka dengan serta-merta. Ia membolehkan anda memberikan perkhidmatan yang lebih pantas kepada adat anda

Terangkan konsep pengikatan statik lewat dalam PHP. Terangkan konsep pengikatan statik lewat dalam PHP. Mar 21, 2025 pm 01:33 PM

Artikel membincangkan pengikatan statik lewat (LSB) dalam PHP, yang diperkenalkan dalam Php 5.3, yang membolehkan resolusi runtime kaedah statik memerlukan lebih banyak warisan yang fleksibel. Isu: LSB vs polimorfisme tradisional; Aplikasi Praktikal LSB dan Potensi Perfo

Menyesuaikan/Memperluas Rangka Kerja: Cara Menambah Fungsi Custom. Menyesuaikan/Memperluas Rangka Kerja: Cara Menambah Fungsi Custom. Mar 28, 2025 pm 05:12 PM

Artikel ini membincangkan menambah fungsi khusus kepada kerangka kerja, memberi tumpuan kepada pemahaman seni bina, mengenal pasti titik lanjutan, dan amalan terbaik untuk integrasi dan debugging.

See all articles