Press "Enter" to skip to content

Serialize/Unserialize破坏单例

我们经常采用如下方式定义单列:

class Singleton {
    private static $instance = NULL;
    /** 不容许直接调用构造函数 */
    private function __construct() {
    }
    /** 不容许深度复制 */
    private function __clone() {
    }
    public static function getInstance() {
        if (NULL === self::$instance) {
        	self::$instance = new self();
		}
        return self::$instance;
    }
}

很多人都会记得对深度copy的保护, 但, 其实我们却疏忽了一点...

Filed in PHP应用, 随笔
with 15 Comments

深入理解PHP内存管理之谁动了我的内存

首先让我们看一个问题: 如下代码的输出,

var_dump(memory_get_usage());
$a = "laruence";
var_dump(memory_get_usage());
unset($a);
var_dump(memory_get_usage());

输出(在我的个人电脑上, 可能会因为系统,PHP版本,载入的扩展不同而不同):

int(90440)
int(90640)
int(90472)

注意到 90472-90440=32, 于是就有了各种的结论, 有的人说PHP的unset并不真正释放内存, 有的说, PHP的unset只是在释放大变量(大量字符串, 大数组)的时候才会真正free内存, 更有人说, 在PHP层面讨论内存是没有意义的.
那么, 到底unset会不会释放内存? 这32个字节跑哪里去了?

Filed in PHP应用, PHP源码分析
with 46 Comments

加速PHP的ECHO

你也许注意到过, 在PHP中使用ECHO输出大段字符串的时候, 执行时间会明显的长, 也就会有朋友认为PHP的ECHO性能很差.
我在之前的文章中, 已经解释过了原因, 也希望能纠正"PHP的ECHO性能差"的这个误会.
然而之前的文章, 也仅仅是给出了原因, 并没有介绍如何避免这个问题, 在今天公司内的某个产品线(Apache with PHP)发现了一个问题, 有用户在短时间内大量发起下载请求, 导致http连接数和数据库连接数剧增,
而数据库连接数剧增的原因是因为数据库的连接是单列模式, 一直到请求处理结束, 才会释放数据库链接. 这样就有了一个问题, 如果请求处理时间过长, 就会造成大量的数据库链接存在.
而这个用户的网速很慢,, 下载时间很长~, 这也就意味着, ECHO的"性能"很差~
这也就引出了今天我要谈的这个问题, 如何让ECHO变快, 让PHP的请求处理过程, 尽快结束...

Filed in PHP应用, PHP源码分析
with 36 Comments

深入理解PHP内存管理之一个低概率Core的分析

一个同事forward过来一个, 公司某产品线遇到的一个低概率, 但长时间出现了几次的Core的bt信息, 找我帮忙分析下原因.
bt栈如下(路径信息以*代替):

#0  0x00000000004a75e5 in _zend_mm_alloc_int (heap=0xd61260, size=79)
at /*/php-5.2.6/Zend/zend_alloc.c:1879
#1  0x000000000048d3cd in vspprintf (pbuf=0x7fbffe9cd8, max_len=1024, format=Variable "format" is not available.
)
    at /*/php-5.2.6/main/spprintf.c:224
#2  0x0000000000489747 in php_error_cb (type=1, error_filename=0x2a9a787ee8 "/*/application/helpers/util.php",
    error_lineno=1149, format=Variable "format" is not available.
) at /*/php-5.2.6/main/main.c:799
#3  0x000000000061db35 in soap_error_handler (error_num=1,
    error_filename=0x2a9a787ee8 "/*/application/helpers/util.php", error_lineno=1149,
    format=0x7b9cb8 "Maximum execution time of %d second%s exceeded", args=0x7fbffea3b0)
    at /*/php-5.2.6/ext/soap/soap.c:2178
#4  0x00000000004c2576 in zend_error (type=1, format=0x7b9cb8 "Maximum execution time of %d second%s exceeded")
    at /*/php-5.2.6/Zend/zend.c:976
#5  <signal handler called>
#6  0x00000000004a720f in _zend_mm_free_int (heap=0xd61260, p=Variable "p" is not available.
) at /*/php-5.2.6/Zend/zend_alloc.c:844
...以下省略

Filed in PHP应用, PHP源码分析
with 12 Comments

Expect:100-continue

在使用curl做POST的时候, 当要POST的数据大于1024字节的时候, curl并不会直接就发起POST请求, 而是会分为俩步,

  1. 发送一个请求, 包含一个Expect:100-continue, 询问Server使用愿意接受数据
  2. 接收到Server返回的100-continue应答以后, 才把数据POST给Server
  

Filed in PHP应用, 随笔
with 20 Comments

Compilation failed: support for \P, \p, and \X has not been compiled

首先感谢DiaHosting给我赞助了一个免费的VPS.
今天我终于把blog(WordPress)迁移到了新的VPS上, 由于环境的不一致(原来是Apache+mod_php, 现在是lighttpd+php_cgi), 中间出现不少问题, 但都没啥可说的.
一直到遇到如下这个问题:

Compilation failed: support for \P, \p, and \X has not been compiled
at offset 16 in /***/search-everything.php on line 802

Filed in PHP应用
with 7 Comments

如何获取一个变量的名字

比如, 我提供一个查询服务, 用户可以提交一个人的名字和年龄做为查询条件.
假设我要查询一个名字叫做"laruence", 年龄是27的人, 我认为这个人的定义的查询token可以写做:

   laruence=27

不幸的是, 当这样的一个token做为query string提交给服务器的处理脚本的时候, 你就会发现, 诶,,我不知道用户名是什么,,,
那么能否在PHP中获取到一个变量的名字呢?

Filed in PHP应用, PHP源码分析
with 20 Comments

Mpass - PHP做Socket服务的解决方案

一般很少有用PHP做服务的, 但是如果你的已有业务逻辑都是PHP实现的, 而现在却需要基于已有的业务逻辑提供一套Socket服务, 怎么办?
当然, 解决方法很多, 但最简单的办法, 还是直接使用PHP做Socket服务.
而这样做要解决的问题有很多, 主要要解决的问题有如下几个:

1. 作为后台服务,需要常驻后台运行, 那么丁点的内存泄露都是不能接受的.
2. 作为后台服务,畸形数据导致进程异常退出, 也是不可接受的.
3. 作为后台服务, 要能做到graceful restart.
4. 作为后台服务, 对资源的使用必须在可接受的范围以内.

最近,我就基于PHP写一个简单的提供Socket服务的框架. 取其名为Mpass(Multi-Processes Socket Server).

Filed in PHP应用
with 31 Comments

PHP stream未能及时清理现场导致Core的bug

同事发现一个在使用set_error_handler的时候, 能100%重现的core, 提炼后的重现代码如下(环境必须不能访问internet):

<?php
function err_handler(){
    exit;
    return true;
}
set_error_handler('err_handler');
$client = file_get_contents("http://www.laruence.com/ServiceNoWse.asmx?WSDL");

这段代码, 放在webServer中, 第一次访问不会有事, 第二第三次的时候就会出core.

Filed in PHP源码分析
with 12 Comments