You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP按200KB固定内存大小拆分数组为最少块数

实现数组按序列化大小拆分的最优方案

要实现将大数组拆分为数量最少的子数组块(每个块序列化后不超过200KB),核心思路是让每个子数组尽可能接近内存上限,具体实现步骤如下:

关键思路

  1. 先将内存限制转换为字节单位:200KB = 204800 字节
  2. 先估算单个元素的序列化平均大小,快速得到每个块的初始元素数量,避免逐次试探的低效
  3. 对初始数量进行动态调整,找到当前范围内能容纳的最大元素数,确保序列化后不超过限制
  4. 循环拆分原数组,直到所有元素都被分配到子块中

代码实现

// 定义内存上限:200KB 转字节
define('MAX_SERIALIZED_SIZE', 200 * 1024);

$profileIds = range(1, 8000); // 示例数组
$chunks = [];
$totalElements = count($profileIds);
$currentIndex = 0;

// 先估算单个元素的平均序列化大小(取前10个元素计算)
$sample = array_slice($profileIds, 0, min(10, $totalElements));
$sampleSize = mb_strlen(serialize($sample), '8bit');
$avgElementSize = $sampleSize / count($sample);

// 计算初始的每个块元素数量(留出一定冗余,避免直接踩上限)
$initialChunkSize = floor(MAX_SERIALIZED_SIZE / $avgElementSize) - 1;
$initialChunkSize = max(1, $initialChunkSize); // 确保至少1个元素

while ($currentIndex < $totalElements) {
    // 尝试当前最大可能的元素数
    $remainingElements = $totalElements - $currentIndex;
    $chunkSize = min($initialChunkSize, $remainingElements);
    
    // 调整chunkSize,确保序列化后不超过限制
    while (true) {
        $currentChunk = array_slice($profileIds, $currentIndex, $chunkSize);
        $currentSize = mb_strlen(serialize($currentChunk), '8bit');
        
        if ($currentSize <= MAX_SERIALIZED_SIZE) {
            // 尝试能否再添加元素(如果还有剩余)
            if ($chunkSize < $remainingElements) {
                $testChunk = array_slice($profileIds, $currentIndex, $chunkSize + 1);
                $testSize = mb_strlen(serialize($testChunk), '8bit');
                if ($testSize <= MAX_SERIALIZED_SIZE) {
                    $chunkSize++;
                    continue;
                }
            }
            break;
        } else {
            // 超过限制,减少元素数
            $chunkSize--;
            if ($chunkSize === 0) {
                // 极端情况:单个元素就超过限制,这里可以抛出异常或单独处理
                throw new Exception("单个元素序列化后超过内存上限");
            }
        }
    }
    
    // 将符合条件的块加入结果
    $chunks[] = array_slice($profileIds, $currentIndex, $chunkSize);
    $currentIndex += $chunkSize;
    
    // 更新初始chunkSize为当前找到的最大值,优化后续循环
    $initialChunkSize = $chunkSize;
}

// 输出结果验证
foreach ($chunks as $i => $chunk) {
    echo "块 " . ($i+1) . " 元素数:" . count($chunk) . ",序列化大小:" . mb_strlen(serialize($chunk), '8bit') . "字节\n";
}

代码说明

  • 初始估算:通过前10个元素计算平均大小,快速得到初始块大小,避免从1开始逐个试探的低效
  • 动态调整:先验证初始块大小,若超过上限则减少,若还有剩余空间则尝试增加元素,确保每个块都用到最大允许的内存
  • 极端情况处理:如果单个元素序列化后就超过200KB,会抛出异常,你可以根据实际需求修改这部分逻辑(比如单独存储该元素)
  • 效率优化:每次找到合适的块大小后,将其作为下一次的初始值,减少后续的调整次数

内容的提问来源于stack exchange,提问作者Md. Zayed Hassan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 22:20:28