PHP指南:使用记忆化进行性能优化
可用语言 :
Sébastien TIMONER
作为 Web 开发和技术团队管理专家,我专注于创建和优化高性能数字解决方案。通过对 React.js、Node.js、TypeScript、Symfony 和 IoT 领域的 Zephyr OS 等现代技术的深入掌握,我确保在 offroadLabs 中为各行业企业的复杂 SaaS 和 IoT 项目从设计到生产的成功。
在 offroadLabs,我提供定制开发服务,结合技术专长和协作方法。无论是创建创新的 SaaS 解决方案、使用 Zephyr OS 开发 IoT 系统、现代化现有应用程序还是支持团队的专业成长,我都致力于提供稳健且高效的解决方案,适应每个项目的具体需求。
我可以在艾克斯普罗旺斯周边或完全远程工作。
记忆化是一种优化技术,它的核心是缓存函数调用的结果。与其多次重复计算相同的结果,我们将其存储在内存中以供后续使用。这种方法特别适用于:
让我们从一个简单且安全的实现开始:
php
php
php
php
php
php
PHP中的记忆化是一种强大的技术,可以大大提升应用程序的性能。这些实现提供了:
记忆化结合良好的缓存管理,能让您优化PHP应用程序,同时保持代码的整洁和可维护性!💪
1<?php
2
3/**
4 * 记忆化基础类
5 */
6class Memoizer
7{
8 private array $cache = [];
9 private array $timestamps = [];
10
11 /**
12 * 记忆化一个函数
13 *
14 * @param callable $fn 要记忆化的函数
15 * @return callable 记忆化后的函数
16 */
17 public function memoize(callable $fn): callable
18 {
19 return function (...$args) use ($fn) {
20 $key = $this->generateCacheKey($args);
21
22 if ($this->hasValidCacheEntry($key)) {
23 error_log("缓存命中,键值:$key");
24 return $this->cache[$key];
25 }
26
27 $result = $fn(...$args);
28 $this->cache[$key] = $result;
29 $this->timestamps[$key] = time();
30 error_log("新计算,键值:$key");
31
32 return $result;
33 };
34 }
35
36 /**
37 * 生成唯一的缓存键
38 */
39 private function generateCacheKey(array $args): string
40 {
41 return md5(serialize($args));
42 }
43
44 /**
45 * 检查缓存条目是否有效
46 */
47 private function hasValidCacheEntry(string $key): bool
48 {
49 return isset($this->cache[$key]);
50 }
51
52 /**
53 * 清空缓存
54 */
55 public function clearCache(): void
56 {
57 $this->cache = [];
58 $this->timestamps = [];
59 }
60}
1<?php
2
3/**
4 * 高级记忆化配置
5 */
6class MemoizeConfig
7{
8 public function __construct(
9 public readonly int $maxCacheSize = 1000,
10 public readonly int $ttl = PHP_INT_MAX,
11 public readonly ?callable $cacheKeyGenerator = null
12 ) {}
13}
14
15/**
16 * 缓存统计
17 */
18class CacheStats
19{
20 public function __construct(
21 public int $hits = 0,
22 public int $misses = 0,
23 public float $totalAccessTime = 0,
24 public int $accessCount = 0
25 ) {}
26
27 public function getAverageAccessTime(): float
28 {
29 return $this->accessCount > 0 ? $this->totalAccessTime / $this->accessCount : 0;
30 }
31}
32
33/**
34 * 高级记忆化实现,包含完整的缓存管理
35 */
36class AdvancedMemoizer
37{
38 private array $cache = [];
39 private array $timestamps = [];
40 private CacheStats $stats;
41
42 public function __construct(private readonly MemoizeConfig $config = new MemoizeConfig())
43 {
44 $this->stats = new CacheStats();
45 }
46
47 public function memoize(callable $fn): callable
48 {
49 return function (...$args) use ($fn) {
50 $startTime = microtime(true);
51 $key = $this->generateCacheKey($args);
52 $now = time();
53
54 if ($this->hasValidCacheEntry($key, $now)) {
55 $this->updateStats(true, $startTime);
56 return $this->cache[$key];
57 }
58
59 // 缓存大小管理
60 if (count($this->cache) >= $this->config->maxCacheSize) {
61 $this->removeOldestEntry();
62 }
63
64 $result = $fn(...$args);
65 $this->cache[$key] = $result;
66 $this->timestamps[$key] = $now;
67 $this->updateStats(false, $startTime);
68
69 return $result;
70 };
71 }
72
73 private function generateCacheKey(array $args): string
74 {
75 if ($this->config->cacheKeyGenerator) {
76 return ($this->config->cacheKeyGenerator)($args);
77 }
78 return md5(serialize($args));
79 }
80
81 private function hasValidCacheEntry(string $key, int $now): bool
82 {
83 return isset($this->cache[$key]) &&
84 ($now - $this->timestamps[$key] <= $this->config->ttl);
85 }
86
87 private function updateStats(bool $isHit, float $startTime): void
88 {
89 $accessTime = microtime(true) - $startTime;
90 $this->stats->totalAccessTime += $accessTime;
91 $this->stats->accessCount++;
92
93 if ($isHit) {
94 $this->stats->hits++;
95 } else {
96 $this->stats->misses++;
97 }
98 }
99
100 private function removeOldestEntry(): void
101 {
102 $oldestKey = array_key_first($this->timestamps);
103 unset($this->cache[$oldestKey], $this->timestamps[$oldestKey]);
104 }
105
106 public function getStats(): array
107 {
108 return [
109 'hits' => $this->stats->hits,
110 'misses' => $this->stats->misses,
111 'size' => count($this->cache),
112 'averageAccessTime' => $this->stats->getAverageAccessTime()
113 ];
114 }
115
116 public function clearCache(): void
117 {
118 $this->cache = [];
119 $this->timestamps = [];
120 }
121}
1<?php
2
3$memoizer = new Memoizer();
4$fibonacci = $memoizer->memoize(function (int $n) use (&$fibonacci): int {
5 if ($n <= 1) return $n;
6 return $fibonacci($n - 1) + $fibonacci($n - 2);
7});
8
9// 使用示例
10echo $fibonacci(30); // 使用记忆化后运行速度大大提升
1<?php
2
3class UserAPI
4{
5 private AdvancedMemoizer $memoizer;
6
7 public function __construct()
8 {
9 $this->memoizer = new AdvancedMemoizer(new MemoizeConfig(
10 maxCacheSize: 100,
11 ttl: 300, // 5分钟
12 cacheKeyGenerator: fn($args) => $args[0] // 使用ID作为键
13 ));
14 }
15
16 public function fetchUser(string $userId): array
17 {
18 $fetchUserData = $this->memoizer->memoize(function (string $userId) {
19 $response = file_get_contents("https://api.example.com/users/{$userId}");
20 if ($response === false) {
21 throw new RuntimeException("获取用户数据失败");
22 }
23 return json_decode($response, true);
24 });
25
26 return $fetchUserData($userId);
27 }
28}
1<?php
2
3class DataTransformer
4{
5 private AdvancedMemoizer $memoizer;
6
7 public function __construct()
8 {
9 $this->memoizer = new AdvancedMemoizer(new MemoizeConfig(
10 cacheKeyGenerator: function($args) {
11 [$data, $options] = $args;
12 return md5(json_encode($data) . '-' . $options['format'] . '-' . $options['version']);
13 }
14 ));
15 }
16
17 public function transform(array $data, array $options): string
18 {
19 $transformData = $this->memoizer->memoize(function (array $data, array $options) {
20 // 复杂的转换逻辑...
21 return json_encode($data);
22 });
23
24 return $transformData($data, $options);
25 }
26}
1<?php
2
3/**
4 * 性能监控包装器
5 */
6class PerformanceMonitor
7{
8 private int $calls = 0;
9 private float $totalTime = 0;
10 private int $cacheHits = 0;
11
12 public function wrap(callable $fn): callable
13 {
14 return function (...$args) use ($fn) {
15 $start = microtime(true);
16 $result = $fn(...$args);
17 $this->totalTime += microtime(true) - $start;
18 $this->calls++;
19
20 return $result;
21 };
22 }
23
24 public function getMetrics(): array
25 {
26 return [
27 'totalCalls' => $this->calls,
28 'averageExecutionTime' => $this->calls > 0 ? $this->totalTime / $this->calls : 0,
29 'cacheEfficiency' => $this->calls > 0 ? $this->cacheHits / $this->calls : 0
30 ];
31 }
32}