资源可以长期驻留,不只是在所有引用它的变量超出作用域之后,甚至是在一个请求结束并且新的请求产生之后 。这些资源称为持久资源,因为它们贯通 SAPI的整个生命周期持续存在,除非特意销毁 。很多情况下,持久化资源可以在一定程度上提高性能 。比如我们常见的mysql_pconnect ,持久化资源通过pemalloc分配内存,这样在请求结束的时候不会释放 。对zend来说,对两者本身并不区分 。
4-3 . PHP变量管理——引用计数和写时拷贝:
引用计数在内存回收、字符串操作等地方使用非常广泛 。Zval的引用计数通过成员变量is_ref和ref_count实现,通过引用计数,多个变量可以共享同一份数据 。避免频繁拷贝带来的大量消耗 。在进行赋值操作时,zend将变量指向相同的zval同时ref_count++,在unset操作时,对应的ref_count-1 。只有ref_count减为0时才会真正执行销毁操作 。如果是引用赋值,则zend会修改is_ref为1 。
【PHP底层运行机制与原理】PHP变量通过引用计数实现变量共享数据,那如果改变其中一个变量值呢?当试图写入一个变量时,Zend若发现该变量指向的zval被多个变量共享,则为其复制一份ref_count为1的zval,并递减原zval的refcount,这个过程称为“zval分离” 。可见,只有在有写操作发生时 zend才进行拷贝操作,因此也叫copy-on-write(写时拷贝)
对于引用型变量,其要求和非引用型相反,引用赋值的变量间必须是捆绑的,修改一个变量就修改了所有捆绑变量 。
4-4 . PHP局部变量和全局变量的实现:
PHP中的局部变量和全局变量是如何实现的?对于一个请求,任意时刻PHP都可以看到两个符号表(symbol_table和 active_symbol_table),其中前者用来维护全局变量 。后者是一个指针,指向当前活动的变量符号表,当程序进入到某个函数中时,zend 就会为它分配一个符号表x同时将active_symbol_table指向a 。通过这样的方式实现全局、局部变量的区分 。
获取变量值:PHP的符号表是通过hash_table实现的,对于每个变量都分配唯一标识,获取的时候根据标识从表中找到相应zval返回 。
函数中使用全局变量:在函数中,我们可以通过显式申明global来使用全局变量 。在active_symbol_table中创建symbol_table中同名变量的引用(引用变量的值要更新大家会一起更新),如果symbol_table中没有同名变量则会先创建 。
推荐阅读
- php反射机制用法详解
- PHP实现站内信
- PHP五十个提升执行效率的小技巧,和常见问题
- PHP导出百万条数据方法
- PHP的TS和NTS有何区别,PHP在各环境下的伪静态是如何配置的
- 用PHP做SSL 证书到期时间检测,单文件 附源码
- 开发中php安全性考虑哪些
- PHP脚本占用内存太多,解决方案
- php7和php5区别
- centos7系统源码编译安装PHP7.3.5版本