PHP7 的高性能来自于哪些改进

  • 变量容器 zval 结构体定义改变,减少内存占用,减少引用计数相关操作。
  • zend_string。字符串复制的时候,采用引用赋值,zend_string可以避免的内存拷贝。
  • zend_array。数组的value默认为zval。
    HashTable的大小从72下降到56字节,减少22%。
    Buckets的大小从72下降到32字节,减少50%。
    数组元素的Buckets的内存空间是一同分配的。
    数组元素的key(Bucket.key)指向zend_string。
    数组元素的value被嵌入到Bucket中。
    降低CPU Cache Miss。
  • 改进函数调用机制。
  • 通过宏定义和内联函数(inline),让编译器提前完成部分工作

参考链接:

  1. http://www.csdn.net/article/2015-09-16/2825720
  2. PHP’s new hashtable implementation
  3. Internal value representation in PHP 7 – Part 2

MyISAM 和 InnoDB 存储引擎区别及各自使用场景

InnoDB 主要优势

  • 事务支持:事务提交回滚以及错误恢复。
  • 行级锁
  • 聚合索引
  • 外键支持

InnoDB 在 MySQL 5.6.4 后支持全文索引。

MySQL 5.5 后默认存储引擎为InnoDb。

如果不能使用到索引,行级锁会失效。

如何选择两种存储引擎

大量读,几乎没有写请求 和 小于5.6.4版本需要全文索引,选择 MyISAM,其他情况选择InnoDB。

我的性能测试结果,仅供参考

CREATE TABLE `engine_t1` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

单进程插入10万条记录,MyISAM 1.8348009586334 秒, InnoDB 2.0098528862 秒

6个进程同时各插入10万条记录,MyISAM 3.860533952713 秒, InnoDB 2.9386329650879 秒(每个进程运行时间差不多,文章中给出的是其中一进程的运行时间,下同)

12个进程同时各插入10万条记录,MyISAM 7.4965870380402 秒, InnoDB 5.0007991790771 秒

