本文目录导读:

我来帮你了解 PHP 的预提取(预加载/预加载机制)。
PHP 预加载(Preloading)
PHP 8.0 引入了预加载(Preloading)功能,允许在服务器启动时预先加载 PHP 文件到内存中。
基本概念
// opcache.preload 配置文件 // 在 php.ini 中设置 opcache.preload=/path/to/preload.php opcache.preload_user=www-data // 可选,指定预加载的用户
创建预加载脚本
<?php
// preload.php - 预加载脚本
// 方法1:手动预加载类
require_once __DIR__ . '/src/Database.php';
require_once __DIR__ . '/src/User.php';
require_once __DIR__ . '/src/Logger.php';
// 方法2:自动扫描目录
function preloadDirectory($dir) {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
if ($file->getExtension() === 'php') {
require_once $file->getPathname();
}
}
}
preloadDirectory(__DIR__ . '/src');
预加载优化示例
<?php
// optimized_preload.php
class Preloader {
private array $classes = [];
private array $paths = [];
public function addPath(string $path): self {
$this->paths[] = $path;
return $this;
}
public function exclude(string $pattern): self {
// 排除不需要预加载的类
$this->excludes[] = $pattern;
return $this;
}
public function load(): void {
foreach ($this->paths as $path) {
$this->loadDirectory($path);
}
}
private function loadDirectory(string $dir): void {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
if ($file->getExtension() === 'php') {
require_once $file->getPathname();
}
}
}
}
// 使用预加载器
$preloader = new Preloader();
$preloader
->addPath(__DIR__ . '/vendor')
->addPath(__DIR__ . '/app')
->load();
PHP 7.4+ Opcache 预加载
; php.ini 配置 opcache.enable=1 opcache.memory_consumption=256 opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.revalidate_freq=2 opcache.fast_shutdown=1 opcache.enable_cli=1
性能监控与验证
<?php
// check_preload.php
// 检查预加载状态
echo "Opcache 状态:\n";
print_r(opcache_get_status());
// 检查特定类是否预加载
$class = 'App\\Services\\DatabaseService';
if (opcache_is_script_cached(__DIR__ . '/src/DatabaseService.php')) {
echo "类 {$class} 已缓存\n";
}
// 查看预加载统计
$status = opcache_get_status();
echo "预加载文件数量: " . count($status['scripts'] ?? []) . "\n";
echo "缓存命中率: " . ($status['opcache_statistics']['hits'] ?? 0) . "\n";
实战示例:Laravel 预加载配置
<?php
// config/preload.php
namespace App\Preload;
class LaravelPreloader {
public function __invoke(): void {
$this->preloadCore();
$this->preloadServices();
$this->preloadModels();
}
private function preloadCore(): void {
$files = [
base_path('vendor/laravel/framework/src/Illuminate/Support/Str.php'),
base_path('vendor/laravel/framework/src/Illuminate/Support/Collection.php'),
base_path('vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php'),
];
foreach ($files as $file) {
if (file_exists($file)) {
require_once $file;
}
}
}
private function preloadServices(): void {
$path = app_path('Services');
if (is_dir($path)) {
$files = glob($path . '/*.php');
foreach ($files as $file) {
require_once $file;
}
}
}
private function preloadModels(): void {
$path = app_path('Models');
if (is_dir($path)) {
$files = glob($path . '/*.php');
foreach ($files as $file) {
require_once $file;
}
}
}
}
// 在 index.php 或框架入口调用
(new \App\Preload\LaravelPreloader)();
注意事项
<?php
// preload_caution.php
/**
* 预加载注意事项:
*
* 1. 只加载稳定的、不常修改的类
* 2. 避免加载包含数据库连接的文件
* 3. 注意内存消耗
* 4. 开发环境不建议启用
* 5. 修改预加载文件后需要重启服务器
*/
class PreloadValidator {
public static function validate(string $file): bool {
// 检查文件大小
if (filesize($file) > 1024 * 1024) {
return false; // 超过1MB不预加载
}
// 检查文件内容
$content = file_get_contents($file);
// 排除包含数据库连接的文件
if (preg_match('/new\s+PDO|mysqli_connect|mysql_connect/', $content)) {
return false;
}
// 排除测试文件
if (strpos($file, '/tests/') !== false ||
strpos($file, '/Tests/') !== false) {
return false;
}
return true;
}
}
性能测试对比
<?php
// benchmark_preload.php
$startTime = microtime(true);
$startMemory = memory_get_usage();
// 测试预加载效果
for ($i = 0; $i < 1000; $i++) {
new SomeClass(); // 假设这是一个预加载的类
}
$endTime = microtime(true);
$endMemory = memory_get_usage();
echo "执行时间: " . ($endTime - $startTime) * 1000 . "ms\n";
echo "内存使用: " . ($endMemory - $startMemory) / 1024 . "KB\n";
最佳实践建议
- 生产环境使用:预加载主要用于生产环境
- 合理选择类:只预加载频繁使用的核心类
- 监控性能:使用
opcache_get_status()监控效果 - 重启策略:修改预加载文件后必须重启 PHP-FPM
这样可以显著提升框架应用(如 Laravel、Symfony)的性能,减少每次请求的文件加载开销。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播