性能优化

最后更新: 2026-01-27 11:02:47

性能优化

本文档提供了 Unicode Framework 性能优化的最佳实践和建议。

路由优化

路由缓存

在生产环境中启用路由缓存:

<h1 id="设置环境变量">设置环境变量</h1>
APP_ENV=production

<h1 id="框架会自动缓存路由">框架会自动缓存路由</h1> <h1 id="缓存文件bootstrapcacheroutesphp">缓存文件:bootstrap/cache/routes.php</h1>

路由组织

// ✅ 推荐:将常用路由放在前面
Route::get('/api/users', [UserController::class, 'index']);  // 常用路由
Route::get('/api/users/{id}', [UserController::class, 'show']);
Route::get('/api/admin/settings', [AdminController::class, 'settings']);  // 不常用路由

// ❌ 错误:不常用路由在前 Route::get('/api/admin/settings', [AdminController::class, 'settings']); Route::get('/api/users', [UserController::class, 'index']);

数据库优化

查询优化

// ✅ 推荐:只查询需要的字段
$users = db('users')
    ->select(['id', 'name', 'email'])
    ->get();

// ❌ 错误:查询所有字段 $users = db('users')->get();

避免 N+1 查询

// ❌ 错误:N+1 查询
$users = User::all();
foreach ($users as $user) {
    $posts = $user->posts;  // 每次循环都查询数据库
}

// ✅ 推荐:预加载关联 $users = User::with('posts')->get(); foreach ($users as $user) { $posts = $user->posts; // 已预加载,不查询数据库 }

使用索引

// ✅ 推荐:在迁移中创建索引
public function up(): void
{
    $this->schema()->table('users', function($table) {
        $table->index('email');
        $table->index(['status', 'created_at']);
    });
}

查询缓存

// ✅ 推荐:缓存查询结果
$cacheKey = 'users:active';
$users = $cache->get($cacheKey, function() {
    return db('users')->where('status', 'active')->get();
}, 3600);

分页

// ✅ 推荐:使用分页
$users = db('users')
    ->offset(0)
    ->limit(20)
    ->get();

// ❌ 错误:一次性加载所有数据 $users = db('users')->get(); // 如果数据量大,会消耗大量内存

缓存优化

缓存策略

// ✅ 推荐:根据数据更新频率设置缓存时间
$cache->set('config:app', $config, 86400);  // 配置:24小时
$cache->set('user:1', $user, 3600);  // 用户数据:1小时
$cache->set('stats:daily', $stats, 3600);  // 统计数据:1小时

标签缓存

// ✅ 推荐:使用标签缓存批量清除
$taggedCache = new TaggedCache($cache, ['users']);
$taggedCache->set('user:1', $user1, 3600);
$taggedCache->set('user:2', $user2, 3600);

// 用户数据更新时,清除所有用户相关缓存 $taggedCache->flush();

缓存预热

// ✅ 推荐:应用启动时预热缓存
public function warmUpCache(): void
{
    // 预热配置
    $config = db('config')->get();
    $cache->set('config:all', $config, 86400);

// 预热热门数据 $hotUsers = db('users') ->where('status', 'active') ->orderBy('views', 'desc') ->limit(100) ->get();

foreach ($hotUsers as $user) { $cache->set("user:{$user['id']}", $user, 3600); } }

视图优化

模板缓存

// ✅ 推荐:在生产环境启用模板缓存
// config/view.php
return [
    'engines' => [
        'smarty' => [
            'caching' => true,
            'cache_lifetime' => 3600,
        ],
    ],
];

视图编译

// ✅ 推荐:预编译模板
// 在部署时编译所有模板
php console view:compile

减少视图数据

// ✅ 推荐:只传递必要的数据
return view('user/profile', [
    'user' => [
        'id' => $user->id,
        'name' => $user->name,
        'email' => $user->email,
    ],
]);

// ❌ 错误:传递过多数据 return view('user/profile', [ 'user' => $user, // 可能包含不需要的数据 ]);

代码优化

延迟加载

