この記事では、PHP の参照カウントのメモリ管理メカニズムとガベージ コレクション メカニズムについて説明します。助けが必要な友人は参照してください。
参照の代入
$a = 'apple'; $b = &$a;
上記のコードでは、変数 a に文字列を割り当てます。次に、a の参照を変数 b に代入します。明らかに、この時点で指すメモリは次のようになるはずです:
$a -> 'apple' <p>a と b は同じメモリ領域 (変数コンテナ <em>zval</em>) を指します。これは <code>var_dump($a, $b) を通じて取得します。 code> <code>string(5) "apple" string(5) "apple"</code> 、これは予期された結果です。 <code>var_dump($a, $b)</code> 得到 <code>string(5) "apple" string(5) "apple"</code> ,这是我们预期的结果。</code></p><h2 id="unset函数-与-引用计数">unset函数 与 引用计数</h2><h3 id="unset-函数">unset 函数</h3><p>假如我想将 <code>'apple'</code> 这个字符串从内存中释放掉。我是这么做的:</p><pre class="brush:php;toolbar:false">unset($a);
但是通过再次打印 $a
$b
两变量的信息,我得到了这样的结果:Notice: Undefined variable: a
和 string(5) "apple"
。奇怪,$a
$b
指向同一个变量容器,又明明将$a
释放了,为什么$b还是'apple'
。
其实是这样的,unset()
只是将一个变量符号a
(指针)销毁了,并没有释放掉那个变量容器,所以执行完操作之后,内存指向只是变成了这样:
'apple'引用计数
引用计数 (reference count)是每个变量容器中都会存放的一条信息,它表示当前变量容器正被多少个变量符号所引用。
正如之前的例子,unset()并没有释放变量所指向的变量容器,而只是将变量符号销毁了。同时,将变量容器中的 引用计数 减1,当引用计数为0时,也就是说当变量容器不被任何变量引用时,便会触发php的垃圾回收(错误),它便会被释放(正确)。
更正上述的一个小错误: 这种单纯的引用计数方式是 php 5.2 之前的内存管理机制,称不上是垃圾回收机制,垃圾回收机制是 php 5.3 才引入的,垃圾回收机制为的是解决这种单纯的引用计数内存管理机制的缺陷(即 循环引用导致的内存泄漏,下文会进行讲解)
回到正题,我们用代码来验证一下先前的结论:
$a = 'apple'; $b = &$a; $before = memory_get_usage(); unset($a); $after = memory_get_usage(); var_dump($before - $after); // 结果为int(0),变量容器的引用计数为1,没有释放$a = 'apple'; $b = &$a; $before = memory_get_usage(); unset($a, $b); $after = memory_get_usage(); var_dump($before - $after); // 结果为int(24),变量容器的引用计数为0,得到释放直接释放
那要怎样做才能真正释放掉
'apple'
所占用的内存呢?利用上述方法,我们可以在
unset($a)
之后再unset($b)
,将变量容器的所有引用都销毁,引用计数减为0了,自然就被释放掉了。当然,还有更直接的方法:
$a = null;直接赋值
null
会将$a
所指向的内存区域置空,并将引用计数归零,内存便被释放。脚本执行结束后的内存
对于一般的web程序来说(fpm模式下),php的执行是单线程同步阻塞型的,当脚本执行结束之后,脚本内使用的所有内存都会被释放。那么,我们手动去释放内存到底有意义吗?
其实关于这个问题,早有解答,推荐大家看一下鸟哥 @laruence 2012年发表的一篇文章:
请手动释放你的资源(Please release resources manually)引用计数内存管理机制的缺陷:循环引用
现在我们来讲讲之前提到的引用计数内存管理机制的缺陷。
当一个变量容器的引用计数为0时,php会进行垃圾回收。但是,你可想过,有一种情况会导致一个变量容器的引用计数永远不会被减为0,举个例子:
$a = ['one']; $a[] = &$a;我们看到,
$a
数组第二个元素就是它本身。那么,存放数组的这个变量容器的引用计数为2,一个引用是变量a
,另一个引用是这个数组的第二个元素 - 索引1
。
那么,如果这时我们
unset 関数と参照カウントunset($a)
,存放数组的变量容器的引用计数会减1,但还有1个引用,就是数组的元素1
unset 関数
文字列'apple'
をメモリから解放したいとします。これが私がやったことです:rrreee しかし、
$a
$b
という 2 つの変数の情報を再度出力すると、次の結果が得られました:Notice: Unknown variable : a
とstring(5) "apple"
。奇妙なことに、$a
$b
は同じ変数コンテナを指していますが、$a
は明らかに解放されています。なぜ $b はのままなのでしょうか。リンゴ '
。実際には、これが当てはまります。
rrreeeunset()
は変数シンボルa
(ポインター) を破棄するだけで、変数コンテナーを解放しません。そのため、操作が完了した後、メモリ ポインタは次のようになります。Reference Count
参照カウント (参照カウント) は、各変数コンテナに格納されている情報であり、現在の変数によって使用されている変数シンボルの数を示します。コンテナ。 前の例と同様に、unset() は変数が指す変数コンテナを解放せず、変数シンボルを破棄するだけです。同時に、変数コンテナの
参照数🎜を1減らします。参照数が0の場合、つまり、変数コンテナがどの変数からも参照されていない場合、 PHP のガベージ コレクションがトリガーされ (誤) 🎜、解放されます (正)。 🎜🎜🎜上記の小さなエラーの修正: この単純な参照カウント方法は、PHP 5.2 より前のメモリ管理メカニズムであり、ガベージ コレクション メカニズムとは PHP 5.3 でのみ導入されました。コレクションメカニズムは、この単純な参照カウントメモリ管理メカニズムの欠点 (つまり、循環参照によって引き起こされるメモリリーク、以下で説明します) を解決します 🎜🎜🎜 トピックに戻り、コードを使用して前の結論を検証します: 🎜rrreeerrreee🎜直接解放🎜🎜 それでは、'apple'
が占有しているメモリを実際に解放するにはどうすればよいでしょうか? 🎜🎜上記のメソッドを使用すると、unset($a)
してからunset($b)
を実行して、変数コンテナへのすべての参照を破棄し、参照カウントを 0 に減らすことができます。 、自然にリリースされました。 🎜🎜もちろん、もっと直接的な方法もあります: 🎜rrreee🎜null
を直接代入すると、$a
が指すメモリ領域が空になり、参照カウントがゼロにリセットされます。 . メモリが解放されます。 🎜🎜スクリプト実行終了後のメモリ🎜🎜 一般的なWebプログラム(fpmモード)の場合、PHPの実行はシングルスレッド同期ブロッキングであり、スクリプトの実行が終了すると、スクリプトで使用されていたすべてのメモリが解放されます。では、手動でメモリを解放するのは意味があるのでしょうか? 🎜🎜実際、この質問は長い間解決されてきましたが、2012 年に Brother Bird @laruence が公開した記事を読むことをお勧めします。 🎜リソースを手動で解放してください (リソースを手動で解放してください)🎜参照カウントのメモリ管理メカニズムの欠陥: 循環参照🎜🎜 ここで、前述した参照カウントのメモリ管理メカニズムの欠陥について話しましょう。 🎜🎜変数コンテナの参照カウントが0になると、PHPはガベージコレクションを実行します。ただし、考えたことはありますか。変数コンテナの参照カウントが 0 に減らない状況が存在します。例: 🎜rrreee🎜$a array 要素はそれ自体です。次に、配列を格納する変数コンテナの参照カウントは 2 で、1 つの参照は変数 <code>a
で、もう 1 つの参照は配列の 2 番目の要素 - インデックス1
です。 。 🎜🎜🎜🎜🎜🎜次に、
unset( $a )
の場合、配列を格納する変数コンテナの参照数は 1 減りますが、参照はまだ 1 つあります。これは配列の要素1
になります。次のように: 🎜🎜 🎜🎜🎜🎜🎜変数コンテナの参照カウントが 0 に変更されていないため、解放できません。また、現時点ではそれを参照している他の外部変数シンボルはなく、ユーザーは解放する方法がありません。この構造をクリアすれば、それは永遠にそこに残ります。 🎜🎜そのため、コード内にそのような構造や操作が多数ある場合、最終的にはメモリの損失やリークさえも発生します。 🎜循環参照🎜によりメモリが解放できない問題です。 🎜幸いなことに、fpm モードでは、要求されたスクリプトの実行が終了すると、PHP はこの構造を含むスクリプトで使用されているすべてのメモリを解放します。しかし、それがデーモンプロセス下の php プログラムの場合はどうなるでしょうか?スウールなど。 php で解決する必要があるこの緊急の問題 (すでに解決されています。以下を参照してください)。
PHP 5.3.0で導入された同期アルゴリズム
伝統的に、過去にPHPで使用されていた参照カウントメモリメカニズムは、循環参照のメモリリークを処理できません。ただし、5.3.0 PHP の使用法に関する記事「参照カウント システムの同時サイクル コレクション」にある同期アルゴリズムは、このメモリ リークの問題を解決します。このアルゴリズムは、PHP のガベージ コレクション メカニズムです。
特定のアルゴリズムの実装とプロセスは少し複雑です。ここでは詳しく説明しませんが、アルゴリズムのプロセスを説明する記事へのリンクもいくつか添付します:
http ://php.net/manual/zh/feat... 公式ドキュメント
http://www.cnblogs.com/leoo2s...
https://blog.csdn.net/phpkern...最後に、私はまだNiao兄弟の記事を引用しています これらの2つの段落は問題を説明しています:
PHP5.2以前、PHPはリソース管理に参照カウントを使用していましたが、zvalの参照カウントが0の場合、循環参照が存在します。 ( 循環参照 ) しかし、Web スクリプトの特性と目的は実行時間が短く、長時間実行されないため、このような設計は Web スクリプト開発には問題ありません。循環参照によるリソース リークは最後に発生します。つまり、リクエストが終了したときにリソースを解放するのが救済措置 (バックアップ) ですただし、PHP を使用する人が増えるにつれて、多くの人がいくつかのバックグラウンド スクリプトで PHP を使用するようになります。スクリプトが長時間実行されると、参照カウントが時間内に未使用のリソースを解放できなくなり、最終的にはスクリプトがメモリ不足になって終了するため、PHP5.3 以降では導入されました。 GC、つまりユーザーが解決できない問題を解決するために GC を導入しました
以上がPHP 参照カウントのメモリ管理メカニズムとガベージ コレクション メカニズムの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