CREATE TABLE `wp_posts_1` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `post_author` bigint(20) unsigned NOT NULL DEFAULT '0',
  `post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_date_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_content` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `post_title` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `post_excerpt` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `post_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'publish',
  `comment_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open',
  `ping_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open',
  `post_password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  `post_name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  `to_ping` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `pinged` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_modified_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_content_filtered` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `post_parent` bigint(20) unsigned NOT NULL DEFAULT '0',
  `guid` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  `menu_order` int(11) NOT NULL DEFAULT '0',
  `post_type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'post',
  `post_mime_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  `comment_count` bigint(20) NOT NULL DEFAULT '0',
  PRIMARY KEY (`ID`),
  KEY `post_name` (`post_name`(191)),
  KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
  KEY `post_parent` (`post_parent`),
  KEY `post_author` (`post_author`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

单进程插入1万条记录,MyISAM 4.3874440193176 秒, InnoDB 3.8677229881287 秒

6个进程同时各插入1万条记录,MyISAM 9.7532279491425 秒, InnoDB 6.4886889457703 秒(平均每个进程运行时间)

12个进程同时各插入1万条记录,MyISAM 22.401536941528 秒, InnoDB 8.3166329860687 秒(平均每个进程运行时间)

12个进程同时主键SELECT1万次,MyISAM 3.3773090839386 秒, InnoDB 3.3466641902924 秒(平均每个进程运行时间)

30个进程同时主键SELECT1万次,MyISAM 8.7141139507294 秒, InnoDB 8.6588280200958 秒(平均每个进程运行时间)

总结:从这个测试结果来看,InnoDB几乎是完胜啊。(结果仅供参考,或许完全没有参考价值,毕竟与真实业务中的查询情况相差巨大)

PHP内存回收原理

每个php变量存在一个叫”zval”的变量容器中。除了包含变量的类型和值,还包括两个字节的额外信息。is_ref 是个bool值,用来标识这个变量是否是属于引用集合(reference set),refcount 用以表示指向这个zval变量容器的变量(也称符号即symbol)个数

refcount 为0时变量从内存中删除。在5.3之前的版本无法处理循环引用的问题。5.3及以后, 在引入新的垃圾回收算法来对付循环引用计数的时候, 作者加入了大量的宏来操作refcount, 为了能让错误更快的显现, 所以改名为refcount__gc, 迫使大家都使用宏来操作refcount。

一个zval在5.3之前版本占用24字节(64位系统,下同),5.3为了解决循环引用的问题,用zval_gc_info劫持了zval的分配,因此5.3到5.6,一个zval实际占用32字节。

从PHP7开始, 对于在zval的value字段中能保存下的值, 就不再对他们进行引用计数了, 而是在拷贝的时候直接赋值, 这样就省掉了大量的引用计数相关的操作, 这部分类型有:IS_LONG、IS_DOUBLE,对于那种根本没有值, 只有类型的类型, 也不需要引用计数了:IS_NULL、IS_FALSE、IS_TRUE。

PHP7的性能,我们并没有引入什么新的技术模式, 不过就是主要来自, 持续不懈的降低内存占用, 提高缓存友好性, 降低执行的指令数的这些原则而来的。

PHP5(v<5.3) zval 结构体定义:

struct _zval_struct {
    union {
        long lval;					/* long value */
        double dval;				/* double value */
        struct {
            char *val;
            int len;
        } str;
        HashTable *ht;				/* hash table value */
        zend_object_value obj;
    } value;
    unsigned int refcount;
    unsigned char type;
    unsigned char is_ref;
};

PHP5(5.3<= v < 7) zval 结构体定义:

struct _zval_struct {
    union {
        long lval;					/* long value */
        double dval;				/* double value */
        struct {
            char *val;
            int len;
        } str;
        HashTable *ht;				/* hash table value */
        zend_object_value obj;
    } value;
    unsigned int refcount__gc;
    unsigned char type;
    unsigned char is_ref__gc;
};

5.3及以上版本虽然 struct  _zval_struct 结构体的内容没有变(除了 refcount 重命名为 refcount__gc,is_ref 重命名为 is_ref__gc),但是新增的头文件 zend_gc.h 重定义了 ALLOC_ZVAL 宏

#undef  ALLOC_ZVAL
#define ALLOC_ZVAL(z) 									\
	do {												\
		(z) = (zval*)emalloc(sizeof(zval_gc_info));		\
		GC_ZVAL_INIT(z);								\
	} while (0)

zval_gc_info 的定义为

typedef struct _zval_gc_info {
	zval z;
	union {
		gc_root_buffer       *buffered;
		struct _zval_gc_info *next;
	} u;
} zval_gc_info;

所以实际上5.3及以上版本zval大小为32字节。

PHP7 zval 结构体定义如下

struct _zval_struct {
    union {
        zend_long lval;                /* long value */
        double dval;                /* double value */
        zend_refcounted *counted;
        zend_string *str;
        zend_array *arr;
        zend_object *obj;
        zend_resource *res;
        zend_reference *ref;
        zend_ast_ref *ast;
        zval *zv;
        void *ptr;
        zend_class_entry *ce;
        zend_function *func;
        struct {
            uint32_t w1;
            uint32_t w2;
        } ww;
    } value;            /* value */
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                    zend_uchar type,            /* active type */
                    zend_uchar type_flags,
                    zend_uchar const_flags,
                    zend_uchar reserved)        /* call info for EX(This) */
        } v;
        uint32_t type_info;
    } u1;
    union {
        uint32_t var_flags;
        uint32_t next;                 /* hash collision chain */
        uint32_t cache_slot;           /* literal cache slot */
        uint32_t lineno;               /* line number (for ast nodes) */
        uint32_t num_args;             /* arguments number for EX(This) */
        uint32_t fe_pos;               /* foreach position */
        uint32_t fe_iter_idx;          /* foreach iterator index */
    } u2;
};

 

关于内存对齐请参考:https://levphy.github.io/2017/03/23/memory-alignment.html

PhpStorm 激活服务器 PhpStorm License Server

下面给出的激活服务器可以激活 JetBrains 系列的所有产品,包括但不限于:PhpStorm AppCode CLion IDEA PyCharm RubyMine WebStorm

