


Several difficult points in memory management of PHP principles_PHP tutorial
PHP’s memory management is divided into two parts. The first part is PHP’s own memory management. The main content of this part is reference counting, copy-on-write, and other application-oriented management. The second part is what I want to introduce today. The memory management of PHP itself described in zend_alloc, including how it manages available memory, how to allocate memory, etc.
In addition, why should I write this, because it has not been done before There is no information to introduce the strategies, data structures, or algorithms used in PHP memory management. But when we usually develop extensions and fix PHP bugs, we need to have a good understanding of this part of the knowledge. Within the PHP development team Many of my friends are not very clear about this, so I think it is necessary to write about it.
I won’t go into details about some basic concepts, because it is easy to understand by looking at the code, so I will focus here Let me introduce a few points that are not easy to understand when looking at the code. Why do I say this? Haha, before writing the article, I searched for existing information to avoid duplication of work. I saw the description of this part of the TIPI project. I found a lot of errors in it. So, I think this part is not easy to understand even if you look at the code
Currently, the English version of the introduction is also being written: Zend MM
Zend Memory Manager, hereafter referred to as Zend MM, is the logic of memory management in PHP. There is a key data structure: zend_mm_heap:
Zend MM divides memory into two types: small memory and large memory, and treats them differently. For small memory, This part is the most commonly used, so high performance is pursued. For large blocks of memory, stability is pursued and memory waste is avoided as much as possible.
Therefore, for small blocks of memory, PHP also introduces a cache mechanism:

Zend MM Hope Try to do it through cache, and the allocation can be found in one location.
One point that is not easy to understand is the declaration of free_buckets:
Q: Why is the length of the free_buckets array ZEND_MM_NUMBER_BUCKET?
A: This is because PHP uses a trick here, using a fixed-length array to store ZEND_MM_NUMBER_BUCKET zend_mm_free_blocks, as shown in the red box in the picture above. For an element of free_buckets that is not used, The only useful data structures are next_free_block and prev_free_block. Therefore, in order to save memory, PHP does not allocate ZEND_MM_NUMBER_BUCKET * sizeof(zend_mm_free_block) size of memory, but only uses ZEND_MM_NUMBER_BUCKET * (sizeof(*next_free_block) + sizeof(*prev_free_block)) size. memory..
Let’s look at the definition of the ZEND_MM_SMALL_FREE_BUCKET macro:
<ol class="dp-xml"> <li class="alt"><span><span>#define ZEND_MM_SMALL_FREE_BUCKET(heap, index) </span></span></li> <li> <span> (zend_mm_free_block*) ((char*)&heap-</span><span class="tag">></span><span>free_buckets[index * 2] + </span> </li> <li class="alt"><span> sizeof(zend_mm_free_block*) * 2 - </span></li> <li><span> sizeof(zend_mm_small_free_block)) </span></li> </ol>
After that, Zend MM guarantees that it will only use the prev and next pointers, so it will not cause memory read errors. .
Then, the second point that is not easy to understand is PHP’s management of large_free_buckets. Let’s first introduce the allocation (the TIPI project team’s description of this part is somewhat vague):
<ol class="dp-xml"><li class="alt"><span><span>static zend_mm_free_block *zend_mm_search_large_block(zend_mm_heap *heap, size_t true_size) </span></span></li></ol>
large_free_buckets can be said to be a combination of tree building and two-way list:

