Writing datasets to shared (shared) memory using PHP

Lecture



A step-by-step guide to using shared PHP memory as a drive

This article focuses on shared memory and how to use it in Web applications as a data collector, taking advantage of high speed, reliability, and the ability to exchange data with other applications. These examples show how this can help in solving typical tasks in the development of Web applications.

Overview

Shared memory is an efficient way to exchange data between applications in the same machine. One process creates a shared memory segment that other processes can access if they have the necessary permissions. Each segment receives a unique shmid identifier, indicating the area of ​​physical memory where other processes can work with it. After creation, the segment becomes available to other processes in the same machine that have the appropriate permissions that can perform read, write, and delete operations.

This means that an application written in C can exchange information with an application written in another language, such as Java ™ or PHP. They can exchange information, if only they are able to obtain and understand this information. Shared memory is widely used in implementations available in most languages, so access should not be a problem. As for understanding the information, you can use a standard format, such as XML or JSON.

Shared memory is a fast way to exchange data between processes, mainly because after creating segments, the kernel of the operating system takes no part in the data transfer process. Such methods are often referred to as interprocess communication (IPC). Other IPC methods include pipelines, message queues, RPC, and sockets. Such a fast and reliable way to exchange data between applications is invaluable when working with an ecosystem of applications that need to communicate with each other. The usual method of using databases to exchange information between applications often leads to slow processing of requests and even blocking I / O depending on the size of the ecosystem. When working with shared memory, I / O operations that slow down the process are absent.

This article offers a simple way to create and use shared memory segments using PHP to store data sets that other applications can use. Even without a plan for using shared memory for data exchange, you can get the benefit, because applications do not need to deal with solving I / O problems. Storing datasets directly in memory has many advantages, from caching Web services data to sharing sessions. This is a very useful concept that every PHP developer should be familiar with.

Shared Memory and PHP

PHP has a wide range of extensions, including for working with shared memory. But developers can easily manipulate segments with several common functions without installing any extensions.

Creating segments

Shared memory functions are similar to file management functions, but instead of streams you work with shared memory access identifiers. The first example is the shmop_open function, which allows you to open an existing or create a new segment. This function is very similar to the classic fopen function, which opens threads to manipulate files, returning a resource available for use by other functions that perform read or write operations to this open stream. Consider the shmop_open function shown in Listing 1.

Listing 1. The shmop_open function
  <? php 

 $ systemid = 864;  // System ID of the shared memory segment
 $ mode = "c";  // Access mode 
 $ permissions = 0755;  // Permissions for shared memory segment 
 $ size = 1024;  // Segment size in bytes 

 $ shmid = shmop_open ($ systemid, $ mode, $ permissions, $ size); 

 ?> 

The first parameter is the system ID. This is the number that identifies the shared memory segment in the system. The second parameter is the access mode, which is very similar to the fopen access mode. Access to the segment can be obtained in four ways:

  • Mode "a" allows you to access the segment only for reading;
  • “w” mode allows you to access the segment for reading and writing;
  • in “c” mode, a new segment is created, and if it already exists, an attempt is made to open it for reading and writing;
  • “n” mode creates a new segment, and if it already exists, an error message is displayed.

The third parameter is the permissions for the segment. Here you need to specify the octal number.

The fourth parameter specifies the size of the segment in bytes. Before writing data to a segment, you need to allocate the required number of bytes in it.

Note that this function returns an identification number that can be used with other functions to manipulate a shared memory segment. This is a shared memory access identifier, different from the system identifier passed as a parameter. Do not confuse them. If shmop_open function shmop_open return FALSE.

Write to segments

To write data to a shared memory block, use the shmop_write function. It is very easy to use and takes only three parameters. See listing 2.

Listing 2. Using shmop_write to write to a shared memory block
  <? php 

 $ shmid = shmop_open (864, 'c', 0755, 1024); 
 shmop_write ($ shmid, "Hello World!", 0); 

 ?> 

It is similar to the fwrite function, which takes two parameters: the open stream resource returned by the fopen function, and the data to be written. The shmop_write function does the same thing.

The first parameter, the identifier returned by the shmop_open function, determines the block of shared memory you are going to work with. The second parameter is the data to be stored and, finally, the third parameter determines the address to start recording. The default is 0, so the recording starts from the beginning. In case of failure, this function returns the value FALSE and the number of successfully written bytes.

Reading from segments

Reading from shared memory segments is a simple procedure. Just open a segment and use the shmop_read function. It takes several parameters and works similarly to the fread function. Listing 3 shows an example of reading the contents of a file in PHP.

Listing 3. Using the shmop_read function to read the contents of a file
  <? php 

 $ stream = fopen ('file.txt', 'r +'); 
 fwrite ($ stream, "Hello World!"); 
 echo fread ($ stream, 11); 

 ?> 

Reading the contents of the shared memory segment is similar, as shown in Listing 4.

Listing 4. Reading the contents of a shared memory segment
  <? php

 $ shmid = shmop_open (864, 'c', 0755, 1024);
 shmop_write ($ shmid, "Hello World!", 0);
 echo shmop_read ($ shmid, 0, 11);

 ?> 

Pay attention to the parameters. The shmop_read function accepts the identifier returned by the shmop_open function, which we already know, and two other parameters. The second parameter is the place from which to start reading the segment; and the third is the number of bytes that you want to read. The second parameter can always be 0, the beginning of the data, but the third can cause a problem, since we may not know how many bytes we want to count.

This is very similar to the behavior of the fread function, which takes two parameters: the open stream resource returned by the fopen function, and the number of bytes that are required to be read from this stream. To read the file in its entirety, use the filesize function, which returns the number of bytes in the file.

