久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

PHP V5.2 中的新增功能,,第 1 部分: 使用新的內(nèi)存管理器

 滄海九粟 2007-07-20

PHP V5.2:開始

2006 年 11 月發(fā)布了 PHP V5.2,,它包括許多新增功能和錯(cuò)誤修正,。它廢止了 5.1 版并被推薦給所有 PHP V5 用戶進(jìn)行升級(jí),。我最喜歡的實(shí)驗(yàn)室環(huán)境 —— Windows®,、Apache,、MySQL、PHP (WAMP) —— 已經(jīng)被引入了 V5.2 的新軟件包中(請(qǐng)參閱 參考資料),。您將在那里找到在 Windows® XP 或 2003 計(jì)算機(jī)上安裝 PHP V5.2,、MySQL 和 Apache 的應(yīng)用程序。您可以十分輕松地進(jìn)行安裝,,它有很多不錯(cuò)的小的管理優(yōu)點(diǎn),,并且我十分誠懇地推薦使用它。

雖然對(duì)于 Windows 用戶來說,,這是最簡(jiǎn)單的軟件包,,但是在 Linux 上配置 PHP 時(shí)您需要添加以下代碼:--memory-limit-enabled(適用于您服務(wù)器的任何其他選項(xiàng)除外)。不過,,在 Windows 下,,提供了一個(gè)解決此問題的函數(shù)。

PHP V5.2 中有很多改進(jìn)之處,,并且一個(gè)至關(guān)重要的領(lǐng)域是內(nèi)存管理,。從 README.ZEND_MM 中準(zhǔn)確地引述就是:“新內(nèi)存管理器(PHP5.2 以及更高版本)的目標(biāo)是減少內(nèi)存分配開銷并加速內(nèi)存管理。”

下面是 V5.2 發(fā)行說明中的一些關(guān)鍵內(nèi)容:

  • 刪除了不必要的 --disable-zend-memory-manager 配置選項(xiàng)
  • 添加了 --enable-malloc-mm 配置選項(xiàng),,調(diào)試構(gòu)建時(shí)此配置選項(xiàng)將被默認(rèn)啟用以允許使用內(nèi)部和外部?jī)?nèi)存調(diào)試程序
  • 允許使用 ZEND_MM_MEM_TYPEZEND_MM_SEG_SIZE 環(huán)境變量調(diào)整內(nèi)存管理器

為了理解這些新增功能的含義,,我們需要深入研究?jī)?nèi)存管理中的藝術(shù),并考慮為什么分配開銷和運(yùn)行速度是大問題,。





回頁首


為什么進(jìn)行內(nèi)存管理,?

計(jì) 算中開發(fā)最快速的一項(xiàng)技術(shù)是內(nèi)存和數(shù)據(jù)存儲(chǔ),它們是受不斷增加速度和存儲(chǔ)大小這樣持續(xù)的需求而驅(qū)動(dòng)的,。早期的計(jì)算機(jī)使用卡作為內(nèi)存,,然后轉(zhuǎn)向了芯片技術(shù),。 您能想象在只有 1 KB RAM 內(nèi)存的計(jì)算機(jī)工作的情景嗎?很多早期的計(jì)算機(jī)程序員就曾使用過,。這些先驅(qū)者很快就意識(shí)到,,要在技術(shù)限制下工作,他們將必須細(xì)心地用瑣碎的命令避免系統(tǒng)過 載,。

身為 PHP 開發(fā)人員,,與使用 C++ 或其他更嚴(yán)格的語言編碼的同事相比,我們所在的環(huán)境更方便進(jìn)行編碼,。在我們的世界里,,我們自己不必?fù)?dān)心如何處理系統(tǒng)內(nèi)存,因?yàn)?PHP 將為我們處理這個(gè)問題,。但是,,在其他編程領(lǐng)域里,負(fù)責(zé)任的編碼人員將使用各種函數(shù)確保執(zhí)行的命令不會(huì)覆蓋其他一些程序數(shù)據(jù) —— 因而,,破壞了程序的運(yùn)行,。

內(nèi)存管理通常是由來自編碼人員的請(qǐng)求處理的,以分配和釋放內(nèi)存塊,。分配塊 可以保存任何類型的數(shù)據(jù),,并且此過程將為該數(shù)據(jù)隔開一定量的內(nèi)存,,并當(dāng)操作需要訪問數(shù)據(jù)時(shí)為應(yīng)用程序提供訪問方法,。人們期望程序在完成任何操作后釋放分配的內(nèi)存,并允許系統(tǒng)和其他程序員使用該內(nèi)存,。如果程序沒有把內(nèi)存釋放回系統(tǒng),,則稱為內(nèi)存泄露

