Added overallocation support for DataBlock.

This provides improved performance for repeated binary data appending.


git-svn-id: http://yate.null.ro/svn/yate/trunk@5973 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2015-05-18 13:12:02 +00:00
parent b7281eaade
commit 09f40eb24c
2 changed files with 83 additions and 19 deletions

View File

@ -82,20 +82,27 @@ const DataBlock& DataBlock::empty()
return s_empty;
}
DataBlock::DataBlock()
: m_data(0), m_length(0)
DataBlock::DataBlock(unsigned int overAlloc)
: m_data(0), m_length(0), m_allocated(0), m_overAlloc(overAlloc)
{
}
DataBlock::DataBlock(const DataBlock& value)
: GenObject(),
m_data(0), m_length(0)
m_data(0), m_length(0), m_allocated(0), m_overAlloc(value.overAlloc())
{
assign(value.data(),value.length());
}
DataBlock::DataBlock(void* value, unsigned int len, bool copyData)
: m_data(0), m_length(0)
DataBlock::DataBlock(const DataBlock& value, unsigned int overAlloc)
: GenObject(),
m_data(0), m_length(0), m_allocated(0), m_overAlloc(overAlloc)
{
assign(value.data(),value.length());
}
DataBlock::DataBlock(void* value, unsigned int len, bool copyData, unsigned int overAlloc)
: m_data(0), m_length(0), m_allocated(0), m_overAlloc(overAlloc)
{
assign(value,len,copyData);
}
@ -123,15 +130,17 @@ void DataBlock::clear(bool deleteData)
}
}
DataBlock& DataBlock::assign(void* value, unsigned int len, bool copyData)
DataBlock& DataBlock::assign(void* value, unsigned int len, bool copyData, unsigned int allocated)
{
if ((value != m_data) || (len != m_length)) {
void *odata = m_data;
m_length = 0;
m_allocated = 0;
m_data = 0;
if (len) {
if (copyData) {
void *data = ::malloc(len);
allocated = allocLen(len);
void *data = ::malloc(allocated);
if (data) {
if (value)
::memcpy(data,value,len);
@ -140,12 +149,17 @@ DataBlock& DataBlock::assign(void* value, unsigned int len, bool copyData)
m_data = data;
}
else
Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",len);
Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",allocated);
}
else
else {
if (allocated < len)
allocated = len;
m_data = value;
if (m_data)
}
if (m_data) {
m_length = len;
m_allocated = allocated;
}
}
if (odata && (odata != m_data))
::free(odata);
@ -189,14 +203,20 @@ void DataBlock::append(const DataBlock& value)
if (m_length) {
if (value.length()) {
unsigned int len = m_length+value.length();
void *data = ::malloc(len);
if (len <= m_allocated) {
::memcpy(m_length+(char*)m_data,value.data(),value.length());
m_length = len;
return;
}
unsigned int aLen = allocLen(len);
void *data = ::malloc(aLen);
if (data) {
::memcpy(data,m_data,m_length);
::memcpy(m_length+(char*)data,value.data(),value.length());
assign(data,len,false);
assign(data,len,false,aLen);
}
else
Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",len);
Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",aLen);
}
}
else
@ -208,14 +228,20 @@ void DataBlock::append(const String& value)
if (m_length) {
if (value.length()) {
unsigned int len = m_length+value.length();
void *data = ::malloc(len);
if (len <= m_allocated) {
::memcpy(m_length+(char*)m_data,value.safe(),value.length());
m_length = len;
return;
}
unsigned int aLen = allocLen(len);
void *data = ::malloc(aLen);
if (data) {
::memcpy(data,m_data,m_length);
::memcpy(m_length+(char*)data,value.safe(),value.length());
assign(data,len,false);
assign(data,len,false,aLen);
}
else
Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",len);
Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",aLen);
}
}
else
@ -242,6 +268,16 @@ void DataBlock::insert(const DataBlock& value)
assign(value.data(),vl);
}
unsigned int DataBlock::allocLen(unsigned int len) const
{
// allocate a multiple of 8 bytes
unsigned int over = (8 - (len & 7)) & 7;
if (over < m_overAlloc)
return (len + m_overAlloc + 7) & ~7;
else
return len + over;
}
bool DataBlock::convert(const DataBlock& src, const String& sFormat,
const String& dFormat, unsigned maxlen)
{

View File

@ -3751,21 +3751,31 @@ public:
/**
* Constructs an empty data block
* @param overAlloc How many bytes of memory to overallocate
*/
DataBlock();
DataBlock(unsigned int overAlloc = 0);
/**
* Copy constructor
* @param value Data block to copy from
*/
DataBlock(const DataBlock& value);
/**
* Copy constructor with overallocation
* @param value Data block to copy from
* @param overAlloc How many bytes of memory to overallocate
*/
DataBlock(const DataBlock& value, unsigned int overAlloc);
/**
* Constructs an initialized data block
* @param value Data to assign, may be NULL to fill with zeros
* @param len Length of data, may be zero (then value is ignored)
* @param copyData True to make a copy of the data, false to just insert the pointer
* @param overAlloc How many bytes of memory to overallocate
*/
DataBlock(void* value, unsigned int len, bool copyData = true);
DataBlock(void* value, unsigned int len, bool copyData = true, unsigned int overAlloc = 0);
/**
* Destroys the data, disposes the memory.
@ -3823,6 +3833,20 @@ public:
inline unsigned int length() const
{ return m_length; }
/**
* Get the memory overallocation setting.
* @return Amount of memory that will be overallocated.
*/
inline unsigned int overAlloc() const
{ return m_overAlloc; }
/**
* Set the memory overallocation.
* @param bytes How many bytes of memory to overallocate
*/
inline void overAlloc(unsigned int bytes)
{ m_overAlloc = bytes; }
/**
* Clear the data and optionally free the memory
* @param deleteData True to free the deta block, false to just forget it
@ -3834,8 +3858,9 @@ public:
* @param value Data to assign, may be NULL to fill with zeros
* @param len Length of data, may be zero (then value is ignored)
* @param copyData True to make a copy of the data, false to just insert the pointer
* @param allocated Real allocated data length in case it should not be copied
*/
DataBlock& assign(void* value, unsigned int len, bool copyData = true);
DataBlock& assign(void* value, unsigned int len, bool copyData = true, unsigned int allocated = 0);
/**
* Append data to the current block
@ -3971,8 +3996,11 @@ public:
String sqlEscape(char extraEsc) const;
private:
unsigned int allocLen(unsigned int len) const;
void* m_data;
unsigned int m_length;
unsigned int m_allocated;
unsigned int m_overAlloc;
};
/**