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; return s_empty;
} }
DataBlock::DataBlock() DataBlock::DataBlock(unsigned int overAlloc)
: m_data(0), m_length(0) : m_data(0), m_length(0), m_allocated(0), m_overAlloc(overAlloc)
{ {
} }
DataBlock::DataBlock(const DataBlock& value) DataBlock::DataBlock(const DataBlock& value)
: GenObject(), : 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()); assign(value.data(),value.length());
} }
DataBlock::DataBlock(void* value, unsigned int len, bool copyData) DataBlock::DataBlock(const DataBlock& value, unsigned int overAlloc)
: m_data(0), m_length(0) : 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); 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)) { if ((value != m_data) || (len != m_length)) {
void *odata = m_data; void *odata = m_data;
m_length = 0; m_length = 0;
m_allocated = 0;
m_data = 0; m_data = 0;
if (len) { if (len) {
if (copyData) { if (copyData) {
void *data = ::malloc(len); allocated = allocLen(len);
void *data = ::malloc(allocated);
if (data) { if (data) {
if (value) if (value)
::memcpy(data,value,len); ::memcpy(data,value,len);
@ -140,12 +149,17 @@ DataBlock& DataBlock::assign(void* value, unsigned int len, bool copyData)
m_data = data; m_data = data;
} }
else 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; m_data = value;
if (m_data) }
if (m_data) {
m_length = len; m_length = len;
m_allocated = allocated;
}
} }
if (odata && (odata != m_data)) if (odata && (odata != m_data))
::free(odata); ::free(odata);
@ -189,14 +203,20 @@ void DataBlock::append(const DataBlock& value)
if (m_length) { if (m_length) {
if (value.length()) { if (value.length()) {
unsigned int len = m_length+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) { if (data) {
::memcpy(data,m_data,m_length); ::memcpy(data,m_data,m_length);
::memcpy(m_length+(char*)data,value.data(),value.length()); ::memcpy(m_length+(char*)data,value.data(),value.length());
assign(data,len,false); assign(data,len,false,aLen);
} }
else else
Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",len); Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",aLen);
} }
} }
else else
@ -208,14 +228,20 @@ void DataBlock::append(const String& value)
if (m_length) { if (m_length) {
if (value.length()) { if (value.length()) {
unsigned int len = m_length+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) { if (data) {
::memcpy(data,m_data,m_length); ::memcpy(data,m_data,m_length);
::memcpy(m_length+(char*)data,value.safe(),value.length()); ::memcpy(m_length+(char*)data,value.safe(),value.length());
assign(data,len,false); assign(data,len,false,aLen);
} }
else else
Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",len); Debug("DataBlock",DebugFail,"malloc(%d) returned NULL!",aLen);
} }
} }
else else
@ -242,6 +268,16 @@ void DataBlock::insert(const DataBlock& value)
assign(value.data(),vl); 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, bool DataBlock::convert(const DataBlock& src, const String& sFormat,
const String& dFormat, unsigned maxlen) const String& dFormat, unsigned maxlen)
{ {

View File

@ -3751,21 +3751,31 @@ public:
/** /**
* Constructs an empty data block * Constructs an empty data block
* @param overAlloc How many bytes of memory to overallocate
*/ */
DataBlock(); DataBlock(unsigned int overAlloc = 0);
/** /**
* Copy constructor * Copy constructor
* @param value Data block to copy from
*/ */
DataBlock(const DataBlock& value); 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 * Constructs an initialized data block
* @param value Data to assign, may be NULL to fill with zeros * @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 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 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. * Destroys the data, disposes the memory.
@ -3823,6 +3833,20 @@ public:
inline unsigned int length() const inline unsigned int length() const
{ return m_length; } { 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 * Clear the data and optionally free the memory
* @param deleteData True to free the deta block, false to just forget it * @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 value Data to assign, may be NULL to fill with zeros
* @param len Length of data, may be zero (then value is ignored) * @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 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 * Append data to the current block
@ -3971,8 +3996,11 @@ public:
String sqlEscape(char extraEsc) const; String sqlEscape(char extraEsc) const;
private: private:
unsigned int allocLen(unsigned int len) const;
void* m_data; void* m_data;
unsigned int m_length; unsigned int m_length;
unsigned int m_allocated;
unsigned int m_overAlloc;
}; };
/** /**