泄露是任何運(yùn)行程序都存在的普遍問題,,并且某種程度內(nèi)通常是可以接受的,,尤其是當(dāng)我們知道運(yùn)行程序?qū)⒘⒓唇K止并釋放默認(rèn)分配給程序的所有內(nèi)存。

由 于隨機(jī)運(yùn)行和終止程序,,像幾乎所有客戶機(jī)應(yīng)用程序一樣,,這是個(gè)問題。期望服務(wù)器應(yīng)用程序不確定地運(yùn)行而不終止或重新啟動(dòng),,這使得內(nèi)存管理對(duì)于服務(wù)器守護(hù)程 序編程絕對(duì)的至關(guān)重要,。在長(zhǎng)時(shí)間運(yùn)行的程序中,即使一個(gè)小的泄露最后都將發(fā)展為系統(tǒng)衰弱問題,,因?yàn)閮?nèi)存塊已被使用并且永遠(yuǎn)不被釋放,。





回頁首


長(zhǎng)期考慮

正如使用任何語言編寫一樣,用 PHP 編寫的永久性服務(wù)器守護(hù)程序有很多可能的用途,。但是當(dāng)我們出于這些目的開始使用 PHP 時(shí),,我們也必須考慮內(nèi)存使用情況,。

解 析大量數(shù)據(jù)或可能隱藏?zé)o限次循環(huán)的腳本都趨于消耗大量?jī)?nèi)存。很明顯,,一旦內(nèi)存被耗盡,,服務(wù)器的性能就降低,因此在執(zhí)行腳本時(shí)我們還必須注意內(nèi)存的使用情 況,。雖然我們可以通過啟用系統(tǒng)監(jiān)視器來簡(jiǎn)單觀察內(nèi)存的使用量,,但是它不會(huì)告訴我們比整個(gè)系統(tǒng)內(nèi)存狀態(tài)更有用的任何內(nèi)容。有時(shí)我們不止需要幫助進(jìn)行故障檢修 或優(yōu)化的內(nèi)容,,而有時(shí)我們只是需要更多詳細(xì)信息,。

獲得腳本執(zhí)行內(nèi)容的透明性的一種方法是使用內(nèi)部或外部調(diào)試器。內(nèi)部調(diào)試器 是呈現(xiàn)為執(zhí)行腳本的相同的進(jìn)程,。從操作系統(tǒng)的角度考慮的獨(dú)立進(jìn)程是外部調(diào)試器,。使用調(diào)試器進(jìn)行內(nèi)存分析類似于任何一種情況,但是使用了不同的方法訪問內(nèi)存,。內(nèi)部調(diào)試器對(duì)運(yùn)行進(jìn)程所在的內(nèi)存空間具有直接訪問權(quán),,而外部調(diào)試器將通過套接字訪問內(nèi)存。

有許多方法和可用的調(diào)試服務(wù)器(外部)和庫(內(nèi)部)可用于輔助開發(fā),。為了準(zhǔn)備好對(duì) PHP 安裝進(jìn)行調(diào)試,,可以使用新提供的 --enable-malloc-mm,它在 DEBUG 構(gòu)建中默認(rèn)被啟用,。這使環(huán)境變量 USE_ZEND_ALLOC 可用于允許在運(yùn)行時(shí)選擇 mallocemalloc 內(nèi)存分配,。使用 malloc-type 內(nèi)存分配將允許外部調(diào)試器觀察內(nèi)存使用情況,而 emalloc 分配將使用 Zend 內(nèi)存管理器抽象,,要求進(jìn)行內(nèi)部調(diào)試,。





回頁首


PHP 中的內(nèi)存管理函數(shù)

除了使內(nèi)存管理器更靈活更透明之外,PHP V5.2 還為 memory_get_usage()memory_get_peak_usage() 提供了一個(gè)新參數(shù),,這兩個(gè)函數(shù)允許查看內(nèi)存使用量,。說明中提及的新布爾值是 real_size。通過調(diào)用函數(shù) memory_get_usage($real);(其中 $real = true),,結(jié)果將為調(diào)用時(shí)系統(tǒng)中實(shí)際分配的內(nèi)存大小,,包括內(nèi)存管理器開銷。如果不使用標(biāo)記組,,則返回的數(shù)據(jù)將只包括在運(yùn)行腳本內(nèi)使用的內(nèi)存,,減去內(nèi)存管理器開銷。

