一个很小的细节,但容易忽略, 给用的人也提示一下!
之前使用protobuf 一直没有注意针对repeated 字段的内存管理是,每次add时都很有可能会 new 一次新空间,然后把旧空间的数据 copy 到新空间,最后把旧空间delete;这个操作就像 STL 里vector 的push_back 一样, 空间不够了, 就会自动增长, 而性能就消耗在自动增长了.
后来发现, 对于使用repeated 描述的字段, 就像vector 一样,提供了一个预分配的方法:Reserve. 当你的repeated 描述的字段将要存储很多个元素, 这个字段所在的对象又频繁的构造析构, 而且每个元素都不小的时候, 使用Reserve预分配, 提高的效率是不可估量的!
template <typename TypeHandler>
inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add() {
if (current_size_ < allocated_size_) {
return cast<TypeHandler>(elements_[current_size_++]);
}
if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
++allocated_size_;
typename TypeHandler::Type* result = TypeHandler::New();
elements_[current_size_++] = result;
return result;
}
void RepeatedPtrFieldBase::Reserve(int new_size) {
if (total_size_ >= new_size) return;
void** old_elements = elements_;
total_size_ = max(total_size_ * 2, new_size);
elements_ = new void*[total_size_];
memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
if (old_elements != initial_space_) {
delete [] old_elements;
}
}