怎样对键盘有更好地了解

tech2023-10-24  108

怎样对键盘有更好地了解

It’s interesting how just a few years can make a difference in the names that are given to things. If this were to come up today, it would probably be called PHP Recycling Options, because rather than picking things up and throwing them into a landfill where they’ll never be seen again, we are really talking about grabbing things whose use has passed and setting them up to be useful again. But, recycling wasn’t le petit Cherie of society back when the idea was developed and so this task was given the vulgar name of ‘Garbage Collection’. What can we do but follow what history and common usage have given us?

有趣的是,仅仅几年时间就能使事物的名称有所不同。 如果今天能解决这个问题,它可能会被称为PHP Recycling Options,因为与其将它们捡起来并扔到一个不会再出现的垃圾填埋场中,不如说是在抓取那些已被使用且已经使用过的东西。设置它们再次有用。 但是,当想法产生时,回收并不是社会的小问题 ,因此该任务被俗称为“垃圾收集”。 我们可以做什么,但要遵循历史和常用用法赋予我们的呢?

程序生成的垃圾 (Program Generated Garbage)

Programs use resources; sometimes small ones, sometimes much bigger. An example would be a data field. A program may define a data field, say a sequence number, that is used in the program. And once defined, this data field will take up space in memory, probably only a few bytes, but space nonetheless. Since every machine or programming environment has a finite (albeit large) amount of space available, the remaining space that it has left will be reduced by the amount of space that this field takes up.

程序使用资源; 有时很小,有时更大。 一个示例是数据字段。 程序可以定义在程序中使用的数据字段,例如序列号。 并且一旦定义,该数据字段将占用内存空间,可能只有几个字节,但是仍然有空间。 由于每个机器或编程环境都有有限(尽管很大)的可用空间,因此,该字段所剩余的空间将减少其剩余的剩余空间。

When the program ends, naturally, the program, and any space that it has tied up, will disappear and the total space available will expand back to it’s maximum size. But what happens if the program never ends?

当程序结束时,程序及其占用的任何空间自然都会消失,可用的总空间将扩展回其最大大小。 但是,如果程序永不结束,会发生什么?

I’ve written a few of these such programs in my time. Works of beauty they were, and I was always pleased when everyone else in the shop noticed that I had created one. There’s nothing that points out your capabilities quite as much as bringing a big ol’ piece of IBM iron to a stand-still all by yourself, while from the surrounding cubicles one person after another says loudly, “hey, is there something wrong with the system?” The trick is to chime in second or third so to deflect attention from yourself.

我当时写了一些这样的程序。 它们是美丽的作品,当商店中的其他所有人都注意到我创造了一件作品时,我总是很高兴。 没有什么能指出您的能力,就像您自己将一台大型IBM铁杆停下来一样,而周围的一个人又一个人大声说:“嘿,这有什么问题吗?”系统?” 诀窍是排在第二或第三,以转移您的注意力。

But some programs are even meant to run forever, like daemons and other such things. And as they run, the amount of debris they generate can potentially keep growing. If the locked up resources are substantial, then it can have a real negative impact on your system.

但是有些程序甚至可以永久运行,例如守护程序和其他类似的东西。 而且当它们运行时,它们产生的碎片数量可能会继续增长。 如果锁定的资源很大,那么可能会对您的系统产生真正的负面影响。

As a result, every language must have a way of clearing out orphaned resources, making them available to other users and ensuring that the total available system space remains constant. Fortunately, PHP has a three tiered approach to garbage removal.

结果,每种语言都必须有一种方法来清除孤立的资源,使它们可供其他用户使用,并确保总的可用系统空间保持不变。 幸运的是,PHP具有三层方法来清除垃圾。

一级–范围结束 (First Level – End of Scope)

First, like most languages, whenever a scope of action ends, everything within that scope of action is destroyed, and any allocated resources are released. The scope of action can cover a function, a script, a session, etc. and when that scope ends, so does everything it is holding on to. Of course, you can always free up a resource any time you want by using the unset() function.

首先,与大多数语言一样,每当操作范围结束时,该操作范围内的所有内容都会被破坏,并且释放所有分配的资源。 作用范围可以涵盖功能,脚本,会话等,并且该作用范围结束时,它所保留的所有内容也将如此。 当然,您随时可以使用unset()函数随时释放资源。

This is one reason why functions and methods are so very important, because they establish a scope of action, when particular memory usage begins and when it should end, and limits how long things can be around. They should be used whenever possible instead of global entities.

这就是功能和方法如此重要的原因之一,因为它们确定了作用范围,何时开始使用特定内存以及何时应该终止使用内存,并限制了事物可以存在多长时间。 应尽可能使用它们而不是全局实体。

第二级–参考计数 (Second Level – Reference Counting)

Second, like most scripting languages, PHP keeps track of how many entities are using a given variable using a technique called reference counting.

其次,与大多数脚本语言一样,PHP使用一种称为引用计数的技术来跟踪使用给定变量的实体数量。

