Closed ziaratban closed 2 years ago
Shared memory is simply a chunk of physical RAM that gets mapped into the process space by the OS. In your example, you would have a grand total of 1024 bytes of shared memory. To "clear" the memory, you would simply move to the beginning and write up to 1024 bytes of whatever you define as "clear." You should surround shared memory accesses with at least one synchronization primitive(s) like a mutex to avoid race conditions. What you do with shared memory is up to you.
Been a while since I looked but I'm pretty sure physical RAM is guaranteed to be reserved by the kernel (only if space is available) and won't use swap space for shared memory segments. For that reason, system level shared memory objects should be used sparsely by applications in general (not just PHP) and kept fairly small. Also, since system memory is allocated/reserved/mapped in specific sizes, you might as well round up the value to the nearest page size of the system. Modern OSes allocate pages in chunks of 4KB or 8KB. So even if you only need 50 byes, you'll still get a full 4KB page. But as I said, it's been a while since I looked at that.
Thanks for the explanation.
But I think I do not choose a good word(clear) for my goal.
My goal is shmop_delete
.
There's no need for that. When all object instances go out of scope, the shared memory is freed. Example code:
<?php
echo "Part 1.\n";
$obj = new SyncSharedMemory("test", 4096);
var_dump($obj->First());
var_dump($obj->Write("blahblah"));
var_dump($obj->Read());
echo "\n";
echo "Part 2.\n";
$obj2 = new SyncSharedMemory("test", 4096);
var_dump($obj2->First());
var_dump($obj2->Read());
echo "\n";
unset($obj);
echo "Part 3.\n";
$obj = new SyncSharedMemory("test", 4096);
var_dump($obj->First());
var_dump($obj->Read());
echo "\n";
unset($obj);
unset($obj2);
echo "Part 4.\n";
$obj = new SyncSharedMemory("test", 4096);
var_dump($obj->First());
var_dump($obj->Read());
?>
Produces:
Part 1.
bool(true)
int(8)
string(4096) "blahblah"
Part 2.
bool(false)
string(4096) "blahblah"
Part 3.
bool(false)
string(4096) "blahblah"
Part 4.
bool(true)
string(4096) ""
There's no need for that. When all object instances go out of scope, the shared memory is freed.
Also at the end of the process? or do I have to call unset()
manually?
Okay, but how does it work in multiple processes?
-------------------------------Lifecycle-----------------------------
Process 1 : |-------New('test')-------------|
Process 2 : |---------New('test')-----------|
Process 3 : |---------New('test')--------------|
Is there still data in Process 3
?
In my mind is:
test
shared memory in process 1 and this is the first.test
shared memory in process 2 and this is not the first.test
is deleted at the end of process 2 (according to your example)test
shared memory in process 3 and this is the first.Also at the end of the process? or do I have to call unset() manually?
When the refcount to the shared memory object across all processes drops to zero, the shared memory object is reset/removed.
The use of the unset()
keyword removes a reference in PHP and will generally call a destructor on a class instance when the last reference to the object is removed. It was just a way to demonstrate the refcounting aspect.
<?php
class TestClass
{
public function __construct()
{
echo "constructor.\n";
}
public function __destruct()
{
echo "destructor.\n";
}
}
$obj = new TestClass();
echo "Before unset.\n";
unset($obj);
echo "After unset.\n";
?>
Output is:
constructor.
Before unset.
destructor.
After unset.
Shared memory contents continue to be available and First()
will return false
as long as there is one process holding onto an instance of the object. The point of named objects is to use them across processes.
Whenever I want to test out a theory that's timing based, I use echo
and sleep()
statements in a quick little bit of code. I'll fire up a few terminal sessions and run one process in one terminal and then start another process in a second terminal and maybe another process in a third terminal. sleep()
statements allow sufficient time to start the other processes and also allow for watching the timed operations happen at a snail's pace instead of going so fast that there's no way to understand what is happening.
The use of the unset() keyword removes a reference in PHP and will generally call a destructor on a class instance when the last reference to the object is removed. It was just a way to demonstrate the refcounting aspect.
I think there is a logical bug here.
PHP remove all objects at the end of the script. So php automatically calls the __destruct()
method.
So if the sync project uses this method to remove the shared memory block, the data will practically never remain in the shared memory.
And in fact I can not use it as a cache !
Am I guessing right?
Yes. And it's consistent behavior with Windows. Shared memory is for conducting IPC between two currently running processes, not long-term storage.
For a RAM cache, on many Linux distros there is /run
which is mounted as tmpfs
. That's basically a RAM drive. More generic alternatives are to use some sort of shared object caching system like Memcached.
Hmmm, I think this behavior is present in Linux as well.
The shared memory created by shm_open is persistent. It stays in the system until explicitly removed by a process. This has a drawback that if the process crashes and fails to clean up shared memory it will stay until system shutdown. https://en.wikipedia.org/wiki/Shared_memory
Shared memory is for conducting IPC between two currently running processes, not long-term storage.
Why ? Can you explain more?
https://stackoverflow.com/questions/25823097/unix-socket-vs-shared-memory-message-which-is-faster https://stackoverflow.com/questions/2101671/unix-domain-sockets-vs-shared-memory-mapped-file
Yes. And it's consistent behavior with Windows
I tested this behavior in shmop between two process and it worked when two processes exit .
Please also visit https://github.com/goldsborough/ipc-bench
Hmmm, I think this behavior is present in Linux as well.
The shared memory created by shm_open is persistent. It stays in the system until explicitly removed by a process. This has a drawback that if the process crashes and fails to clean up shared memory it will stay until system shutdown. https://en.wikipedia.org/wiki/Shared_memory
Shared memory is for conducting IPC between two currently running processes, not long-term storage.
Why ? Can you explain more?
Computer science. But your own quote above summarizes why you definitely want shared memory to go away when all processes using it exit: "This has a drawback that if the process crashes and fails to clean up shared memory it will stay until system shutdown."
That's a pretty serious drawback. Stuff crashes all the time and usually unexpectedly. Leaving things in unknown states is why synchronization objects, shared memory, and other system resources should be managed in the kernel, not in user space. shm_open()
is a fundamentally flawed function by design. PECL sync provides a minor bit of protection in that even if the script being executed by PHP "crashes," PHP itself isn't likely to crash and will likely allow PECL sync to clean up any objects being used in a relatively safe manner. There are still ways to create broken objects and leave behind a mess on the system even with this extension such as forcefully killing PHP (e.g. kill
).
https://stackoverflow.com/questions/25823097/unix-socket-vs-shared-memory-message-which-is-faster https://stackoverflow.com/questions/2101671/unix-domain-sockets-vs-shared-memory-mapped-file
Yes. And it's consistent behavior with Windows
I tested this behavior in shmop between two process and it worked when two processes exit .
shmop
uses POSIX shared memory functions on Linux. Shared memory on Windows, however, is non-persistent. When the last handle closes on Windows, the associated shared memory is freed by the kernel:
https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory
If you aren't seeing that behavior on Windows, then you still have a handle open to the shared memory somewhere. For consistency between all supported OSes, PECL sync frees shared memory when the last process using it closes its final handle. Windows, of course, does that automatically in the kernel. PHP userland code should work identically everywhere. I personally dislike when there are significant discrepancies in an implementation in PHP core rather than having expended a little extra effort to have feature parity across all major platforms.
For long-term, high-performance RAM-oriented storage, use a mounted RAM drive. If the concern is sheer performance, then writing C/C++ code is a better solution. Micro-optimization inside an interpreted language like PHP isn't a particularly useful exercise.
Hi
How do I clear a shared memory object?