我必须将大量数据读入:
vector<char>
第三方库会多次读取此数据。在每个回合中,它调用我的回调函数,其签名如下:
CallbackFun ( int CBMsgFileItemID,
unsigned long CBtag,
void* CBuserInfo,
int CBdataSize,
void* CBdataBuffer,
int CBisFirst,
int CBisLast )
{
...
}
目前我已经使用STL容器实现了一个缓冲容器,其中提供了我的方法insert()
和getBuff
来插入新缓冲区并获取存储缓冲区。但我仍然希望更好地执行代码,以便最小化分配和取消分配:
template<typename T1>
class buffContainer
{
private:
class atomBuff
{
private:
atomBuff(const atomBuff& arObj);
atomBuff operator=(const atomBuff& arObj);
public:
int len;
char *buffPtr;
atomBuff():len(0),buffPtr(NULL)
{}
~atomBuff()
{
if(buffPtr!=NULL)
delete []buffPtr;
}
};
public :
buffContainer():_totalLen(0){}
void insert(const char const *aptr,const unsigned long &alen);
unsigned long getBuff(T1 &arOutObj);
private:
std::vector<atomBuff*> moleculeBuff;
int _totalLen;
};
template<typename T1>
void buffContainer< T1>::insert(const char const *aPtr,const unsigned long &aLen)
{
if(aPtr==NULL,aLen<=0)
return;
atomBuff *obj=new atomBuff();
obj->len=aLen;
obj->buffPtr=new char[aLen];
memcpy(obj->buffPtr,aPtr,aLen);
_totalLen+=aLen;
moleculeBuff.push_back(obj);
}
template<typename T1>
unsigned long buffContainer<T1>::getBuff(T1 &arOutObj)
{
std::cout<<"Total Lenght of Data is: "<<_totalLen<<std::endl;
if(_totalLen==0)
return _totalLen;
// Note : Logic pending for case size(T1) > T2::Value_Type
int noOfObjRqd=_totalLen/sizeof(T1::value_type);
arOutObj.resize(noOfObjRqd);
char *ptr=(char*)(&arOutObj[0]);
for(std::vector<atomBuff*>::const_iterator itr=moleculeBuff.begin();itr!=moleculeBuff.end();itr++)
{
memcpy(ptr,(*itr)->buffPtr,(*itr)->len);
ptr+= (*itr)->len;
}
std::cout<<arOutObj.size()<<std::endl;
return _totalLen;
}
如何才能让这更高效?
答案 0 :(得分:2)
如果我对你的回调函数的猜测很有意义,那么除了向量之外你不需要任何东西:
std::vector<char> foo;
foo.reserve(MAGIC); // this is the important part. Reserve the right amount here.
// and you don't have any reallocs.
setup_callback_fun(CallbackFun, &foo);
CallbackFun ( int CBMsgFileItemID,
unsigned long CBtag,
void* CBuserInfo,
int CBdataSize,
void* CBdataBuffer,
int CBisFirst,
int CBisLast )
{
std::vector<char>* pFoo = static_cast<std::vector<char>*>(CBuserInfo);
char* data = static_cast<char*>CBdataBuffer;
pFoo->insert(pFoo->end(), data, data+CBdataSize);
}
答案 1 :(得分:1)
根据您计划使用结果的方式,您可能会尝试将传入数据放入rope数据结构而不是向量,尤其是如果您希望进入的字符串非常大。附加到绳索非常快,但随后的char-by-char遍历因常数因素而变慢。这种权衡可能对你有用,我不知道你需要对结果做些什么。
编辑:我从你的评论中看到,这是不可取的。在一般情况下,当进入的数据大小完全是任意的时,我认为你不能做得更有效率。否则,您可以尝试在向量中初始保留足够的空间,以便在平均情况下,数据适合不进行或最多只能进行一次重新分配。
我注意到你的代码有一件事:
if(aPtr==NULL,aLen<=0)
我认为你的意思是
if(aPtr==NULL || aLen<=0)
答案 2 :(得分:0)
你可以做的主要是避免做那么多的数据复制。现在,当调用insert()时,您将数据复制到缓冲区中。然后,当调用getbuff()时,您将数据复制到他们(希望)指定的缓冲区。因此,要从外部获取数据,您需要复制每个字节两次。
这部分:
arOutObj.resize(noOfObjRqd);
char *ptr=(char*)(&arOutObj[0]);
似乎假设arOutObj实际上是一个向量。如果是这样的话,将getbuff重写为采用(引用a)向量而不是真正仅适用于一种类型参数的模板的正常函数会好得多。
从那里,完全消除一个数据副本变得相当简单。在insert()中,不是手动分配内存和跟踪大小,而是将数据直接放入向量中。然后,当调用getbuff()时,不要将数据复制到缓冲区中,只需给出对现有向量的引用。
class buffContainer {
std::vector<char> moleculeBuff;
public:
void insert(char const *p, unsigned long len) {
Edit: Here you really want to add:
moleculeBuff.reserve(moleculeBuff.size()+len);
End of edit.
std::copy(p, p+len, std::back_inserter(moleculeBuff));
}
void getbuff(vector<char> &output) {
output = moleculeBuff;
}
};
请注意,我已经将getbuff的结果更改为void - 因为你给它们一个向量,它的大小是已知的,并且返回大小没有意义。实际上,您可能希望实际更改签名,只返回缓冲区:
vector<char> getbuff() {
vector<char> temp;
temp.swap(moleculeBuff);
return temp;
}
由于它按值返回一个(可能很大的)向量,这在很大程度上取决于你的编译器实现命名的返回值优化(NRVO),但是1)最糟糕的情况是它无论如何都要做你正在做的事情,并且2)几乎所有合理的当前编译器都实现了NRVO。
这也解决了原始代码没有(似乎)的另一个细节。实际上,getbuff会返回一些数据,但是如果你再次调用它,它(显然不会跟踪已经返回的数据),所以它会再次返回它。它会不断分配数据,但绝不会删除任何数据这就是交换的用途:它创建一个空向量,然后用buffContainer维护的向量交换,所以buffContainer现在有一个空向量,填充的向量移交给任何叫做getbuff()的东西。
另一种做法是将交换更进一步:基本上,你有两个缓冲区:
在正常情况下,我们可以预期缓冲区大小会很快达到某个最大大小。从那时起,我们真的想简单地重新循环该空间:将一些数据读入一个,传递给它进行处理,然后在发生这种情况时,将数据读入另一个数据。
碰巧的是,这也很容易做到。将getbuff()更改为如下所示:
void getbuff(vector<char> &output) {
swap(moleculeBuff, output);
moleculeBuff.clear();
}
这应该可以提高速度 - 而不是来回复制数据,它只是将一个向量的指针与其他数据交换到数据(以及其他一些细节,如当前分配大小和使用的大小)向量)。 clear通常真的快 - 对于矢量(或任何没有dtor的类型)它只会将矢量中的项目数设置为零(如果项目有dtors,则必须当然要毁掉它们。从那里,下次调用insert()时,新数据将被复制到向量已经拥有的内存中(除非它需要比向量分配的空间更多的空间)。