PHP カーネルを深く理解する (1)、PHP kernel を深く理解する_PHP チュートリアル

WBOY
リリース: 2016-07-12 09:05:21
オリジナル
1237 人が閲覧しました

PHP カーネルの深い理解 (1)、PHP カーネルの深い理解

PHP は、シンプルで強力な言語として、Web に適した多くの言語機能を提供できます。この記事では、実践から始めて、弱く型指定された変数の原理を探求し、PHP カーネルの深い理解へと導き続けます。

最近、ネットユーザーとコミュニケーションをとっているときに、非常に奇妙な質問を受けました。つまり、演算に参照を追加すると、パフォーマンスが 10,000 倍遅くなることがわかります。私の考えでは、参照は非常にエラーが発生しやすい問題であり、特に PHP での参照には多くの罠があります。私は以前にこの部分の PHP ソース コードを具体的に研究したことがあるので、この記事を読んだ後はこの問題を完全に理解できると思います。ご質問や知りたいことがございましたら、メッセージを残していただけます。

まずコードを見てみましょう:

リーリー

このコードを完成させて、reffer と noreffer のパフォーマンスの差が 10,000 倍であることがわかれば、以下を読む必要はありません。このブログは、PHP を初めて使用する人を対象としています。このコードを実行して試してみると、確かに 10,000 倍悪いです。もちろん、ネチズンが遭遇した問題のコードは上記よりも複雑です。上記のコードは、問題を説明するために私が特別に簡略化したものです。おそらくコードから問題をすでに理解しているかもしれませんが、なぜこれが起こるのかについては。まだまだ分析が必要かと思います。こうすることで、今後 PHP を使用するときに同じ間違いを犯すことはなくなります。

コピーを減らすために、PHP はコピーオンライター機構を採用しています。これは非常に一般的なメカニズムであり、おそらく聞いたことがあると思います。たとえば、gcc の stl 文字列の実装では、このようなメカニズムが使用されています。文字列の割り当ては実際のコピーではなく、変更された場合にのみコピーされます。まず最も単純な例を見てみましょう:

リーリー

$a が非常に大きな文字列である場合、$b = $a をコピーすると大量のメモリと CPU が消費され、非常に不経済です。次のコードは $a と $b を変更しないため、コピーは行われません。まったく必要です。もちろん、$a は後で変更されます。コピーしないと論理的ではありません。しかし、ここで疑問が生じます。$a が変更されると、そのようなマークがなければコピーされなければならないことをどのようにして知ることができるのでしょうか。この方法は参照カウントを使用することです。参照カウントはメモリ管理にも使用されます。

基本的なプロセスは次のとおりです:

1: 10,000 個のゼロの文字列を保持できる変数を作成します。

2: この変数を参照する変数シンボル a を作成します。変数シンボルと変数は同じものではなく、別のものであることに注意してください。

C 言語の観点から見ると、PHP はおそらく次のことを実現します:

リーリー

active_symbol_table は PHP のシンボルテーブルであり、アクセス可能な変数はすべてこの中にあります。変数 var には、10,000 個のゼロの文字列が格納されます。そして、zvalの構造です。 zvalの構造は次のとおりです。 リーリー

zvalue_value は、long、double、string、ハッシュ テーブル (PHP 配列)、オブジェクトを保存できるユニオンです。つまり、すべての PHP タイプです。実際、zval は zvalue_value に、type、reference is_ref、および参照カウント refcount の 3 つの関数を追加したものです。これは PHP の単なる通常の変数です。 PHP を使用して大規模な処理を実行すると、メモリの使用量が非常に多くなることがわかります。この変数は従来の C 言語の変数ではなくなったため、多くのことが追加されます。

さて、最初の文は完了しました。ここで 2 番目の文です。 2 番目の文は非常に単純です。新しい変数シンボル b を生成し、それを active_symbol_table に追加します。ただし、新しい変数は追加されず、refcount++ のみが追加されます。任務は完了しました。写真に示すように:

まず第一に、a と b は単なるシンボルであり、active_symbol_table テーブル内のキーであり、どちらも zval を指すポインターを持っていることに注意する必要があります。したがって、a と b は C 言語レベルで完全に一貫しています。 PHP 変数の第一法則が得られます:

