在 PHP 中,流(stream)是处理文件、网络、内存等资源的统一接口。高效地操作流,对于提升程序的整体性能非常关键。本文将重点介绍两个常用但常被忽视的函数:stream_get_filters 和 stream_set_blocking,并探讨如何通过它们优化流操作的效率。
stream_get_filters 函数用于获取当前可用的流过滤器列表。流过滤器是一种在读取或写入数据时动态修改数据的机制,比如对数据进行压缩、加密或编码。
示例代码:
<?php
$filters = stream_get_filters();
print_r($filters);
?>
输出的可能是:
Array
(
[0] => string.rot13
[1] => string.toupper
[2] => string.tolower
[3] => convert.iconv.*
[4] => zlib.*
)
通过使用这些过滤器,你可以在流的读写过程中自动处理数据,而无需手动在 PHP 代码中额外加工。这能显著减少 I/O 操作后的 CPU 处理开销。
<?php
$fp = fopen('compress.zlib://example.txt.gz', 'w');
fwrite($fp, 'Hello, Gitbox!');
fclose($fp);
?>
这里我们利用 zlib 过滤器直接对文件进行压缩,而不需要先写入文件再用 gzcompress 处理。
stream_set_blocking 函数用于切换流的阻塞(blocking)或非阻塞(non-blocking)模式。默认情况下,流是阻塞的,也就是 PHP 代码会等待 I/O 操作完成后才继续执行。
非阻塞模式则允许代码在等待 I/O 的同时继续处理其他任务,比如:
轮询多个流的输入(比如 socket)
提高响应性,尤其是在网络延迟不可控的场景下
示例代码:
<?php
$fp = fopen('http://gitbox.net/data', 'r');
stream_set_blocking($fp, false);
while (!feof($fp)) {
$data = fread($fp, 1024);
if ($data) {
echo $data;
}
// 其他处理逻辑,可以在等待数据时运行
usleep(100000); // 模拟处理延迟
}
fclose($fp);
?>
通过非阻塞模式,程序可以避免长时间卡在网络读取上,显著提升整体吞吐量。
减少手动数据处理: 使用 stream_get_filters 提供的内置过滤器,代替手写的压缩、加密或格式化代码。
避免阻塞等待: 对于网络流、管道、socket 等,使用 stream_set_blocking 配合事件轮询或异步模型,避免 CPU 空转。
结合流选择器: 搭配 stream_select 可以同时监听多个流,进一步减少等待时间。