使用PHP计算价格不同排列组合并生成JSON文件的资源占用优化问题
解决方案
你遇到的性能瓶颈本质是附加项的所有子集和数量随附加项数量指数级增长:n个附加项对应2^n种组合,n=20时组合数就超过100万,n=25更是达到3300万,常规全量预存所有组合的方案必然会触发内存溢出和超时问题,可按以下逻辑重构代码:
1. 核心优化思路
放弃全量预计算存储所有组合的模式,改用流式生成+流式输出的逻辑,全程不需要持有全量数据在内存中,仅保留当前计算需要的少量中间值。
2. 用生成器迭代输出子集和
使用PHP生成器(Generator)实现子集和的迭代生成,不需要把所有组合存到数组里,生成一个组合就处理一个:
function generateSumIterator(int $basePrice, array $addons): Generator { // 先输出不选任何附加项的基础价格 yield $basePrice; $currentSums = [$basePrice]; // 迭代附加项生成所有组合和 foreach ($addons as $addon) { $temp = []; foreach ($currentSums as $existingSum) { $newSum = $existingSum + $addon; yield $newSum; $temp[] = $newSum; } $currentSums = array_merge($currentSums, $temp); } }
3. 实时计算乘数结果并流式写入JSON
生成子集和后直接遍历乘数计算所有结果,即时写入流式JSON编码器,不存储任何中间结果:
// 配置项 $basePrice = 50; $addons = [5, 10, 15]; // 你的附加项数组 $multipliers = [1, 3, 6, 12]; // CLI模式下可加这两行避免执行超时,内存限制设为128M完全足够 set_time_limit(0); ini_set('memory_limit', '128M'); // 流式写入JSON $encoder = new \Violet\StreamingJsonEncoder\BufferJsonEncoder(); $encoder->startArray(); foreach (generateSumIterator($basePrice, $addons) as $sum) { foreach ($multipliers as $m) { $encoder->write($sum * $m); } } $encoder->endArray(); file_put_contents('prices.json', $encoder->getString());
4. 额外优化建议
- 先对附加项数组去重,相同价格的附加项不需要重复计算组合
- 生成子集和的过程中可增加去重逻辑,避免重复计算相同的和,多数场景下可减少30%以上的无效计算
- 如果附加项数量超过20,建议脚本仅在CLI模式下运行,不要通过Web请求触发
内容的提问来源于stack exchange,提问作者Tyssen
相关产品推荐
相关产品推荐