When a variable is created in a PHP script, PHP creates a little ‘container’ called a zval that consists of the value assigned to that variable plus two other pieces of information: is_ref and refcount. The zval containers are kept in a table where there is one table per scope of action (script, function, method, whatever).

在PHP脚本中创建变量时,PHP将创建一个名为zval的小“容器”,该容器包含分配给该变量的值以及其他两个信息:is_ref和refcount。 zval容器保存在一个表中,每个动作范围(脚本,函数,方法等)都有一个表。

is_ref is a simple true/false value that indicates if the variable is part of a reference set, thus helping PHP to tell if this is a simple variable or a reference.

is_ref是一个简单的true / false值,它指示变量是否是引用集的一部分,从而帮助PHP判断这是简单变量还是引用。

The refcount is more interesting in that it holds a numeric value indicating how many different variables are using this value. That is, if you define variable $dave = 6, the refcount will be set to 1. If I then say $programmer = $dave, the refcount will be incremented to 2. PHP knows enough not to create a second zval for the value 6; it just updates the counter on the already existing value container. When the program ends, or when we leave the scope of the function, or when unset() is used, then this refcount will be decremented. When the refcount hits zero, the zval is destroyed and any memory that it was holding is now free.

引用计数更有趣,因为它包含一个数字值,指示有多少不同的变量正在使用该值。 也就是说,如果定义变量$dave = 6 ,则引用计数将设置为1。如果我再说$programmer = $dave ,则引用计数将增加为2。PHP知道不会为该值创建第二个zval。 6; 它只是更新已经存在的值容器上的计数器。 当程序结束时,或者当我们离开函数的范围时,或者当使用unset()时,此引用计数将减少。 当refcount达到零时,zval被销毁,并且其持有的任何内存现在都可用。

Of course, this is a simple example for a simple variable. When you are talking about arrays or objects then it’s much more complicated for with multiple zrefs being created for the multiple values for an element in an array, but the basic processing is the same.

当然,这是一个简单变量的简单示例。 当您谈论数组或对象时,要为数组中元素的多个值创建多个zref,要复杂得多,但是基本处理是相同的。

A problem occurs, however, if we use an array within another array, something that happens with some frequency in more complicated PHP scripts. In this case, the refcount for an array value is set to 1 when the original array value is set, then incremented to 2 when the array is associated with another array. If the scope of use of the second array then ends, then the refcount is decremented by 1. We are now in a situation where the value itself is no longer associated with anything, but the container (zval) that represents it still has a refcount greater than zero.

但是,如果我们在另一个数组中使用一个数组,则会出现问题,在更复杂PHP脚本中,某些事情会以某种频率发生。 在这种情况下,当设置原始数组值时,将数组值的引用计数设置为1,然后在将该数组与另一个数组关联时将其递增为2。 如果第二个数组的使用范围结束,则refcount递减1。我们现在处于一种情况,即值本身不再与任何内容关联,但是表示它的容器(zval)仍然具有refcount大于零。

The end result is that the storage represented by the original array will not be freed up and that amount of memory is now unavailable for use by anything. Normally, we think of this amount of lost storage as being small, but often it isn’t. Arrays can be very big things today and it is especially problematic if the script in which this occurs is a daemon or other nearly continuously running function. In this case, the resultant ‘memory leak’ can have devastating consequences on performance and even the ability of a server to operate.

最终结果是,原始数组所代表的存储将不会被释放,并且现在任何人都无法使用该数量的内存。 通常,我们认为丢失的存储量很小,但通常并非如此。 数组今天可能是非常大的事情,如果发生这种情况的脚本是守护程序或其他几乎连续运行的函数,则尤其成问题。 在这种情况下,由此产生的“内存泄漏”可能会对性能甚至服务器的运行能力造成毁灭性的后果。

第三级–正式垃圾收集 (Third Level – Formal Garbage Collection)

Obviously, reference count oriented clears have their limitations but fortunately, PHP 5.3 offered another option to help with this situation.

显然,面向引用计数的清除具有其局限性,但是幸运的是,PHP 5.3提供了另一种选择来解决这种情况。

The specific situation that we want our garbage cycle to address is the case where the zval has been decremented, but it is still a non-zero value. Basically the cycle sees which values can be decremented further and then free up the ones that go to zero.

我们希望垃圾回收周期解决的特定情况是zval递减的情况,但是它仍然是非零值。 基本上,循环会看到哪些值可以进一步减小,然后释放变为零的值。

What really happens is that PHP keeps track of the all root containers (zvals). This is done whether garbage collection is turned on not (because it is faster for it to just do it rather than asking if garbage collection is on, yada, yada, yada). This root buffer holds up to 10,000 roots (fixed size, but this can be changed). When it fills up, then the garbage collection mechanism will kick off and it will begin analyzing this buffer.