まだ人気があるのは、使いやすさ、柔軟性、強力なエコシステムです。 1)使いやすさとシンプルな構文により、初心者にとって最初の選択肢になります。 2)Web開発、HTTP要求とデータベースとの優れた相互作用と密接に統合されています。 3)巨大なエコシステムは、豊富なツールとライブラリを提供します。 4)アクティブなコミュニティとオープンソースの性質は、それらを新しいニーズとテクノロジーの傾向に適応させます。

PHPとPythonはどちらも、Web開発、データ処理、自動化タスクで広く使用されている高レベルのプログラミング言語です。 1.PHPは、ダイナミックウェブサイトとコンテンツ管理システムの構築によく使用されますが、PythonはWebフレームワークとデータサイエンスの構築に使用されることがよくあります。 2.PHPはエコーを使用してコンテンツを出力し、Pythonは印刷を使用します。 3.両方ともオブジェクト指向プログラミングをサポートしますが、構文とキーワードは異なります。 4。PHPは弱いタイプの変換をサポートしますが、Pythonはより厳しくなります。 5. PHPパフォーマンスの最適化には、Opcacheおよび非同期プログラミングの使用が含まれますが、PythonはCprofileおよび非同期プログラミングを使用します。

PHPは主に手順プログラミングですが、オブジェクト指向プログラミング(OOP)もサポートしています。 Pythonは、OOP、機能、手続き上のプログラミングなど、さまざまなパラダイムをサポートしています。 PHPはWeb開発に適しており、Pythonはデータ分析や機械学習などのさまざまなアプリケーションに適しています。