http://jetbrains.tencent.click
http://idea.lanyus.com
http://idea.qinxi1992.cn

http://idea.imsxm.com/
http://114.215.133.70:41017/
http://172.245.22.235:1017/
http://mcpmcc.com:1017
http://idea.pjoc.pub

http://idea.goxz.gq/
http://v2mc.net:1017/
http://idea.imsxm.com/
http://idea.ibdyr.com/

作者:伍源辉
链接:http://www.jianshu.com/p/8c49c41603ab
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

线上服务故障紧急处理

1 确认服务器状态(CPU,MEM)
    1.1 MySQL 负载高?
        1.1.1 找出当前执行超过10秒的查询,如有异常,结合最近的发布情况,确定是否新发布代码引起,如果是,回滚代码。
            select * from information_schema.processlist where time>10 and Command!='sleep' order by time;
    1.2 FPM 负载高?
        1.2.1 查看当前访问的URL,是否同一时刻执行了大量耗时请求
            curl 'http://127.0.0.1:10068/fpm_status?full'|grep 'request URI'|awk '{print $3}'|sort|uniq -c
2 确认nginx状态码
    2.1 出现大量500
        2.1.1 Redis MySQL sphinx 等服务运行状态正常?
            2.1.1.1 不正常,重启对应服务
        2.1.2 如最近有发布,回滚代码
    2.2 出现大量502
        2.2.1 确认FPM进程状态,重启 fpm,nginx
            sudo service php-fpm restart
            sudo kill `ps -ef|grep fpm|awk '{print $2}'|xargs`
            sudo service php-fpm start
            sudo service nginx restart
    2.3 出现大量503
        2.3.1 nginx 连接 fpm 超时?
            tail -100000 /logs/user/access_liebiao.log | grep ' 503 ' | awk '{if($NF>=1 && $NF <2){print}}'
            重启 fpm
        2.3.2 SQL执行超时?
            tail -100000 /logs/user/access_liebiao.log | awk '{if($NF>=30){print}}'

 

原版windows xp安装镜像与密钥(包含sp3)

Windows XP Professional(Simplified Chinese)

文件名      CN_WINXP_PRO_ISO.img
SHA1        73800FE8959F40361BAE3A6553CC66D27D78722E
文件大小 505.63MB
发布时间 2001-10-30

ed2k://|file|CN_WINXP_PRO_ISO.img|530186240|7855069CE4216615D761654E2B75A4F7|/
BX6HT-MDJKW-H2J4X-BX67W-TVVFG

Windows XP Professional with Service Pack 3 (x86) – CD VL (Chinese-Simplified)

文件名     zh-hans_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-74070.iso
SHA1       D142469D0C3953D8E4A6A490A58052EF52837F0F
文件大小 601.04MB
发布时间 2008-05-02

ed2k://|file|zh-hans_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-74070.iso|630237184|EC51916C9D9B8B931195EE0D6EE9B40E|/
MRX3F-47B9T-2487J-KWKMF-RPWBY

以上亲测可用!

一次 ping 不通问题排查

线上一台服务器在重启后发现,有些机器无法 ping 通,有些机器可以。

机器情况如下:

host_a 192.168.1.111 192.168.11.1 x.x.x.x
host_b 192.168.1.112
host_c y.y.y.y 192.168.11.2
其中,host_a 和 host_b 在同一个局域网中 192.168.1.0/24,host_a 上运行着 openvpn server,host_c 运行着 openvpn client。

问题表现为在 c 机器上,ping b 的 ip,无法 ping 通,tcpdump 在 b 上抓包,有接收到 ping request 包,没有 ping reply 包。

正当我要按 stackoverflow 上的一个答案配置打开 log_martians 这个选项时,想到会不会是 b 的路由表配置问题,运行 ip route 查看路由发现果然。

ip route add 192.168.11.0/24 via 192.168.1.111

上述命令添加路由后问题解决。

 

参考:

  1. http://stackoverflow.com/questions/18536796/icmp-request-received-but-doesnt-reply
  2. https://www.cyberciti.biz/faq/linux-log-suspicious-martian-packets-un-routable-source-addresses/
  3. https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/s1-networkscripts-static-routes.html