局部变量和全局变量

本文最后更新于:2023年12月5日 晚上

局部变量

在事件回调函数返回后,所有局部对象和变量会全部回收,不需要 unset 。如果变量是一个资源类型,那么对应的资源也会被 PHP 底层释放。

function test()
{
    $a = new Object;
    $b = fopen('/data/t.log', 'r+');
    $c = new swoole_client(SWOOLE_SYNC);
    $d = new swoole_client(SWOOLE_SYNC);
    global $e;
    $e['client'] = $d;
}

$a, $b, $c 都是局部变量,当此函数 return 时,这 3 个变量会立即释放,对应的内存会立即释放,打开的 IO 资源文件句柄会立即关闭。 $d 也是局部变量,但是 return 前将它保存到了全局变量 $e,所以不会释放。当执行 unset($e['client']) 时,并且没有任何其他 PHP 变量仍然在引用 $d 变量,那么 $d 就会被释放。

全局变量

PHP 中,有 3 类全局变量。

  • 使用 global 关键词声明的变量
  • 使用 static 关键词声明的类静态变量、函数静态变量
  • PHP 的超全局变量,包括 $_GET、$_POST、$GLOBALS

全局变量和对象,类静态变量,保存在 swoole_server 对象上的变量不会被释放。需要程序员自行处理这些变量和对象的销毁工作。

class Test
{
    static $array = array();
    static $string = '';
}

function onReceive($serv, $fd, $reactorId, $data)
{
    Test::$array[] = $fd;
    Test::$string .= $data;
}
  • 在事件回调函数中需要特别注意非局部变量的 array 类型值,某些操作如 TestClass::$array[] = "string" 可能会造成内存泄漏,严重时可能发生爆内存,必要时应当注意清理大数组。
  • 在事件回调函数中,非局部变量的字符串进行拼接操作是必须小心内存泄漏,如 TestClass::$string .= $data,可能会有内存泄漏,严重时可能发生爆内存。

解决方法

  • 同步阻塞并且请求响应式无状态的 Server 程序可以设置 max_request,当 Worker进程/Task进程 结束运行时或达到任务上限后进程自动退出。该进程的所有变量/对象/资源均会被释放回收。
  • 程序内在 onClose 或设置定时器及时使用 unset 清理变量,回收资源

内存管理部分参照了 Swoole 官方文档。


局部变量和全局变量
http://blog.lujinkai.cn/PHP/EasySwoole/局部变量和全局变量/
作者
像方便面一样的男子
发布于
2022年1月25日
更新于
2023年12月5日
许可协议