copy on write php

Copy-on-write в PHP

Copy-on-write или копирование при записи — один из способов управлением памятью. Но перед тем как давать какие-то определения, предлагаю рассмотреть пример:

В данном примере есть функция handle. В эту функцию передаётся массив большого размера. По умолчанию в PHP передача аргументов происходит по значению. Это означает, что если изменить значение аргумента внутри функции, то вне функции значение всё равно останется прежним. Другими словами внутри функции используется копия переменной, но для создания копии требуется выделить память.

Вопрос: в целях оптимизации стоит ли передать аргумент по ссылке handle(array &$array)?

На самом деле ответ зависит от того, что происходит внутри функции handle.

Чтение аргумента

Модификация аргумента

В данном случае произойдет копирование переменной, то есть создание нового контейнера zval с выделением памяти.

Copy-on-write

Суть подхода сopy-on-write или копирование при изменении заключается в том, что при чтении переменных используется общая копия, в случае изменения переменной — создается новая копия.

Замеры памяти

Проведём тест, попробуем увидеть, что при чтении аргумента используется общая копия, а при модификации выделяется память.

Из результата видно, что при изменении аргумента, была выделена память, а при чтении нет.

Передача объекта в качестве аргумента

Стоит рассмотреть случай передачи объекта в качестве аргумента. И посмотреть, применяется ли для данного случая механизм copy-on-write. Рассмотрим следующий пример:

Складывается впечатление, что объект передаётся по ссылке, а не по значению, но это не совсем верно. На самом деле при передаче объекта в качестве аргумента передаётся только ID объекта. Содержимое объекта хранится отдельно и доступ можно получить по ID. Из-за этого, если что-то изменить внутри объекта, то это доступно и внутри функции и вне функции. Более детально можно прочитать документации PHP: Объекты и ссылки.

То есть в данном примере не нужно передавать объект по ссылке, так как передается всего лишь ID объекта.

Вывод

В подавляющем большинстве не нужно передавать аргумент по ссылке. Так как редко оперируем большими по памяти переменными. И аргументы в большинстве случаев используются только на чтение. Если речь идет про передачу объектов, то и в этом случае не нужно передавать аргумент по ссылке, так как передаётся только идентификатор объекта.

Другими словами не нужно сейчас бежать, и срочно что-то менять в вашей коде и в вашем подходе. Продолжаем писать код как, обычно, но уже более осознанно.

Источник

Copy on write php

Let’s start with an example:

What is «copy»

This is an example taken from Brother Bird’s blog. It is clearer, so I posted it directly.

Copy-on-write application scenarios

An example to prove that PHP COW optimizes memory usage:

The memory has not improved significantly.

The principle of «copy-on-write»

Multiple variables with the same value sharing the same memory does save memory space, but the value of the variable will change. If in the above example, the value pointing to the same memory changes (or may change), you need To «separate» the changed value, this «separation» operation is «copy».

In PHP, in order to distinguish whether the same zval address is shared by multiple variables, the Zend engine introduces two variables ref_count and is_ref for identification:

ref_count and is_ref are defined in the zval structure

Is_ref identifies whether it is a mandatory reference for users to use &;

ref_count is a reference count, used to identify how many variables this zval is referenced, that is, the automatic reference of COW, it will be destroyed when it is 0;

I believe you can also understand the implementation principle of COW in PHP: COW in PHP is implemented based on the reference count ref_count and is_ref. If you add a variable pointer, you add 1 to ref_count, and vice versa. One more mandatory reference & will increase is_ref by 1, and vice versa.

Источник

PHP: Copy On Write and Assign By Reference perform different on PHP5 and PHP7

We have a piece of simple code:

On PHP5, it outputs 8, because:

But in PHP7, it always outputs 7.

I’ve checked the changes in PHP7: http://php.net/manual/en/migration70.incompatible.php, but I did not get any clue.

Any help will be great, thanks in advance.

update1

Here is the result of the code on PHP5 / PHP7: https://3v4l.org/USTHR