PHPは1994年に発信され、Rasmuslerdorfによって開発されました。もともとはウェブサイトの訪問者を追跡するために使用され、サーバー側のスクリプト言語に徐々に進化し、Web開発で広く使用されていました。 Pythonは、1980年代後半にGuidovan Rossumによって開発され、1991年に最初にリリースされました。コードの読みやすさとシンプルさを強調し、科学的コンピューティング、データ分析、その他の分野に適しています。

PHPはWeb開発と迅速なプロトタイピングに適しており、Pythonはデータサイエンスと機械学習に適しています。 1.PHPは、単純な構文と迅速な開発に適した動的なWeb開発に使用されます。 2。Pythonには簡潔な構文があり、複数のフィールドに適しており、強力なライブラリエコシステムがあります。

PHPは、多数のWebサイトとアプリケーションをサポートし、フレームワークを通じて開発ニーズに適応するため、近代化プロセスで依然として重要です。 1.PHP7はパフォーマンスを向上させ、新機能を紹介します。 2。Laravel、Symfony、Codeigniterなどの最新のフレームワークは、開発を簡素化し、コードの品質を向上させます。 3.パフォーマンスの最適化とベストプラクティスは、アプリケーションの効率をさらに改善します。

phphassiblasifly-impactedwebdevevermentandsbeyondit.1)itpowersmajorplatformslikewordpratsandexcelsindatabase interactions.2)php'sadaptableability allowsitale forlargeapplicationsusingframeworkslikelavel.3)

PHPタイプは、コードの品質と読みやすさを向上させるためのプロンプトがあります。 1)スカラータイプのヒント:php7.0であるため、基本データ型は、int、floatなどの関数パラメーターで指定できます。 3)ユニオンタイプのプロンプト:PHP8.0であるため、関数パラメーターまたは戻り値で複数のタイプを指定することができます。 4)Nullable Typeプロンプト:null値を含めることができ、null値を返す可能性のある機能を処理できます。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

SublimeText3 中国語版
中国語版、とても使いやすい

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

ドリームウィーバー CS6
ビジュアル Web 開発ツール

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境
