build-ipa/ironSource/PlayBTopOn/SERIAL_VS_PARALLEL.md
2026-01-05 10:40:05 +08:00

5.3 KiB
Raw Blame History

串行加载 vs 并行加载对比

📊 旧逻辑(并行加载)

时间轴:
0s    ┌──────┐
      │loadAd│ 启动
      └──┬───┘
         ├─────────┐
1s       │ 加载 A  │
         ├─────────┤
2s       │ 加载 B  │ (同时进行)
         ├─────────┤
3s       │ 加载 C  │
         └─────────┘
4s    ┌──────┐
      │start │ 启动定时器
      └──┬───┘
         │
5s       ├→ 检查是否有可展示的广告
6s       ├→ 检查
7s       ├→ 检查
8s       ├→ 检查(找到 Aecpm 满足)
         ├→ 展示 A ✓
         
问题:
❌ 浪费B 和 C 也加载了但可能用不上
❌ 等待4-8秒才检查到可以展示
❌ 频率限制3个广告同时请求

🎯 新逻辑(串行加载)

时间轴:
0s    ┌──────┐
      │loadAd│ 启动
      └──┬───┘
         │
0.5s     ├─────────┐
         │ 加载 A  │
         └─────────┘
1.5s     ↓ 成功ecpm 满足
         ├→ 立即展示 A ✓
         
优势:
✓ 节省:只加载了 A
✓ 快速1.5秒就展示
✓ 成功率高:单个请求不触发频率限制

如果 A 失败的情况:
0.5s     ├─────────┐
         │ 加载 A  │
         └─────────┘
1.5s     ↓ 失败 ✗
1.6s     ├─────────┐
         │ 加载 B  │
         └─────────┘
2.6s     ↓ 成功!
         ├→ 立即展示 B ✓

📈 性能对比

指标 旧逻辑 新逻辑 改进
最快展示时间 ~8秒 ~1.5秒 5倍提速
平均流量消耗 3个广告 1-2个广告 节省50%+
SDK请求次数 3次 1-3次 按需请求
CPU占用 定时器持续轮询 事件驱动 更低
成功率 受频率限制影响 避免频率限制 更高

🔄 真实场景模拟

场景A: 第一个就成功(最常见)

旧逻辑:

0s:  加载 A、B、C同时
5s:  A完成(✓), B完成(✓), C完成(✓)
8s:  定时器检查 → 展示A
总耗时: 8秒
浪费: B和C的流量

新逻辑:

0s:  加载 A
1.5s: A完成(✓) → 立即展示A
总耗时: 1.5秒
浪费: 0

场景B: 第一个失败,第二个成功

旧逻辑:

0s:  加载 A、B、C同时
5s:  A失败(✗), B完成(✓), C完成(✓)
8s:  定时器检查 → 跳过A → 展示B
总耗时: 8秒
浪费: C的流量

新逻辑:

0s:  加载 A
1.5s: A失败(✗) → 立即加载B
3s:  B完成(✓) → 立即展示B
总耗时: 3秒
浪费: 0

场景C: ecpm不足需要多个

旧逻辑:

0s:  加载 A、B、C同时
5s:  A(ecpm低), B(ecpm低), C(ecpm高)
8s:  定时器检查 → 跳过A,B → 展示C
总耗时: 8秒

新逻辑:

0s:  加载 A
1.5s: A完成但ecpm低 → 立即加载B
3s:  B完成但ecpm低 → 立即加载C
4.5s: C完成ecpm高 → 立即展示C
总耗时: 4.5秒

💰 成本节省每天10000次展示

流量成本

旧逻辑:

每次展示加载: 3个广告
每个广告请求: ~50KB
每天: 10000 × 3 × 50KB = 1.43GB

新逻辑:

成功率80%平均1.2个广告
每天: 10000 × 1.2 × 50KB = 0.57GB
节省: 0.86GB (60%)

SDK请求配额

很多 SDK 有每日请求限制,新逻辑可以:

  • 减少请求次数
  • 延长配额使用时间
  • 避免触发频率限制

📱 用户体验对比

用户场景 旧逻辑 新逻辑
打开应用到看到广告 8-10秒 1.5-3秒
等待时的体验 长时间空白 快速响应
流量消耗感知 高(后台偷跑流量) 低(按需加载)
应用流畅度 卡顿同时3个请求 流畅(单个请求)

🎯 最佳实践建议

1. 广告位优先级排序

// 按 ecpm 历史数据排序
var adids = config.allAdIds.sorted { 
    getHistoryEcpm($0) > getHistoryEcpm($1) 
}

2. 添加超时机制

// 单个广告加载超时
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
    if self.isLoadingAd && self.currentLoadingAdId == adId {
        self.loadNextAd() // 超时,加载下一个
    }
}

3. 智能重试

// 网络错误可以重试,其他错误跳过
if error.code == .networkError {
    retry(adId)
} else {
    loadNextAd()
}

迁移检查清单

  • 修改 add(adId:) 方法,不立即加载
  • 添加队列管理逻辑
  • 实现 loadNextAd() 方法
  • 实现 autoShowLoadedAd() 方法
  • 修改状态回调处理
  • 移除定时器依赖
  • 保持 API 兼容性
  • 添加详细日志
  • 测试各种场景

🚀 预期结果

重新编译运行后,你会看到:

✅ 日志更清晰:
   "开始加载广告 [1/3]: A"
   "开始加载广告 [2/3]: B"
   
✅ 展示更快速:
   1-3秒内展示vs 之前的8秒
   
✅ 流量更节省:
   平均只加载1.2个广告vs 之前的3个
   
✅ 成功率更高:
   避免频率限制,自动尝试下一个

总结: 新的串行加载逻辑在速度、成本、成功率上都有显著提升!🎉