update2

copy on write php

2 Answers 2

Disclaimer: I’m not a PHP Internals expert (yet?) so this is all from my understanding, and not guaranteed to be 100% correct or complete. 🙂

Edit: It was pointed out on the PHP Internals mailing list that using multiple operations that modify a variable within a single statement is generally considered «undefined behaviour», and ++ is used as an example of this in C/C++.

As such, it’s reasonable for PHP 5 to return the value it does for implementation / optimisation reasons, even if it is logically inconsistent with a sane serialization into multiple statements.

The (relatively new) PHP language specification contains similar language and examples:

Arguably, this is a weaker claim than «undefined behaviour», since it implies they are evaluated in some particular order, but we’re into nit-picking now.

phpdbg investigation (PHP 5)

I was curious, and want to learn more about the internals, so did some playing around using phpdbg.

No references

With reference assignment

When the variables have been bound together, they share an address, with a refcount of 2, and a by-ref marker:

After the pre-increments (but before the addition), the same address has a refcount of 4, showing the 2 temp vars erroneously bound by reference:

The source of the issue

Digging into the source on http://lxr.php.net, we can find the implementation of the ZEND_PRE_INC opcode:

PHP 5

The crucial line is this:

So we create a new zval for the result value only if it is not currently a reference. Further down, we have this:

So if the return value of the decrement is actually used, we need to «lock» the zval, which following a whole series of macros basically means «increment its refcount», before assigning it as the result.

PHP 7

So what’s different in PHP 7? Several things!

Firstly, the phpdbg output is rather boring, because integers are no longer reference counted in PHP 7; instead, a reference assignment creates an extra pointer, which itself has a refcount of 1, to the same address in memory, which is the actual integer. The phpdbg output looks like this:

Secondly, there is a special code path in the source for integers:

So if the variable is an integer ( IS_LONG ) and not a reference to an integer ( IS_REFERENCE ) then we can just increment it in place. If we then need the return value, we can copy its value into the result ( ZVAL_COPY_VALUE ).

If it’s a reference, we won’t hit that code, but rather than keeping references bound together, we have these two lines:

So now we have an integer we can decrement, that will affect all by-reference associations, but not by-value ones for refcounted types. Finally, if we want the return value of the increment, we again copy it, rather than just assigning it; and this time with a slightly different macro which will increase the refcount of our new zval if necessary:

Источник

What is copy-on-write?

I would like to know what copy-on-write is and what it is used for. The term is mentioned several times in the Sun JDK tutorials.

copy on write php

9 Answers 9

I was going to write up my own explanation but this Wikipedia article pretty much sums it up.

Here is the basic concept:

Copy-on-write (sometimes referred to as «COW») is an optimization strategy used in computer programming. The fundamental idea is that if multiple callers ask for resources which are initially indistinguishable, you can give them pointers to the same resource. This function can be maintained until a caller tries to modify its «copy» of the resource, at which point a true private copy is created to prevent the changes becoming visible to everyone else. All of this happens transparently to the callers. The primary advantage is that if a caller never makes any modifications, no private copy need ever be created.

Also here is an application of a common use of COW:

The COW concept is also used in maintenance of instant snapshot on database servers like Microsoft SQL Server 2005. Instant snapshots preserve a static view of a database by storing a pre-modification copy of data when underlaying data are updated. Instant snapshots are used for testing uses or moment-dependent reports and should not be used to replace backups.

copy on write php

«Copy on write» means more or less what it sounds like: everyone has a single shared copy of the same data until it’s written, and then a copy is made. Usually, copy-on-write is used to resolve concurrency sorts of problems. In ZFS, for example, data blocks on disk are allocated copy-on-write; as long as there are no changes, you keep the original blocks; a change changed only the affected blocks. This means the minimum number of new blocks are allocated.

These changes are also usually implemented to be transactional, ie, they have the ACID properties. This eliminates some concurrency issues, because then you’re guaranteed that all updates are atomic.

copy on write php