// ✅ 推荐:使用延迟加载
$container->singleton('heavy-service', function($container) {
    return new HeavyService();
}, deferred: true);  // 延迟加载

// ❌ 错误:立即加载 $container->singleton('heavy-service', function($container) { return new HeavyService(); }, deferred: false); // 立即加载,影响启动速度

避免重复计算

// ❌ 错误:重复计算
foreach ($users as $user) {
    $count = db('orders')->where('user_id', $user->id)->count();  // 每次都查询
}

// ✅ 推荐:批量查询 $userIds = array_column($users, 'id'); $counts = db('orders') ->select('user_id', db()->raw('COUNT(*) as count')) ->whereIn('user_id', $userIds) ->groupBy('user_id') ->get() ->keyBy('user_id');

使用批量操作

// ❌ 错误:循环插入
foreach ($users as $user) {
    db('users')->insert($user);
}

// ✅ 推荐:批量插入 db('users')->insert($users);

服务器优化

OPcache

; php.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0  ; 生产环境

数据库连接池

// ✅ 推荐:使用连接池
// 配置数据库连接池大小
return [
    'database' => [
        'connections' => [
            'mysql' => [
                'pool_size' => 10,  // 连接池大小
            ],
        ],
    ],
];

HTTP 缓存

// ✅ 推荐:设置 HTTP 缓存头
$response = Response::json($data);
$response = $response->withHeader('Cache-Control', 'public, max-age=3600');
$response = $response->withHeader('ETag', md5(json_encode($data)));
return $response;

Gzip 压缩

// ✅ 推荐:启用 Gzip 压缩
// 在 Web 服务器配置中启用
// Nginx
gzip on;
gzip_types text/plain text/css application/json application/javascript;

监控和调试

性能监控

// ✅ 推荐:记录慢查询
$startTime = microtime(true);

// 执行操作 $users = db('users')->get();

$duration = microtime(true) - $startTime; if ($duration > 1.0) { Log::warning('Slow query detected', [ 'duration' => $duration, 'query' => 'users::all', ]); }

内存使用

// ✅ 推荐:监控内存使用
$memoryBefore = memory_get_usage();

// 执行操作 processLargeDataset();

$memoryAfter = memory_get_usage(); $memoryUsed = $memoryAfter - $memoryBefore;

if ($memoryUsed > 100 1024 1024) { // 100MB Log::warning('High memory usage', [ 'memory_used' => $memoryUsed, ]); }

最佳实践总结

1. 生产环境配置

<h1 id="env">.env</h1>
APP_ENV=production
APP_DEBUG=false

<h1 id="启用路由缓存">启用路由缓存</h1> <h1 id="启用模板缓存">启用模板缓存</h1> <h1 id="启用-opcache">启用 OPcache</h1>

2. 数据库优化

  • 使用索引
  • 避免 N+1 查询
  • 使用分页
  • 缓存查询结果
  • 3. 缓存策略

  • 合理设置缓存时间
  • 使用标签缓存
  • 缓存预热
  • 4. 代码优化

  • 延迟加载
  • 批量操作
  • 避免重复计算
  • 5. 服务器优化

  • 启用 OPcache
  • 使用连接池
  • HTTP 缓存
  • Gzip 压缩
  • 常见问题

    Q: 如何测量性能?

    A: 使用性能分析工具(如 Xdebug、Blackfire)或添加性能监控代码。

    Q: 路由缓存何时更新?

    A: 删除 bootstrap/cache/routes.php 文件,框架会在下次请求时重新生成。

    Q: 如何优化数据库查询?

    A: 使用索引、避免 N+1 查询、使用分页、缓存查询结果。

    Q: 缓存应该设置多长时间?

    A: 根据数据更新频率设置,配置数据可以设置较长时间,用户数据设置较短时间。

    Q: 如何减少内存使用?

    A: 使用分页、及时释放变量、避免加载大量数据到内存。

    相关文档

  • 缓存系统 - 缓存使用
  • 数据库优化 - 数据库最佳实践
  • 路由系统 - 路由优化