memory_get_usage()memory_get_peak_usage() 的不同之處在于后者將返回到目前為止調(diào)用它的運(yùn)行進(jìn)程的最高內(nèi)存量,,而前者只返回執(zhí)行時(shí)的使用量,。

對(duì)于 memory_get_usage(), 提供了清單 1 中的代碼片段。


清單 1. memory_get_usage() 示例
                
<?php

// This is only an example, the numbers below will
// differ depending on your system

echo memory_get_usage() . "\n"; // 36640
$a = str_repeat("Hello", 4242);
echo memory_get_usage() . "\n"; // 57960
unset($a);
echo memory_get_usage() . "\n"; // 36744

?>

在這個(gè)簡(jiǎn)單示例中,,我們首先回轉(zhuǎn)了直接調(diào)用 memory_get_usage() 的結(jié)果,,代碼注釋中顯示可能在作者的系統(tǒng)中有 36640 字節(jié)的常見結(jié)果,。然后我們使用 4,242 個(gè) “Hello” 副本來裝載 $a 并再次運(yùn)行函數(shù),。圖 1 中可以看到此簡(jiǎn)單應(yīng)用的輸出。


圖 1. memory_get_usage() 的示例輸出
memory_get_usage() 的示例輸出

沒有 memory_get_peak_usage() 的示例,,因?yàn)閮烧呤窒嗨?,語法是相同的,。但是,對(duì)于清單 1 中的示例代碼,,將只有一個(gè)結(jié)果,,即當(dāng)時(shí)的最高內(nèi)存使用量。讓我們看一看清單 2,。


清單 2. memory_get_peak_usage() 示例
                
<?php

// This is only an example, the numbers below will
// differ depending on your system

echo memory_get_peak_usage() . "\n"; // 36640
$a = str_repeat("Hello", 4242);
echo memory_get_peak_usage() . "\n"; // 57960
unset($a);
echo memory_get_peak_usage() . "\n"; // 36744

?>

清單 2 中的代碼跟圖 1 一樣,,但是 memory_get_usage() 已經(jīng)替換為 memory_get_peak_usage()。在我們用 4242 個(gè) “Hello” 副本填充 $a 之前,,輸出都不會(huì)有多大更改,。內(nèi)存跳升至 57960,表示到目前為止的峰值,。當(dāng)檢查內(nèi)存使用量峰值時(shí),,得到了目前為止的最高值,因此所有進(jìn)一步調(diào)用都將得到 57960,,直至我們處理的操作比處理 $a 使用的內(nèi)存更多(參見圖 2),。


圖 2. memory_get_peak_usage() 的示例輸出
memory_get_peak_usage() 的示例輸出





回頁首


限制內(nèi)存使用

確 保托管應(yīng)用程序的服務(wù)器不過載的一種方法是限制 PHP 執(zhí)行的任何腳本使用的內(nèi)存量。這根本不是我們應(yīng)當(dāng)執(zhí)行的操作,,但由于 PHP 是一種松散類型的語言,,并且是在運(yùn)行時(shí)解析的,,因此我們有時(shí)會(huì)獲得在釋放到生產(chǎn)應(yīng)用程序中后編寫得很差的腳本,。這些腳本可能執(zhí)行循環(huán),也可能打開一張長(zhǎng)的 文件列表,,忘記在打開新文件之前先關(guān)閉當(dāng)前文件,。無論在哪一種情況下,編寫很差的腳本可能在您知道之前以消耗大量?jī)?nèi)存告終,。

在 PHP.INI 中,,您可以使用配制參數(shù) memory_limit 來指定任何腳本能夠在系統(tǒng)中運(yùn)行的最大內(nèi)存使用量。這不是對(duì)于 V5.2 的特定更改,,但是內(nèi)存管理器及其使用的任何討論都值得至少快速查看一次這個(gè)特性,。它還精心地引導(dǎo)我使用內(nèi)存管理器的最后幾個(gè)新功能:環(huán)境變量。





回頁首


調(diào)整內(nèi)存管理器