I shall not repeat the same answer on Copy-on-Write. I think Andrew’s answer and Charlie’s answer have already made it very clear. I will give you an example from OS world, just to mention how widely this concept is used.

We can use fork() or vfork() to create a new process. vfork follows the concept of copy-on-write. For example, the child process created by vfork will share the data and code segment with the parent process. This speeds up the forking time. It is expected to use vfork if you are performing exec followed by vfork. So vfork will create the child process which will share data and code segment with its parent but when we call exec, it will load up the image of a new executable in the address space of the child process.

copy on write php

Just to provide another example, Mercurial uses copy-on-write to make cloning local repositories a really «cheap» operation.

The principle is the same as the other examples, except that you’re talking about physical files instead of objects in memory. Initially, a clone is not a duplicate but a hard link to the original. As you change files in the clone, copies are written to represent the new version.

copy on write php

The book Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma et al. clearly describes the copy-on-write optimization (section ‘Consequences’, chapter ‘Proxy’):

The Proxy pattern introduces a level of indirection when accessing an object. The additional indirection has many uses, depending on the kind of proxy:

There’s another optimization that the Proxy pattern can hide from the client. It’s called copy-on-write, and it’s related to creation on demand. Copying a large and complicated object can be an expensive operation. If the copy is never modified, then there’s no need to incur this cost. By using a proxy to postpone the copying process, we ensure that we pay the price of copying the object only if it’s modified.

To make copy-on-write work, the subject must be referenced counted. Copying the proxy will do nothing more than increment this reference count. Only when the client requests an operation that modifies the subject does the proxy actually copy it. In that case the proxy must also decrement the subject’s reference count. When the reference count goes to zero, the subject gets deleted.

Copy-on-write can reduce the cost of copying heavyweight subjects significantly.

Here after is a Python implementation of the copy-on-write optimization using the Proxy pattern. The intent of this design pattern is to provide a surrogate for another object to control access to it.

Class diagram of the Proxy pattern:

copy on write php

Object diagram of the Proxy pattern:

copy on write php

First we define the interface of the subject:

Next we define the real subject implementing the subject interface:

Finally we define the proxy implementing the subject interface and referencing the real subject:

The client can then benefit from the copy-on-write optimization by using the proxy as a stand-in for the real subject:

Источник

Copy on write php

origin

Copy write English name called «copy-on-write», referred to as the «cow», also known as «rely»

Today checked this «cow», had originated in the * nix memory management, and later widely applied in other development languages, C ++ the STL, as well as PHP, I believe many people are aware of copy-on-write this, often McCain with others too quite well.

will not

At first write such PHP code, often ask, so will not take up more memory because the replication and, next to it was said, no. Of course, you do not know what he said «no» means «not occupied», or «I do not know.» Later, we learned memory_get_usage() After this function, personally tested to verify, does not multiply.

xdebug Guanzhongkuibao

Observe will find that the value of refcount has changed in the copy foo and write bar when this process is the copy-on-write PHP. Well, I say, with the high school teacher said, look this is the law of conservation of energy as boring.

PHP variable structure

In fact, refcount PHP core, is a member of the structure variable storage, full name refcount__gc A member of the xdebug printed is_ref also variable structure is_ref__gc To see it complete definition can view the PHP source Zend / zend.h

Let’s look at the PHP core is how to create a variable for us to create, copy, variables and references. PHP is a weakly typed language variable, no type of argument, but PHP is written in C, C type definitions and usage has very strict requirements.

Creating Variables

Copy the variable

Reference variable

Reproduction, multiple combinations

All know that when a reference time, change foo, Hua both one value, another variable changes also followed. Summed up

When writing copy, citing multiple combinations perverted version

Of course, there will be a lot of students will make such problems:

In fact, PHP is very clever, of course, every language is, especially C, well-deserved! PHP core also specifically defines eight types to support all types we created in the PHP code, so let us become lazy. After reading this type list, PHP will achieve a deeper understanding of the kernel.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *