C++ WonderTrader 源码分析之容器类
·
WTSCollection vs STL容器 - 核心优势分析
为什么不直接用STL容器?
1. 🔧 自动内存管理 - 核心优势
STL容器的问题:
// ❌ 传统STL方式 - 容易内存泄漏
std::vector<TradeData*> trades;
trades.push_back(new TradeData("AAPL", 150.0, 1000));
trades.push_back(new TradeData("MSFT", 280.0, 2000));
// 程序员必须记住手动清理,容易忘记
for(auto* trade : trades) {
delete trade; // 忘记这行 = 内存泄漏
}
// ❌ 使用shared_ptr - 与现有系统不兼容
std::vector<std::shared_ptr<TradeData>> trades;
// 问题:TradeData已经继承WTSObject,有自己的引用计数系统
// 现在有两套引用计数系统,容易混乱
WTSCollection的解决方案:
// ✅ WTSCollection - 自动管理
WTSArray* trades = WTSArray::create();
trades->append(new TradeData("AAPL", 150.0, 1000)); // 自动retain()
trades->append(new TradeData("MSFT", 280.0, 2000)); // 自动retain()
trades->release(); // 自动清理所有元素,调用每个元素的release()
2. 🎯 统一的对象生命周期管理
交易系统的特殊需求:
// 交易系统中,对象经常在多个地方被引用:
TradeData* trade = new TradeData("AAPL", 150.0, 1000);
// 同时被多个容器引用
orderBook->addTrade(trade); // 订单簿需要这个交易
riskManager->checkTrade(trade); // 风控模块需要检查
logger->logTrade(trade); // 日志模块需要记录
// 问题:谁负责删除这个对象?
WTSCollection的解决方案:
// ✅ 引用计数自动管理生命周期
TradeData* trade = new TradeData("AAPL", 150.0, 1000); // 引用计数=1
orderBook->addTrade(trade); // 内部调用retain(),引用计数=2
riskManager->checkTrade(trade); // 内部调用retain(),引用计数=3
logger->logTrade(trade); // 内部调用retain(),引用计数=4
// 当各模块不再需要时,自动调用release()
// 当引用计数降到0时,对象自动删除
3. ⚡ 性能优化 - 针对交易系统
标准容器的性能问题:
// shared_ptr的开销
std::vector<std::shared_ptr<TradeData>> trades;
// 还有额外的控制块开销
// 原子操作的开销
// 访问时的间接开销
auto trade = trades[0]; // 需要通过shared_ptr访问
double price = trade->getPrice(); // 额外的间接访问
WTSCollection的性能优势:
// 直接指针,更好的性能
WTSArray* trades = WTSArray::create();
TradeData* trade = trades->at<TradeData>(0); // 直接指针访问
double price = trade->getPrice(); // 无额外间接开销
// 自定义哈希表优化
WTSHashMap<std::string>* marketData = WTSHashMap<std::string>::create();
// 使用wt_hashmap,可能针对交易数据的访问模式优化了:
// - 哈希算法
// - 内存分配策略
// - 冲突解决方案
4. 🔒 线程安全的引用计数
STL容器的线程安全问题:
// ❌ 不是线程安全的
std::vector<TradeData*> trades;
// 线程1
trades.push_back(newTrade); // 不安全
// 线程2
TradeData* trade = trades[0]; // 可能崩溃
delete trade; // 其他线程可能还在使用
WTSCollection的线程安全:
// ✅ 引用计数是线程安全的
WTSArray* trades = WTSArray::create();
// 线程1
TradeData* trade = trades->grab<TradeData>(0); // 原子操作增加引用计数
// 使用trade...
trade->release(); // 原子操作减少引用计数
// 线程2
TradeData* sameTrade = trades->grab<TradeData>(0); // 安全获取
// 使用sameTrade...
sameTrade->release(); // 安全释放
5. 🎨 API一致性 - 降低学习成本
STL容器API不一致:
std::vector<int> vec;
std::map<string, int> map;
std::queue<int> queue;
vec.push_back(1); // 不同的添加方法
map["key"] = 1; // 不同的添加方法
queue.push(1); // 不同的添加方法
vec.size(); // 一致
map.size(); // 一致
queue.size(); // 一致
// 但是清理方式不同
vec.clear(); // 简单清理
map.clear(); // 简单清理
// queue没有clear()方法!
WTSCollection统一API:
// 统一的创建方式
WTSArray* array = WTSArray::create();
WTSMap<string>* map = WTSMap<string>::create();
WTSHashMap<string>* hashMap = WTSHashMap<string>::create();
WTSQueue* queue = WTSQueue::create();
// 统一的大小获取
array->size();
map->size();
hashMap->size();
queue->size();
// 统一的清理方式
array->release(); // 自动清理所有元素
map->release(); // 自动清理所有元素
hashMap->release(); // 自动清理所有元素
queue->release(); // 自动清理所有元素
6. 🏗️ 专门为交易系统设计
交易系统的特殊需求:
// 1. 大量小对象的频繁创建和销毁
// 2. 对象在多个模块间传递
// 3. 严格的内存管理要求
// 4. 高性能要求
// 5. 类型安全要求
WTSCollection的针对性设计:
// ✅ 专门优化
class WTSArray : public WTSObject // 容器本身也是WTSObject
{
std::atomic<bool> _holding; // 线程同步优化
// 针对交易数据优化的方法
void sort(SortFunc func); // 内置排序,常用于价格排序
uint32_t idxOf(WTSObject* obj); // 快速查找索引
// 两种访问模式
WTSObject* at(uint32_t idx); // 不增加引用,适合临时访问
WTSObject* grab(uint32_t idx); // 增加引用,适合长期持有
};
实际应用场景对比
场景1:实时行情处理
// ❌ STL方式 - 复杂且容易出错
std::unordered_map<std::string, std::shared_ptr<TickData>> marketData;
std::vector<std::shared_ptr<TickData>> tickHistory;
void onTick(const std::string& symbol, double price, int volume) {
auto tick = std::make_shared<TickData>(symbol, price, volume);
marketData[symbol] = tick; // 引用计数+1
tickHistory.push_back(tick); // 引用计数+1
// 需要手动管理历史数据大小
if(tickHistory.size() > 10000) {
tickHistory.erase(tickHistory.begin()); // 复杂的清理逻辑
}
}
// ✅ WTSCollection方式 - 简洁且安全
WTSHashMap<std::string>* marketData = WTSHashMap<std::string>::create();
WTSArray* tickHistory = WTSArray::create();
void onTick(const std::string& symbol, double price, int volume) {
TickData* tick = new TickData(symbol, price, volume);
marketData->add(symbol, tick); // 自动管理引用计数
tickHistory->append(tick); // 自动管理引用计数
// 简单的大小管理
if(tickHistory->size() > 10000) {
tickHistory->clear(); // 自动清理所有元素
}
}
场景2:订单管理
// ❌ STL方式 - 内存管理复杂
class OrderManager {
std::map<std::string, Order*> activeOrders;
std::queue<Order*> pendingOrders;
public:
~OrderManager() {
// 必须手动清理所有容器
for(auto& pair : activeOrders) {
delete pair.second;
}
while(!pendingOrders.empty()) {
delete pendingOrders.front();
pendingOrders.pop();
}
}
};
// ✅ WTSCollection方式 - 自动管理
class OrderManager {
WTSMap<std::string>* activeOrders;
WTSQueue* pendingOrders;
public:
OrderManager() {
activeOrders = WTSMap<std::string>::create();
pendingOrders = WTSQueue::create();
}
~OrderManager() {
activeOrders->release(); // 自动清理所有订单
pendingOrders->release(); // 自动清理所有订单
}
};
总结
WTSCollection不是为了重新发明轮子,而是为了解决交易系统中的特定问题:
- 自动内存管理 - 避免内存泄漏,减少程序员负担
- 统一对象生命周期 - 适配现有的WTSObject引用计数系统
- 性能优化 - 针对交易系统的访问模式优化
- 线程安全 - 引用计数的原子操作
- API一致性 - 降低学习和使用成本
- 类型安全 - 统一的WTSObject基类系统
这些优势在高频交易、实时风控、大量数据处理等场景下尤为重要,能显著提高代码质量和系统稳定性。
更多推荐



所有评论(0)