最后,在不能做完美主義者但是又完全符合自己目的的情況下怎樣編程,?新環(huán)境變量 ZEND_MM_MEM_TYPEZEND_MM_SEG_SIZE 正好可以滿足您的需求,。

當(dāng)內(nèi)存管理器分配大型內(nèi)存塊時(shí),它是安裝 ZEND_MM_SEG_SIZE 變量中列出的預(yù)定大小執(zhí)行操作的,。這些內(nèi)存塊的默認(rèn)分區(qū)大小為每塊 256 KB,,但是您可以調(diào)整這些分區(qū)大小以滿足特殊需求。例如,,如果您注意到最常用的一個(gè)腳本中的操作導(dǎo)致大量的內(nèi)存浪費(fèi),,則可以將此大小調(diào)整為更接近匹配腳本 需求的值,減少分配的內(nèi)存量但剩下的內(nèi)存量仍然為零,。在正確的條件下,,此類謹(jǐn)慎的配制調(diào)整可能造成巨大差別。





回頁首


在 Windows 中檢索內(nèi)存使用情況

如果具有預(yù)構(gòu)建的 PHP Windows 二進(jìn)制代碼,,而沒有在構(gòu)建時(shí)使用 --enable-memory-limit 選項(xiàng),,則需要先瀏覽此部分然后再繼續(xù)。對(duì)于 Linux®,,配置 PHP 構(gòu)建時(shí)用 --enable-memory-limit 選項(xiàng)構(gòu)建 PHP,。

要使用 Windows 二進(jìn)制代碼檢索內(nèi)存使用情況,請(qǐng)創(chuàng)建以下函數(shù),。


清單 3. 在 Windows 下獲得內(nèi)存使用情況
                
<?php

function memory_get_usage(){
$output = array();
exec(‘tasklist /FI "PID eq ‘.getmypid().‘" /FO LIST‘, $output );
return preg_replace( ‘/[^0-9]/‘, ‘‘, $output[5] ) * 1024;
}

?>

將結(jié)果保存到名為 function.php 的文件?,F(xiàn)在您只能將此文件包含在需要使用它的腳本中。





回頁首


動(dòng)手實(shí)踐

讓 我們來看一看使用這些設(shè)置的實(shí)際示例給我們帶來的好處,??赡苡泻芏啻文枷胫罏槭裁丛谀_本的末尾沒有正確分配內(nèi)存。原因是因?yàn)橐恍┖瘮?shù)本身導(dǎo)致了內(nèi)存泄 露,,尤其是在僅使用內(nèi)置 PHP 函數(shù)的情況下,。在這里,您將了解如何發(fā)現(xiàn)此類問題,。并且為了開始進(jìn)行內(nèi)存泄露查找的征戰(zhàn),,您將創(chuàng)建一個(gè)測(cè)試 MySQL 數(shù)據(jù)庫,如清單 4 所示,。


清單 4. 創(chuàng)建測(cè)試數(shù)據(jù)庫
                
mysql> create database memory_test;

mysql> use memory_test;

mysql> create table leak_test
( id int not null primary key auto_increment,
data varchar(255) not null default ‘‘);

mysql> insert into leak_test (data) values ("data1"),("data 2"),
("data 3"),("data 4"),("data 5"),("data6"),("data 7"),
("data 8"),("data 9"),("data 10");

這將創(chuàng)建一個(gè)帶有 ID 字段和數(shù)據(jù)字段的簡(jiǎn)單表,。

在下一張清單中,想象我們堅(jiān)韌不拔的程序員正在執(zhí)行一些 MySQL 函數(shù),,特別是使用 mysql_query() 將結(jié)果應(yīng)用到變量,。當(dāng)他這樣做時(shí),他將注意到即使調(diào)用 mysql_free_result(),,一些內(nèi)存也不會(huì)被釋放,,導(dǎo)致內(nèi)存使用量隨著 Apache 進(jìn)程不斷增長(zhǎng)(參見清單 5)。


清單 5. 內(nèi)存泄露檢測(cè)示例
                
for ( $x=0; $x<300; $x++ ) {
$db = mysql_connect("localhost", "root", "test");
mysql_select_db("test");
$sql = "SELECT data FROM test";
$result = mysql_query($sql); // The operation suspected of leaking
mysql_free_result($result);
mysql_close($db);
}