PHP 変数の第一法則: 2 つの変数が同じ zval を指している場合、2 つの変数は区別できません。つまり、a に対するすべての操作は b に関して対称です。ここでの対称性は次のように理解されます。鏡の中のあなたは同じではありません。たとえば、 a に値が割り当てられている場合、 a はコピーを作成します。同様に、b に値を代入すると、同じ操作が実行されます。つまり、b はコピーを生成します。つまり、a と b は同じように動作します。

3 番目の文では、writer が発生すると、PHP は refcount が 2 より大きいかどうかを判断します。2 より大きい場合は、zval をコピーし、元の zval を refcount-- に置き換えます。これはすべてコピーオンライターに関するものです。あなたはこれらすべてをよく知っており、理解していると感じているはずです。

但是,PHP不仅仅是copy on writer 这样简单,它还有一个引用的问题。引入引用的概念,这样,问题就变的有些复杂了。因为,引用这个标记,意思就是说,writer 的时候,你也不需要复制。这样,会修改原来的那个变量。从我们在学校里面以前经常学习的哲学上来说,这是一对矛盾。他们是对立的,又是统一的,各有各的用处。所谓,存在的就是合理的。

好,下面我们来看看这对矛盾,我们只考虑两种组合的情况。多种组合都是类似的。两种组合的话,就是赋值在前,引用在后。

或者  引用在前,赋值在后。我们会分别讨论,先来看:就是赋值在前,引用在后的情况。

  $a = ;
   $b = $a;
   $c = &$a;
ログイン後にコピー

$b = $a, 是copy on writer 行为的 赋值。而 $c 和 $a 是引用赋值。我们假设在上面这样的情况下,我们可以用一个zval表示,也就是不需要复制,那么情况是这样的:

根据我们的PHP变量第一定律,那,就是说,a,b,c的操作是对称的,但是非常明显,对 b 操作要产生复制行为,而对a操作不会产生复制,操作行为不相同,和第一定律矛盾。也就是说,要使得上面的操作没有矛盾,必须,进行分离。分离的原则就是,谁制造矛盾,谁复制。显然是 第三句话,$c = &$a; 在制造矛盾。所以,内部变量的复制过程如下图:

上面情况是赋值在前,引用在后的情况。还有一种情况是,引用在前赋值在后:

 $a = ;
   $b = &$a;
   $c = $a;
ログイン後にコピー

按照PHP变量的第一定律,a,b,c 必须进行分离,才能保证定律的正确。可以发现,b 和 a 明显是一伙人,就是说,b 和 a 的操作是对称的,他们可以指向同一个zval ,而c 的行为和 a,b 不一样,改变c 需要进行复制。看到这里,我想,如果你看懂了的话,为什么刚开始,贴出来的那段代码的,那个两个count差异如此之大,你也应该明白了。当我和那个网友讨论的时候,它最后说,那这样的话,PHP设计的不好,我完全可以,$c先不进行复制,等c被write 了,再进行复制。看来要说懂一个东西,还是一件很难的事情,好好想想那个PHP第一定律吧。你可以假设不进行分离,c指向同一个zval,所以,c 和 a,b的行为是一样的,是is_ref = 1,所以,c 不会进行复制。最后一种内部执行情况可以用下图表示:

我以前也进行搞混这个引用,现在,你可以用那个第一定律来分析所有的情况了。PHP内核分析的文章,以后我还会写一些,如果你想深入了解PHP的某些方面,可以给我留言。

最后再补充一点,也是一个隐性的错误。

function count_bigarray()
{
 global $bigarray;
 return count($bigarray);
}
ログイン後にコピー

这里,没有显示的引用,但是这里隐藏了一个引用。PHP会自动创建一个引用全局变量 $bigarray 的代码,如果你在这里使用count,那么这个效率会非常的慢。最好直接通过$GLOBAL 数组进行引用。

下面文章将给大家介绍深入理解php内核二之SAPI探究,希望大家继续关注哦。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1069346.htmlTechArticle深入理解PHP内核(一),深入理解php内核 PHP作为一门简单而强大的语言,能够提供很多Web适用的语言特性。从实践出发,继弱类型变量原理探...
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!