Fortunately, when working with shared memory shmop_size , the shmop_size function, like filesize , returns the size of a segment in bytes. (See listing 5).

Listing 5. The shmop_size function returns the size of a segment in bytes.
  <? php 

 $ shmid = shmop_open (864, 'c', 0755, 1024); 
 shmop_write ($ shmid, "Hello World!", 0); 

 $ size = shmop_size ($ shmid); 
 echo shmop_read ($ shmid, 0, $ size); 

 ?> 

Deleting a segment

We know how to open, write and read shared memory segments. To complete our class on CRUD, it remains only to learn how to delete segments. This task can be easily solved with the help of the shmop_delete function, which needs only one parameter: the identifier of the shared memory segment that we want to delete.

Listing 6. The shmop_delete function marks a segment for deletion.
  <? php 

 $ shmid = shmop_open (864, 'c', 0755, 1024); 
 shmop_write ($ shmid, "Hello World!", 0); 
 shmop_delete ($ shmid); 

 ?> 

In fact, it does not delete the segment. It marks it for deletion, because the shared memory segment cannot be deleted as long as other processes using it exist. The shmop_delete function marks a segment for deletion and prevents any other process from opening it. Now, to remove a segment, you need to close it.

Segment closing

When you open a shared memory segment, you “join” it. By joining a segment, you can write data to it and read it from it, but when the work is finished, you need to disconnect from the segment. This is done using the shmop_close function, as shown in Listing 7.

It is very similar to the fclose function when working with files. After opening a stream with a file and reading or writing to it, this stream must be closed, otherwise a lock will occur.

Listing 7. Using the shmop_close function to detach from a segment
  <? php 

 $ shmid = shmop_open (864, 'c', 0755, 1024); 
 shmop_write ($ shmid, "Hello World!", 0); 
 shmop_delete ($ shmid); 
 shmop_close ($ shmid); 

 ?> 

Using shared memory as a drive

Having basic knowledge in the field of shared memory and having mastered the basic operations of CRUD on segments of shared memory, one can proceed to the practical application of this knowledge. Shared memory can be used as a unique alternative to the drive, which offers advantages such as fast read / write operations and process interaction. For a web application, this means:

  • buffer memory (storage of queries to the database, data of Web-services, external data);
  • session memory;
  • data exchange between applications.

Before proceeding, I would like to introduce a small library SimpleSHM. This is a compact level of abstraction for working with shared memory in PHP, which makes it easy to manipulate segments using an object-oriented approach. This library helps create much cleaner code when writing small applications that use shared memory to store data. To get started with SimpleSHM, download the tarball file from the GitHub page.

https://github.com/klaussilveira/SimpleSHM

There are three types of operations: read, write and delete. A simple creation of an instance of a class object will ensure the opening of a segment of shared memory. Highlights are shown in Listing 8.

Listing 8. Basic usage of SimpleSHM
  <? php

 $ memory = new SimpleSHM;
 $ memory-> write ('Sample');
 echo $ memory-> read ();

 ?> 

Please note that id is not passed to class. Once the identifier is not transmitted, the number will be selected randomly, and a new segment will open with this number. The number can be passed to the constructor as a parameter, so that the segment opens or is created with a specific ID value, as shown in Listing 9.

Listing 9. Opening a specified segment
  <? php

 $ new = new SimpleSHM (897);
 $ new-> write ('Sample');
 echo $ new-> read ();

 ?> 

The __destructor magic method __destructor care of calling the shmop_close function against a segment to disconnect an object and detach it from the segment. Call it "SimpleSHM 101". Now we will use it for a higher purpose: the use of shared memory as a drive. Serialization is required to store datasets, since arrays or objects cannot be stored in memory. Here JSON is used for serialization, but any other method is suitable, for example, XML or the built-in PHP serialization functions. An example is shown in Listing 10.

Listing 10. Using shared memory as a drive
  <? php

 require ('SimpleSHM.class.php');

 $ results = array (
	 'user' => 'John',
	 'password' => '123456',
	 'posts' => array ('My name is John', 'My name is not John')
 );

 $ data = json_encode ($ results);

 $ memory = new SimpleSHM;
 $ memory-> write ($ data);
 $ storedarray = json_decode ($ memory-> read ());

 print_r ($ storedarray);

 ?> 

We successfully converted the array to a JSON string, stored it in a shared memory block, counted, converted the JSON string back to an array, and displayed it. It all seems trivial, but just imagine what possibilities this fragment opens up. It can be used to store the results of queries to a Web service, databases, or even as a buffer for the processor of text templates. Writing and reading from memory will provide much better performance than writing and reading from disk.

This storage method is useful not only for use as a buffer, but also for exchanging data between applications, if this data is stored in a format that both applications can understand. Don't underestimate the power of shared memory in web applications. There are many different ways to effectively implement such storage, and the only limitation here is the talent and skill of the programmer.

Conclusion

This article covers most of the PHP tools for working with shared memory segments and explains how shared memory functions. Moreover, it contains suggestions for improving Web applications and draws attention to some factors that need to be kept in mind when creating Web applications. Ideas and recommendations for their implementation will be the starting point for the reader. And the basic model built by us will help him to think about more complex functions and solutions.

What's next?

We have identified some common tasks for which shared memory is ideal, such as caching, session sharing, and data exchange between applications. This introduction to shared memory gives the reader the opportunity to explore much more elegant solutions to typical problems. Feel free to extend the current implementation of SimpleSHM to your needs and make these changes to the project.


Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Running server side scripts using PHP as an example (LAMP)

Terms: Running server side scripts using PHP as an example (LAMP)