清單 5 是在任何位置都可能使用的簡(jiǎn)單 MySQL 數(shù)據(jù)庫操作。在運(yùn)行腳本時(shí),,我們注意到一些與內(nèi)存使用量相關(guān)的奇怪行為并需要將其檢查出來,。為了使用內(nèi)存管理函數(shù)以使我們可以檢驗(yàn)發(fā)生錯(cuò)誤的位置,我們將使用以下代碼,。


清單 6. 定標(biāo)查找錯(cuò)誤的示例
                
<?php

if( !function_exists(‘memory_get_usage‘) ){
include(‘function.php‘);
}

echo "At the start we‘re using (in bytes): ",
memory_get_usage() , "\n<br>";

$db = mysql_connect("localhost", "user", "password");
mysql_select_db("memory_test");

echo "After connecting, we‘re using (in bytes): ",
memory_get_usage(),"\n<br>";

for ( $x=0; $x<10; $x++ ) {
$sql =
"SELECT data FROM leak_test WHERE id=‘".$x."‘";
$result = mysql_query($sql); // The operation
// suspected of leaking.
echo "After query #$x, we‘re using (in bytes): ",
memory_get_usage(), "\n<br>";
mysql_free_result($result);
echo "After freeing result $x, we‘re using (in bytes): ",
memory_get_usage(), "\n<br>";
}

mysql_close($db);
echo "After closing the connection, we‘re using (in bytes): ",
memory_get_usage(), "\n<br>";
echo "Peak memory usage for the script (in bytes):".
memory_get_peak_usage();

?>

注:按照定義的時(shí)間間隔檢查當(dāng)前內(nèi)存使用量,。在下面的輸出中,通過顯示我們的腳本一直在為函數(shù)分配內(nèi)存,,并且在應(yīng)當(dāng)釋放的時(shí)候沒有釋放內(nèi)存,,從而提供對(duì)內(nèi)存泄露的實(shí)際測(cè)試,您可以看到每次調(diào)用時(shí)內(nèi)存使用量如何增長(zhǎng),。


清單 7. 測(cè)試腳本輸出
                
At the start we‘re using (in bytes): 63216
After connecting, we‘re using (in bytes): 64436
After query #0, we‘re using (in bytes): 64760
After freeing result 0, we‘re using (in bytes): 64828
After query #1, we‘re using (in bytes): 65004
After freeing result 1, we‘re using (in bytes): 65080
After query #2, we‘re using (in bytes): 65160
After freeing result 2, we‘re using (in bytes): 65204
After query #3, we‘re using (in bytes): 65284
After freeing result 3, we‘re using (in bytes): 65328
After query #4, we‘re using (in bytes): 65408
After freeing result 4, we‘re using (in bytes): 65452
After query #5, we‘re using (in bytes): 65532
After freeing result 5, we‘re using (in bytes): 65576
After query #6, we‘re using (in bytes): 65656
After freeing result 6, we‘re using (in bytes): 65700
After query #7, we‘re using (in bytes): 65780
After freeing result 7, we‘re using (in bytes): 65824
After query #8, we‘re using (in bytes): 65904
After freeing result 8, we‘re using (in bytes): 65948
After query #9, we‘re using (in bytes): 66028
After freeing result 9, we‘re using (in bytes): 66072
After closing the connection, we‘re using (in bytes): 65108
Peak memory usage for the script (in bytes): 88748

我們所做的操作是發(fā)現(xiàn)了執(zhí)行腳本時(shí)出現(xiàn)的一些可疑操作,,然后調(diào)整腳本使其給我們提供一些可理解的反饋。我們?cè)俅芜\(yùn)行了腳本,,在每次迭代期間使用 memory_get_usage() 查看內(nèi)存使用量的變化,。根據(jù)分配的內(nèi)存值的增長(zhǎng)情況,暗示了我們用腳本在某個(gè)位置建立了一個(gè)漏洞,。由于 mysql_free_result() 函數(shù)不釋放內(nèi)存,,因此我們可以認(rèn)為 mysql_query() 并未正確分配內(nèi)存。





回頁首


結(jié)束語

PHP V5.2 版包括一些優(yōu)秀的新工具,,可以幫助您更好地洞察腳本的系統(tǒng)內(nèi)存分配情況,,以及重新全面控制內(nèi)存管理的精確調(diào)整。當(dāng)?shù)玫接行褂脮r(shí),,新內(nèi)存管理工具將支持您的調(diào)試工作,,從而重新獲得一些系統(tǒng)資源。



參考資料

學(xué)習(xí)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多