我有一个项目,它从套接字接收数据,然后处理它并将良好的数据保存到容器中。
我想要高性能,所以,我需要尽可能减少复制操作。
这是我的第一个代码:struct Data { // here is a demo, in real project, Data is a large struct
int a;
char b[20];
}; // data type
std::vector<const Data*> data_base;
void Handle(const Data& a) {
if (a.good()) { // only few data will get good
data_base.emplace_back(&a); // data_map saved pointer to avoid copy
}
}
int main() {
while(true) {
Data* a = new Data;// here waste memory, since only few data need to be saved
socket.Recv(*a);
Handle(*a);
}
}
在这段代码中,我保存了data的指针,因此,复制成本被节省了。
但是问题是Inew
有很多对象,这会占用很多内存。
我有这样的第二个设计:
struct Data {
int a;
char b[20];
}; // data type
std::vector<const Data*> data_base;
void Handle(const Data& a) {
if (a.good()) { // only few data will get good
// TODO: copy a's value to a permanent pointer, i don't know how to do that
}
}
int main() {
Data a;
while(true) {
socket.Recv(a); // make a reusable
Handle(*a);
}
}
我认为第二种解决方案可以节省内存,并且不会损害性能。(没有额外的副本),我说的对吗?
如何将临时变量复制到指针容器中(参见解决方案2中的TODO)?
不要这样做。
这样做:
struct Data {
int a;
char b[20];
}; // data type
std::vector<Data> data_base;
void Handle(const Data& a) {
if (a.good()) { // only few data will get good
data_base.push_back(a);
}
}
int main() {
Data a;
while(true) {
socket.Recv(a);
Handle(a);
}
}
复制您的Data
结构体似乎是相当微不足道的,在任何情况下,您都声明它只会很少发生。所以正确的做法是针对一般情况进行优化。重用接收数据的空间,只在需要时才复制。
// TODO: copy a's value to a permant pointer, i dont know how to do that
你可以这么做,只要:
data_base.push_back(new Data(a))
但是你的代码泄漏内存。使用智能指针:
std::vector<std::unique_ptr<Data>> data_base;
无论如何,我相信这样做的目的不是复制数据,而是只在需要时复制指针。无论如何都要使用智能指针。我相信一些东西:
struct Data { int tmp; bool good(); };
std::vector<std::unique_ptr<Data>> data_base;
void socket_recv(std::unique_ptr<A>& a);
void handle(std::unique_ptr<Data>& a) {
if (a->good()) { // only few data will get good
data_base.emplace_back(std::move(a)); // we move the pointer around
a = std::make_unique<Data>(); // allocate new memory for next run
}
}
int main() {
std::unique_ptr<Data> a = std::make_unique<Data>();
while(true) {
socket_recv(a); // make a reusable
handle(a);
}
}
或使用原始指针:
std::vector<Data *> data_base;
void socket_recv(Data* a);
void handle(Data*& a) {
if (a->good()) { // only few data will get good
data_base.push_back(a); // we move the pointer around
a = new Data(); // allocate new memory for next run
}
}
int main() {
A *a = new Data();
while(true) {
socket_recv(a); // make a reusable
handle(a);
}
delete a;
}