PHP `array_walk`、`array_map` 和 `foreach` 性能测试比较
在 PHP 中,array_walk、array_map 和 foreach 是常用的数组处理方法。它们在性能和用法上有一些不同。下面我们将对这三种方法进行性能测试比较。
1. 方法概述
1.1 array_walk
array_walk 用于对数组中的每个元素应用用户自定义的回调函数。它对原数组进行操作,且不返回新数组。
array_walk($array, 'callback_function');
1.2 array_map
array_map 用于对数组中的每个元素应用用户自定义的回调函数,并返回一个新数组。
$newArray = array_map('callback_function', $array);
1.3 foreach
foreach 是一种语言结构,用于遍历数组的每个元素。您可以在循环中直接修改数组或执行操作。
foreach ($array as $value) {
// 操作
}
2. 性能测试
我们将使用一个简单的性能测试来比较这三种方法。测试的内容是将一个大数组中的每个元素进行简单的加倍操作。
2.1 测试代码
<?php
function double($value) {
return $value * 2;
}
$array = range(1, 100000); // 创建一个包含100000个整数的数组
// array_walk
$start = microtime(true);
array_walk($array, function(&$value) {
$value = double($value);
});
$time_walk = microtime(true) - $start;
// array_map
$start = microtime(true);
$newArrayMap = array_map('double', $array);
$time_map = microtime(true) - $start;
// foreach
$start = microtime(true);
foreach ($array as &$value) {
$value = double($value);
}
$time_foreach = microtime(true) - $start;
// 显示结果
echo "array_walk took: {$time_walk} seconds\n";
echo "array_map took: {$time_map} seconds\n";
echo "foreach took: {$time_foreach} seconds\n";
?>
2.2 运行测试
将上述代码保存为 performance_test.php 并在命令行中运行:
php performance_test.php
3. 性能结果分析
根据测试结果,您将看到每种方法所用的时间。以下是可能的结果分析:
foreach 通常是最快的,因为它是语言结构,开销最小。array_map 通常速度较快,但会创建一个新数组,可能会消耗更多内存。array_walk 可能会稍慢,因为它涉及到回调函数的调用,并且没有返回新数组。
4. 结论
- 如果您需要返回新数组,使用
array_map。 - 如果您只需要对原数组进行操作,
foreach 是最佳选择。 array_walk 用于更复杂的操作,但通常性能不如 foreach。
在 Linux 中将 PHP-FPM 配置成 Service
在 Linux 系统中,您可以将 PHP-FPM 配置为服务,以便更方便地管理其启动、停止和重启。以下是在常见的 Linux 发行版(如 CentOS 和 Ubuntu)中配置 PHP-FPM 为服务的步骤。
1. 安装 PHP-FPM
首先,确保您已安装 PHP-FPM。根据您的 Linux 发行版,您可以使用以下命令进行安装。
CentOS
sudo yum install php-fpm
Ubuntu
sudo apt update
sudo apt install php-fpm
2. 配置 PHP-FPM
在安装完成后,您需要配置 PHP-FPM。编辑配置文件,通常位于 /etc/php-fpm.d/www.conf 或 /etc/php/7.x/fpm/pool.d/www.conf(具体路径可能因 PHP 版本和发行版而异)。
sudo nano /etc/php-fpm.d/www.conf # CentOS
或
sudo nano /etc/php/7.x/fpm/pool.d/www.conf # Ubuntu
确保以下配置项设置正确:
listen = 127.0.0.1:9000 # 配置 PHP-FPM 监听的地址和端口
3. 创建 Systemd 服务文件
CentOS / Ubuntu
您可以创建一个 Systemd 服务文件来管理 PHP-FPM。通常,该文件位于 /etc/systemd/system/。
sudo nano /etc/systemd/system/php-fpm.service
在文件中添加以下内容:
[Unit]
Description=The PHP 7.x FastCGI Process Manager
After=network.target
[Service]
Type=simple
PIDFile=/run/php/php7.x-fpm.pid # 根据您的 PHP 版本修改
ExecStart=/usr/sbin/php-fpm7.x --nodaemonize # 根据您的 PHP 版本修改
ExecReload=/bin/kill -USR2 $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
注意事项
- 确保
ExecStart 中的 PHP-FPM 路径和版本号正确。 - 对于 PHP 7.4,通常是
php-fpm7.4;对于 PHP 8.0,则是 php-fpm8.0。
4. 重新加载 Systemd
创建或修改服务文件后,您需要重新加载 Systemd,以便它识别新服务。
sudo systemctl daemon-reload
5. 启动 PHP-FPM 服务
使用以下命令启动 PHP-FPM 服务:
sudo systemctl start php-fpm
6. 设置开机自启
如果您希望 PHP-FPM 在系统启动时自动启动,可以使用以下命令:
sudo systemctl enable php-fpm
7. 管理 PHP-FPM 服务
您可以使用以下命令管理 PHP-FPM 服务:
检查状态:
sudo systemctl status php-fpm
停止服务:
sudo systemctl stop php-fpm
重启服务:
sudo systemctl restart php-fpm
重新加载配置:
sudo systemctl reload php-fpm
8. 配置防火墙(可选)
如果您使用的是防火墙(如 firewalld 或 ufw),确保允许 PHP-FPM 的监听端口(默认是 9000)。
CentOS(firewalld)
sudo firewall-cmd --add-port=9000/tcp --permanent
sudo firewall-cmd --reload
Ubuntu (ufw)
sudo ufw allow 9000/tcp
PHP Kafka 初体验
Apache Kafka 是一个分布式流处理平台,广泛用于构建实时数据管道和流应用。以下是使用 PHP 操作 Kafka 的基本步骤和示例,帮助您快速上手。
1. 环境准备
1.1 安装 Kafka
首先,您需要在本地或服务器上安装 Kafka。可以从 Kafka 官方网站 下载并解压 Kafka。
1.2 启动 Kafka 和 Zookeeper
Kafka 依赖 Zookeeper,因此需要先启动 Zookeeper:
bin/zookeeper-server-start.sh config/zookeeper.properties
然后启动 Kafka 服务器:
bin/kafka-server-start.sh config/server.properties
1.3 安装 PHP 扩展
为了在 PHP 中使用 Kafka,您可以使用 php-rdkafka 扩展。您可以通过 PECL 安装:
sudo pecl install rdkafka
确保在 php.ini 文件中添加以下行:
extension=rdkafka.so
2. 创建 Kafka 主题
在使用 Kafka 之前,您需要创建一个主题。可以使用以下命令创建一个名为 test 的主题:
bin/kafka-topics.sh --create --topic test --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1
3. PHP 生产者示例
下面是一个简单的 PHP 生产者示例,用于发送消息到 Kafka 主题:
<?php
$conf = new RdKafka\Conf();
$conf->set('metadata.broker.list', 'localhost:9092'); // 设置 broker 地址
$producer = new RdKafka\Producer($conf);
$topic = $producer->newTopic("test");
for ($i = 0; $i < 10; $i++) {
$message = "Message $i";
$topic->produce(RD_KAFKA_PARTITION_UA, 0, $message);
echo "Sent: $message\n";
}
$producer->flush(10000); // 确保消息发送
?>
4. PHP 消费者示例
下面是一个简单的 PHP 消费者示例,用于从 Kafka 主题中接收消息:
<?php
$conf = new RdKafka\Conf();
$conf->set('metadata.broker.list', 'localhost:9092'); // 设置 broker 地址
$consumer = new RdKafka\Consumer($conf);
$consumer->addBrokers("localhost:9092");
$topic = $consumer->newTopic("test");
$topic->consumeStart(0, RD_KAFKA_OFFSET_END); // 从最新位置开始消费
while (true) {
$message = $topic->consume(0, 1000); // 等待消息
if ($message->err) {
if ($message->err == RD_KAFKA_RESP_ERR__TIMED_OUT) {
continue;
}
echo "Consumer error: {$message->err}\n";
break;
}
echo "Received: {$message->payload}\n";
}
?>
5. 运行示例
运行生产者:在一个终端中运行生产者脚本:
php producer.php
运行消费者:在另一个终端中运行消费者脚本:
php consumer.php
您应该能够看到生产者发送的消息被消费者接收。
PHP异常处理中的黑科技
PHP异常处理中的黑科技
前面提到框架中是可以捕获所有的错误和异常的,之所以能实现应该是使用了黑科技,哈哈!其实也不是什么黑科技,主要是三个重要的函数:
1. set_error_handler()
看到这个名字估计就知道什么意思了,这个函数用于捕获错误,设置一个用户自定义的错误处理函数。
当程序出现错误的时候自动调用此方法,不过需要注意一下两点:
第一,如果存在该方法,相应的error_reporting()就不能在使用了。所有的错误都会交给自定义的函数处理。
第二,此方法不能处理以下级别的错误:E_ERROR、E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,set_error_handler() 函数所在文件中产生的E_STRICT,该函数只能捕获系统产生的一些Warning、Notice级别的错误。
并且他有多种调用的方法:
2. register_shutdown_function()
捕获PHP的错误:Fatal Error、Parse Error等,这个方法是PHP脚本执行结束前最后一个调用的函数,比如脚本错误、die()、exit、异常、正常结束都会调用,多么牛逼的一个函数啊!
通过这个函数就可以在脚本结束前判断这次执行是否有错误产生,这时就要借助于一个函数:error_get_last();
这个函数可以拿到本次执行产生的所有错误。error_get_last();
返回的信息:
- [type] - 错误类型
- [message] - 错误消息
- [file] - 发生错误所在的文件
- [line] - 发生错误所在的行
3:set_exception_handler()
设置默认的异常处理程序,用在没有用try/catch块来捕获的异常,也就是说不管你抛出的异常有没有人捕获,如果没有人捕获就会进入到该方法中,并且在回调函数调用后异常会中止。
php.ini 中display_errors = Off 失效的解决
php.ini 中 display_errors = Off 失效的解决
问题: PHP设置文件php.ini中明明已经设置display_errors = Off,但是在运行过程中,网页上还是会出现错误信息。
解决: log_errors= On,据官方的说法,当这个log_errors设置为On,那么必须指定error_log文件,如果没指定或者指定的文件没有权限写入,那么照样会输 出到正常的输出渠道,那么也就使得display_errors 这个指定的Off失效,错误信息还是打印了出来。
于是将 log_errors = Off,问题就解决了。