2009-10-23 101 views
1

我正在寫一個將消息寫入文件的日誌工具,我不確定處理文件指針的最佳方法。我折騰了這兩種方法:在PHP中打開文件句柄的開銷成本?

// Open, Write, Close; Open, Write, Close... 
function write($message) { 
    $fh = fopen('file.log', 'a'); 
    fwrite($fh, $message . "\n"); 
    fclose($fh); 
} 

// OR ----- 

// Open, Write, Write, Write..., Close 
function __construct() { 
    $this->fh = fopen('file.log', 'a'); 
} 
function __destruct() { 
    fclose($this->fh); 
} 
function write($message) { 
    fwrite($fh, $message . "\n"); 
} 

我想象,這個類將被加載並在每一頁上建造,但不一定使用,但它最有可能會。

是否存在任何方法的性能,安全性或其他缺陷,以及您會推薦哪種方法?

+0

爲什麼不直接使用Apache日誌? error_log()等 – cletus 2009-10-23 01:51:34

+1

好,你是一個很好的觀點,但問題仍然存在? – nickf 2009-10-23 01:53:43

回答

2

我不能給你一個數字,但打開一個文件只是關閉並重復打開它會花費你的東西。我在操作系統層面上談論,不僅僅是PHP。調用內核open()(或CreateFile(),如果您說Windows),將路徑字符串與文件系統中的實體匹配,從磁盤讀取目錄結構,然後再關閉句柄的另一個系統調用......特別是如果您有大量I會避免做太多這一切。或者進行一些測量,看看是否可以。

如果您擔心會導致永遠不會使用的產品的成本,您是否考慮過這兩種方法的混合?也就是說,如果文件尚未打開,請執行寫入操作,否則重新使用舊的句柄...

+0

你的意思是單身。 – lemon 2009-10-23 01:54:44

+4

「你說西紅柿....」我知道模式,但我不是那些喜歡用術語來描述技術的人。 :-) – asveikau 2009-10-23 02:04:10

1

取決於您記錄的內容。

真的第二個版本是最好的。可以這樣想:

您希望記錄在請求的週期內發生的錯誤。假設您在請求期間收到3個錯誤。如果您使用第一種方法打開和關閉文件3次,這會導致更多的開銷。如果您使用的是記錄器類的相同實例,則只需打開一次該文件,並在請求期間向其寫入3行。

希望這可以爲你解決問題。

(可選)您可以將文件指針傳遞給第一個方法,並且只讓該方法執行寫入操作。

1

下面是另一個版本:

function log($message) { 
    global $_log; 
    if (!defined(LOG_OPEN)) { 
    define(LOG_OPEN, true); 
    $_log = fopen('filename.log', 'w'); 
    register_shutdown_function('close_log'); 
    } 
    fwrite($_log, $message . "\n"); 
} 

function close_log() { 
    global $_log; 
    fclose($_log); 
} 

至少這樣當你寫一個消息,你只打開日誌。

這會花費你一些東西。在網絡延遲成本的大計劃中,除非你開始打開大量文件,否則我懷疑它會很重要。我懷疑這個日誌甚至可以衡量其效果。

+1

這看起來不錯。我會考慮使用一個靜態變量而不是全局來幫助封裝,儘管關閉函數使用一個額外的參數調用日誌來關閉文件 – 2009-10-23 08:02:54

1

第二種方法顯然更好,IMO。打開和關閉文件句柄確實有成本,雖然它相對較小,但如果在應用程序中執行此操作,它的確會增加很多(但如果這是一件非常罕見的事情,它不會產生任何影響我不認爲)。如果您需要添加一些額外的安裝或清理功能,第二種方法將是最乾淨的,因爲您只需在__construct/__destruct方法中添加一些代碼即可。

相關問題