2009-10-23 87 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方法中添加一些代码即可。

相关问题