真正发生的是PHP跟踪所有根容器(zvals)。 不管是否打开垃圾收集都会完成此操作(因为这样做比查询垃圾收集是否已打开要快得多,例如yada,yada,yada)。 该根缓冲区最多可容纳10,000个根(大小固定,但是可以更改)。 当它填满时,垃圾收集机制将启动,并将开始分析此缓冲区。

The first thing the GC routine does is rip through the root buffer and decrement all of the zval counts by 1. As it does this, it marks each one with a little like check mark so that it only decrements a root once.

GC例程要做的第一件事是通过根缓冲区,将所有的zval计数减1。这样做时,它会用一个有点像复选标记的方式标记每个zval,从而只将根减1。

Then, it goes through again and marks (this time with a little squiggly line) all of the zvals whose reduced counts are zero. The ones that are not zero are incremented so that they resume their original values.

然后,它再次经过并标记(这次用一点弯曲的线条)所有减少计数为零的zval。 不为零的值递增,以便它们恢复其原始值。

Finally, it will roll through there one more time, clearing out the non-zero zvals from the buffer, and freeing up the storage for the ones with a zero refcount.

最后,它将再滚动一次,从缓冲区中清除非零zval,并为引用计数为零的存储器释放存储空间。

Garbage collection is always turned on in PHP, but you can turn it off in the php.ini file with the directive zend.enable_gc. Or, you can do it within your script by calling the gc_enable() and gc_disable() functions.

垃圾收集始终在PHP中打开,但是您可以使用指令zend.enable_gc在php.ini文件中将其关闭。 或者,您可以在脚本中通过调用gc_enable()和gc_disable()函数来完成此操作。

As noted above, the garbage collection, if enabled, runs when the root is full, but you can override this and run the collection when you feel like it with the gc_collect_cycles() function. And, you can modify the size of the root buffer with the gc_root_buffer_max_entries value in the zend/zend_gc.c value in the PHP source code.

如上所述,如果启用了垃圾回收,则在根目录已满时运行,但是您可以使用gc_collect_cycles()函数覆盖该垃圾回收并在感觉满意时运行该回收。 而且,您可以修改与根缓冲区的大小gc_root_buffer_max_entries中值zend/zend_gc.c在PHP源代码的价值。

All in all, this allows you to control whether GC runs and when and were it does, which is a good thing because it is a bit resource intensive and so might not be the sort of thing you run just for the heck of it.

总而言之,这使您可以控制GC是否运行以及何时运行以及何时运行,这是一件好事,因为它占用大量资源,因此可能并非仅仅为了运行而已。

什么时候应该使用 (When Should You Use It)

Because there is a performance hit attached to garbage collection, it is worth taking a minute to figure out when it should be used.

因为垃圾收集对性能有很大影响,所以值得花一点时间弄清楚何时应该使用它。

First, keep in mind that unless you overtly run it (with the gc_collect_cycles() function), the formal garbage collection will not happen until the root table (10,000 entries) is full, and since this table is at the scope level, that isn’t going to happen for small functions.

首先,请记住,除非您公开运行它(使用gc_collect_cycles()函数),否则在根表(10,000个条目)已满之前,不会进行正式的垃圾收集,并且由于该表处于作用域级别,因此不会小功能将不会发生。

Should you use it on small scripts? That’s up to you. It’s hard to say that running something like garbage collection is a bad thing, but if you have small, quick running scripts that start and then end and are gone then there might not be much of a payback. But if your server is running a lot of small scripts that stay persistent, then it will probably be worth the effort. The only real way to know is to benchmark your application and see. And certainly, if you have long running scripts or especially scripts that do not end, then garbage collection is essential if you want to prevent the kind of memory leaking that we talked about above.

您应该在小型脚本上使用它吗? 随你(由你决定。 很难说运行垃圾回收之类的东西是一件坏事,但是如果您有小的,快速运行的脚本开始然后结束并消失了,那么可能没有太多的回报。 但是,如果您的服务器正在运行许多保持持久性的小脚本,那么可能值得付出努力。 唯一真正了解的方法是对应用程序进行基准测试并查看。 当然,如果您有运行时间较长的脚本,或者特别是没有结束的脚本,则垃圾收集对于防止上面提到的那种内存泄漏至关重要。

Perhaps most importantly, we should always try to follow good programming guidelines so that we minimize or eliminate global variables and tie our variables instead to scope, so that even if we have a long running script, we free up that memory when the function, rather than the script, ends. Also be aware of when you are using arrays within arrays, or objects referencing objects, since such situations can cause memory leaking and is the real target of the formal garbage collection process.

也许最重要的是,我们应该始终遵循良好的编程准则,以便最小化或消除全局变量,并将变量代入范围,这样,即使我们运行的脚本很长,我们也可以在释放函数时释放内存。比脚本结束。 还应注意何时使用数组中的数组或引用对象的对象,因为这种情况可能导致内存泄漏,并且是正式垃圾收集过程的真正目标。

Image via Fotolia

图片来自Fotolia

翻译自: https://www.sitepoint.com/better-understanding-phps-garbage-collection/

怎样对键盘有更好地了解

最新回复(0)