Home  >  Article  >  Backend Development  >  Detailed example of how PHP creates shared memory to reduce load

Detailed example of how PHP creates shared memory to reduce load

藏色散人
藏色散人forward
2022-11-03 17:03:033887browse

This article will introduce to you how to create shared memory in PHP to reduce load. Here you need to understand a function shmop. Let’s follow the article to learn~

PHP has two sets of interfaces for memory sharing. One is shm, which is actually variable sharing and will serialize object variables before storing them. It is quite convenient to use, but serialized storage is meaningless for memory access operations that prioritize efficiency. The other one is shmop, which is common to Linux and Windows, but its function is weaker than shm. On Linux, these functions are directly implemented by calling the shm* series of functions, while on Winodows, they are also implemented by encapsulating system functions. made the same call.

To create a shared memory segment, you need to use the function shmop, so the prerequisite is to enable expansion. [Recommended learning: PHP video tutorial]

shmop main function

shmop_open (create or open a shared memory block), shmop_write (write to shared memory block), shmop_read (read data from the shared memory block), shmop_size (get the size of the shared memory block), shmop_close (close the shared memory block), shmop_delete (delete the shared memory block)

<?php
//创建一块共享内存
$shm_key = 0x4337b101;
$shm_id = @shmop_open($shm_key, &#39;c&#39;, 0644, 1024);
//读取并写入数据
$data = shmop_read($shm_id, 0, 1024);
shmop_write($shm_id, json_encode($data), 0);
$size = shmop_size($shm_id); //获取内存中实际数据占用大小
//关闭内存块,并不会删除共享内存,只是清除 PHP 的资源
shmop_close($shm_id);

shmop_open (Create memory segment)

The first thing that appears in this function is the system ID parameter. This is a number that identifies the shared memory segment in the system. The second parameter is the access mode, which is very similar to the access mode of the fopen function. You can access a memory segment in 4 different modes:

Mode "a", which allows you to access a read-only memory segment, read-only access mode "c", which creates a new memory segment, or If the memory segment already exists, try to open it for reading and writing.
Mode "n", it creates a new memory segment. If the same key already exists, the creation will fail. This is for the sake of safe use of shared memory.

The third parameter is the permissions of the memory segment. You must provide an octal value here.

The fourth parameter provides the memory segment size in bytes. Since the shared memory segment used is of fixed length, the length of the data must be calculated when storing and reading, otherwise the writing may fail or a null value may be read. .

Please note that this function returns an ID number that can be used by other functions to operate on this shared memory segment. This ID is the shared memory access ID, unlike the system ID, which is passed as a parameter. Be careful not to confuse the two. On failure, shmop_open will return FALSE. When creating a memory block, it is recommended to use constants instead of variables for the key parameter, otherwise it is likely to cause memory leaks.

shmop_write (write data to the memory segment)

This function is similar to the fwrite function, which has two parameters: the open stream resource (returned by fopen) and the data you wish to write. The shmop_write function also performs this task.

The first parameter is the ID returned by shmop_open, which identifies the shared memory block you are operating on. The second parameter is the data you wish to store, and the final third parameter is the position where you wish to start writing. By default, we always use 0 to indicate where to start writing. Note that this function returns FALSE on failure and the number of bytes written on success.

shmop_read(Read data from memory segment)

Reading data from shared memory segment is very simple. All you need is an open memory segment and the shmop_read function. This function accepts some parameters and works like fread.

Please pay attention to the parameters here. The shmop_read function will accept the ID returned by shmop_open, which we already know, but it also accepts two other parameters. The second argument is the location in the memory segment you wish to read from, and the third is the number of bytes you wish to read. The second parameter can always be 0, indicating the beginning of the data, but the third parameter can be problematic because we don't know how many bytes we want to read.

This is very similar to what we do in the fread function, which accepts two parameters: the open stream resource (returned by fopen) and the number of bytes you wish to read from the stream. Use the filesize function (which returns the number of bytes in a file) to read it completely.

shmop_size (returns the actual size of the memory segment data)

For example, we have opened a memory space with a length of 100 bytes, but the actual length of the stored data is only 90, then the value returned by using shmop_size is 90.

shmop_delete (delete memory segment)

This function only accepts one parameter: the shared memory ID we want to delete, This does not actually delete the memory segment. It marks the memory segment for deletion because a shared memory segment cannot be deleted while another process is using it. The shmop_delete function marks the memory segment for deletion, preventing any other process from opening it. To delete it, we need to close that memory segment. When creating a memory block, it is recommended to use constants instead of variables for the key parameter, otherwise it is likely to cause memory leaks.

shmop_close(Close memory segment)

我们在对内存段进行读取和写入,但完成操作后,我们必须从它解除,这非常类似于处理文件时的 fclose 函数。打开包含一个文件的流并在其中读取或写入数据后,我们必须关闭它,否则将发生锁定。

简单测试结果查看

我是在LNMP环境下操作的,如果你也和我一样,在执行完简单的操作之后,可以使用linux命令查看一下地址和占用大小

# ipcs -m
[root@bogon ~]# ipcs -m

------ Shared Memory Segments --------
key  shmid  owner  perms  bytes  nattch  status  
0x00000000 0       gdm    600     393216   2   dest   
0x00000000 32769    gdm    600     393216   2   dest        
0x4337b101 884750   nobody   644     1024    0

命令说明

key :共享内存的唯一的key值,共享内存通过该key来判断你读取的是哪一块内存。 owner:创建该共享内存块的用户 bytes:该内存块的大小 status:当前状态,如:dest,即将删除等。

项目实际应用小案例

/**
 * 将领技能
 */
class Generalskill_model extends CI_Model {<!-- -->

 private $_memory_key = 0x4337b001; //共享内存地址key
 private $_memory_size = 1048576;  //开辟共享内存大小 //最好根据实际数据长度大小定义。

 public function __construct() {<!-- -->
 parent::__construct();
 }

 public function get_skill_list() {<!-- -->
 $data = [];
 $shmid = @shmop_open($this->_memory_key, &#39;a&#39;, 0644, $this->_memory_size); 

 if ($shmid === FALSE) {<!-- -->
  $shmid = @shmop_open($this->_memory_key, &#39;c&#39;, 0644, $this->_memory_size); 
  $data = $this->return_skill_list();
  shmop_write($shmid, json_encode($data), 0); 
  @shmop_close($shmid);

  return $data;
 }
 $data = json_decode(preg_replace(&#39;/[\x00-\x1F\x80-\x9F]/u&#39;, &#39;&#39;, trim(shmop_read($shmid, 0, $this->_memory_size))), true);
 @shmop_close($shmid);
 return $data; 

 }

 public function return_skill_list() {<!-- --> //这里是一个超大的数组,其实就是把这个数组json化,然后存入共享内存段。 其实可以用redis等其他缓存...这里我就是为了不用redis等其他nosql才用的shmop
 return array (
=> 
 array (&#39;id&#39; => &#39;1&#39;,&#39;animation&#39; => &#39;13&#39;,&#39;skill_type&#39; => &#39;1&#39;,&#39;power_type&#39; => &#39;1&#39;,&#39;site&#39; => &#39;1&#39;,&#39;type&#39; => &#39;1&#39;,&#39;paramete&#39; => &#39;0&#39;,&#39;paramete2&#39; => &#39;0&#39;,&#39;paramete3&#39; => &#39;0&#39;,&#39;chance&#39; => &#39;0&#39;,&#39;ratio&#39; => &#39;1&#39;,
 ),
=> 
 array (&#39;id&#39; => &#39;2&#39;,&#39;animation&#39; => &#39;3&#39;,&#39;skill_type&#39; => &#39;2&#39;,&#39;power_type&#39; => &#39;1&#39;,&#39;site&#39; => &#39;1&#39;,&#39;type&#39; => &#39;1&#39;,&#39;paramete&#39; => &#39;0&#39;,&#39;paramete2&#39; => &#39;0&#39;,&#39;paramete3&#39; => &#39;0&#39;,&#39;chance&#39; => &#39;0&#39;,&#39;ratio&#39; => &#39;2&#39;,
 ),..........................................

当然你要考虑的是,如果数据更新的话,那么内存段也要删除,并且更新数据…通过shmop_delete可以删除 。这就需要你们自己根据项目应用来考虑了

还有就是这篇文章只是为了简单的读,并没有出现复杂的读写,否则可能会出现进程互斥等意想不到的冲突如果复杂,那么就可以考虑信号量了。

The above is the detailed content of Detailed example of how PHP creates shared memory to reduce load. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:jb51.net. If there is any infringement, please contact admin@php.cn delete