large_free_buckets uses a macro to determine what index a memory of a certain size falls on:
<ol class="dp-c"><li class="alt"><span><span>#define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S) </span></span></li></ol>
zend_mm_high_bit gets the serial number of the highest 1 in true_size (zend_mm_high_bit ), the corresponding assembly instruction is bsr (here, the error description of the TIPI project is: "This hash function is used to calculate the number of digits in size, and the return value is the number of 1's in the binary code of size - 1").
In other words, each element in large_free_buckets maintains a pointer to a memory block with a size of 1 at the corresponding index. Oh, that’s a bit convoluted, for example:
For example, large_free_buckets[2] will only save memory with a size of 0b1000 to 0b1111. Another example: large_free_buckets[6] will save pointers of memory with a size of 0b10000000 to 0b11111111.
In this way, when re-allocating memory, Zend MM can quickly locate the most suitable area for search. Improve performance.
And, each element is also a two-way list, maintaining the same size memory block, and the left and right children (child[0] and child[1]) represent the key values 0 and 1 respectively. What does this key value refer to?
Let’s give an example. For example, I asked PHP applied for a memory with true_size of 0b11010. After some steps, no suitable memory was found. PHP entered the zend_mm_search_large_block logic to find suitable memory in large_free_buckets:
1. First, calculate the corresponding true_size index, the calculation method is as described before ZEND_MM_LARGE_BUCKET_INDEX
2. 然后在一个位图结构中, 判断是否存在一个大于true_size的可用内存已经存在于large_free_buckets, 如果不存在就返回:
<ol class="dp-c"> <li class="alt"><span><span>size_t bitmap = heap->large_free_bitmap >> index; </span></span></li> <li> <span class="keyword">if</span><span> (bitmap == 0) { </span> </li> <li class="alt"> <span> </span><span class="keyword">return</span><span> NULL; </span> </li> <li><span>} </span></li> </ol>
3. 判断, free_buckets[index]是否存在可用的内存:
<ol class="dp-c"><li class="alt"><span><span class="keyword">if</span><span> (UNEXPECTED((bitmap & 1) != 0)) </span></span></li></ol>
4. 如果存在, 则从free_buckets[index]开始, 寻找最合适的内存, 步骤如下:
4.1. 从free_buckets[index]开始, 如果free_buckets[index]当前的内存大小和true_size相等, 则寻找结束, 成功返回.
4.2. 查看true_size对应index后(true_size child[1]下面继续寻找, 如果free_buckets[index]->child[1]不存在, 则跳出. 如果true_size的当前最高位为0, 则在free_buckets[index]->child[0]下面继续寻找, 如果free_buckets[index]->child[0]不存在, 则在free_buckets[index]->child[1]下面寻找最小内存(因为此时可以保证, 在free_buckets[index]->child[1]下面的内存都是大于true_size的)
4.3. 出发点变更为2中所述的child, 左移一位ture_size.
5. 如果上述逻辑并没有找到合适的内存, 则寻找最小的”大块内存”:
<ol class="dp-c"> <li class="alt"><span><span class="comment">/* Search for smallest "large" free block */</span><span> </span></span></li> <li><span> best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)]; </span></li> <li class="alt"> <span> </span><span class="keyword">while</span><span> ((p = p->child[p->child[0] != NULL])) { </span> </li> <li> <span> </span><span class="keyword">if</span><span> (ZEND_MM_FREE_BLOCK_SIZE(p) </span> </li> <li class="alt"><span> best_fit = p; </span></li> <li><span> } </span></li> <li class="alt"><span> } </span></li> </ol>
注意上面的逻辑, (p = p->child[p->child[0] != NULL]), PHP在尽量寻找最小的内存.
为什么说, large_free_buckets是个键树呢, 从上面的逻辑我们可以看出, PHP把一个size, 按照二进制的0,1做键, 把内存大小信息反应到了键树上, 方便了快速查找.
另外, 还有一个rest_buckets, 这个结构是个双向列表, 用来保存一些PHP分配后剩下的内存, 避免无意义的把剩余内存插入free_buckets带来的性能问题(此处, TIPI项目错误的描述为: “这是一个只有两个元素的数组。 而我们常用的插入和查找操作是针对第一个元素,即heap->rest_buckets[0]“).
作者: Laruence( ) 原文地址:

Thedifferencebetweenunset()andsession_destroy()isthatunset()clearsspecificsessionvariableswhilekeepingthesessionactive,whereassession_destroy()terminatestheentiresession.1)Useunset()toremovespecificsessionvariableswithoutaffectingthesession'soveralls

Stickysessionsensureuserrequestsareroutedtothesameserverforsessiondataconsistency.1)SessionIdentificationassignsuserstoserversusingcookiesorURLmodifications.2)ConsistentRoutingdirectssubsequentrequeststothesameserver.3)LoadBalancingdistributesnewuser

PHPoffersvarioussessionsavehandlers:1)Files:Default,simplebutmaybottleneckonhigh-trafficsites.2)Memcached:High-performance,idealforspeed-criticalapplications.3)Redis:SimilartoMemcached,withaddedpersistence.4)Databases:Offerscontrol,usefulforintegrati

Session in PHP is a mechanism for saving user data on the server side to maintain state between multiple requests. Specifically, 1) the session is started by the session_start() function, and data is stored and read through the $_SESSION super global array; 2) the session data is stored in the server's temporary files by default, but can be optimized through database or memory storage; 3) the session can be used to realize user login status tracking and shopping cart management functions; 4) Pay attention to the secure transmission and performance optimization of the session to ensure the security and efficiency of the application.

PHPsessionsstartwithsession_start(),whichgeneratesauniqueIDandcreatesaserverfile;theypersistacrossrequestsandcanbemanuallyendedwithsession_destroy().1)Sessionsbeginwhensession_start()iscalled,creatingauniqueIDandserverfile.2)Theycontinueasdataisloade

Absolute session timeout starts at the time of session creation, while an idle session timeout starts at the time of user's no operation. Absolute session timeout is suitable for scenarios where strict control of the session life cycle is required, such as financial applications; idle session timeout is suitable for applications that want users to keep their session active for a long time, such as social media.

The server session failure can be solved through the following steps: 1. Check the server configuration to ensure that the session is set correctly. 2. Verify client cookies, confirm that the browser supports it and send it correctly. 3. Check session storage services, such as Redis, to ensure that they are running normally. 4. Review the application code to ensure the correct session logic. Through these steps, conversation problems can be effectively diagnosed and repaired and user experience can be improved.

session_start()iscrucialinPHPformanagingusersessions.1)Itinitiatesanewsessionifnoneexists,2)resumesanexistingsession,and3)setsasessioncookieforcontinuityacrossrequests,enablingapplicationslikeuserauthenticationandpersonalizedcontent.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

WebStorm Mac version
Useful JavaScript development tools

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.
