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

235 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 串行加载 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. 广告位优先级排序
```swift
// 按 ecpm 历史数据排序
var adids = config.allAdIds.sorted {
getHistoryEcpm($0) > getHistoryEcpm($1)
}
```
### 2. 添加超时机制
```swift
// 单个广告加载超时
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
if self.isLoadingAd && self.currentLoadingAdId == adId {
self.loadNextAd() // 超时,加载下一个
}
}
```
### 3. 智能重试
```swift
// 网络错误可以重试,其他错误跳过
if error.code == .networkError {
retry(adId)
} else {
loadNextAd()
}
```
## ✅ 迁移检查清单
- [x] 修改 `add(adId:)` 方法,不立即加载
- [x] 添加队列管理逻辑
- [x] 实现 `loadNextAd()` 方法
- [x] 实现 `autoShowLoadedAd()` 方法
- [x] 修改状态回调处理
- [x] 移除定时器依赖
- [x] 保持 API 兼容性
- [x] 添加详细日志
- [x] 测试各种场景
## 🚀 预期结果
重新编译运行后,你会看到:
```
✅ 日志更清晰:
"开始加载广告 [1/3]: A"
"开始加载广告 [2/3]: B"
✅ 展示更快速:
1-3秒内展示vs 之前的8秒
✅ 流量更节省:
平均只加载1.2个广告vs 之前的3个
✅ 成功率更高:
避免频率限制,自动尝试下一个
```
---
**总结:** 新的串行加载逻辑在速度、成本、成功率上都有显著提升!🎉