Buffer and FIFOBuffer performance optimizations

This commit is contained in:
Aleksandar Fabijanic
2012-04-28 04:32:35 +00:00
parent d7306cc7d9
commit b82cb14dfc
3 changed files with 64 additions and 24 deletions

View File

@@ -60,6 +60,7 @@ class Buffer
public: public:
Buffer(std::size_t size): Buffer(std::size_t size):
_size(size), _size(size),
_used(size),
_ptr(new T[size]) _ptr(new T[size])
/// Creates and allocates the Buffer. /// Creates and allocates the Buffer.
{ {
@@ -79,21 +80,30 @@ public:
{ {
poco_assert(newSize); poco_assert(newSize);
T* ptr = new T[newSize]; if (newSize > _size)
if (preserveContent)
{ {
std::size_t n = newSize > _size ? _size : newSize; T* ptr = new T[newSize];
std::memcpy(ptr, _ptr, n); if (preserveContent)
std::memcpy(ptr, _ptr, newSize);
delete [] _ptr;
_ptr = ptr;
_size = newSize;
} }
delete [] _ptr;
_ptr = ptr; _used = newSize;
_size = newSize; }
std::size_t allocated() const
/// Returns the allocated memory size.
{
return _size;
} }
std::size_t size() const std::size_t size() const
/// Returns the size of the buffer. /// Returns the used size of the buffer.
{ {
return _size; return _used;
} }
T* begin() T* begin()
@@ -111,25 +121,25 @@ public:
T* end() T* end()
/// Returns a pointer to end of the buffer. /// Returns a pointer to end of the buffer.
{ {
return _ptr + _size; return _ptr + _used;
} }
const T* end() const const T* end() const
/// Returns a pointer to the end of the buffer. /// Returns a pointer to the end of the buffer.
{ {
return _ptr + _size; return _ptr + _used;
} }
T& operator [] (std::size_t index) T& operator [] (std::size_t index)
{ {
poco_assert (index < _size); poco_assert (index < _used);
return _ptr[index]; return _ptr[index];
} }
const T& operator [] (std::size_t index) const const T& operator [] (std::size_t index) const
{ {
poco_assert (index < _size); poco_assert (index < _used);
return _ptr[index]; return _ptr[index];
} }
@@ -140,6 +150,7 @@ private:
Buffer& operator = (const Buffer&); Buffer& operator = (const Buffer&);
std::size_t _size; std::size_t _size;
std::size_t _used;
T* _ptr; T* _ptr;
}; };

View File

@@ -89,6 +89,7 @@ public:
FIFOBuffer(std::size_t size, bool notify = false): FIFOBuffer(std::size_t size, bool notify = false):
_buffer(size), _buffer(size),
_begin(0),
_used(0), _used(0),
_notify(notify) _notify(notify)
/// Creates and allocates the FIFOBuffer. /// Creates and allocates the FIFOBuffer.
@@ -124,7 +125,7 @@ public:
/// Peeks into the data currently in the FIFO /// Peeks into the data currently in the FIFO
/// without actually extracting it. /// without actually extracting it.
/// Resizes the supplied buffer to the size of /// Resizes the supplied buffer to the size of
///.data written to it. If length is not /// data written to it. If length is not
/// supplied by the caller, the current FIFO used length /// supplied by the caller, the current FIFO used length
/// is substituted for it. /// is substituted for it.
/// ///
@@ -135,7 +136,7 @@ public:
if (0 == length || length > _used) length = _used; if (0 == length || length > _used) length = _used;
poco_assert (length <= _buffer.size()); poco_assert (length <= _buffer.size());
buffer.resize(length); buffer.resize(length);
std::memcpy(buffer.begin(), _buffer.begin(), length * sizeof(T)); std::memcpy(buffer.begin(), _buffer.begin() + _begin, length * sizeof(T));
return length; return length;
} }
@@ -144,7 +145,7 @@ public:
/// Copies the data currently in the FIFO /// Copies the data currently in the FIFO
/// into the supplied buffer. /// into the supplied buffer.
/// Resizes the supplied buffer to the size of /// Resizes the supplied buffer to the size of
///.data written to it. /// data written to it.
/// ///
/// Returns the reference to the buffer. /// Returns the reference to the buffer.
{ {
@@ -156,9 +157,9 @@ public:
std::size_t readLen = peek(buffer, length); std::size_t readLen = peek(buffer, length);
poco_assert (_used >= readLen); poco_assert (_used >= readLen);
_used -= readLen; _used -= readLen;
if (_used > 0) if (0 == _used) _begin = 0;
std::memmove(_buffer.begin(), _buffer.begin() + usedBefore - _used, _used); else _begin += length;
if (_notify) notify(usedBefore); if (_notify) notify(usedBefore);
return readLen; return readLen;
@@ -174,11 +175,16 @@ public:
{ {
Mutex::ScopedLock lock(_mutex); Mutex::ScopedLock lock(_mutex);
poco_assert (_used <= _buffer.size()); if (_buffer.size() - (_begin + _used) < buffer.size())
{
std::memmove(_buffer.begin(), _buffer.begin() + _begin, _used);
_begin = 0;
}
std::size_t usedBefore = _used; std::size_t usedBefore = _used;
std::size_t available = _buffer.size() - _used; std::size_t available = _buffer.size() - _used - _begin;
std::size_t len = buffer.size() > available ? available : buffer.size(); std::size_t len = buffer.size() > available ? available : buffer.size();
std::memcpy(_buffer.begin() + _used, buffer.begin(), len * sizeof(T)); std::memcpy(_buffer.begin() + _begin + _used, buffer.begin(), len * sizeof(T));
_used += len; _used += len;
poco_assert (_used <= _buffer.size()); poco_assert (_used <= _buffer.size());
if (_notify) notify(usedBefore); if (_notify) notify(usedBefore);
@@ -212,7 +218,7 @@ public:
if (index >= _used) if (index >= _used)
throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1)); throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
return _buffer[index]; return _buffer[_begin + index];
} }
const T& operator [] (std::size_t index) const const T& operator [] (std::size_t index) const
@@ -223,7 +229,7 @@ public:
if (index >= _used) if (index >= _used)
throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1)); throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
return _buffer[index]; return _buffer[_begin + index];
} }
bool isEmpty() const bool isEmpty() const
@@ -251,6 +257,7 @@ private:
FIFOBuffer& operator = (const FIFOBuffer&); FIFOBuffer& operator = (const FIFOBuffer&);
Buffer<T> _buffer; Buffer<T> _buffer;
std::size_t _begin;
std::size_t _used; std::size_t _used;
bool _notify; bool _notify;
mutable Mutex _mutex; mutable Mutex _mutex;

View File

@@ -197,6 +197,8 @@ void CoreTest::testBuffer()
{ {
std::size_t s = 10; std::size_t s = 10;
Buffer<int> b(s); Buffer<int> b(s);
assert (b.size() == s);
assert (b.allocated() == s);
std::vector<int> v; std::vector<int> v;
for (int i = 0; i < s; ++i) for (int i = 0; i < s; ++i)
v.push_back(i); v.push_back(i);
@@ -207,6 +209,26 @@ void CoreTest::testBuffer()
for (int i = 0; i < s; ++i) for (int i = 0; i < s; ++i)
assert (b[i] == i); assert (b[i] == i);
b.resize(s/2);
for (int i = 0; i < s/2; ++i)
assert (b[i] == i);
assert (b.size() == s/2);
assert (b.allocated() == s);
b.resize(s*2);
v.clear();
for (int i = 0; i < s*2; ++i)
v.push_back(i);
std::memcpy(b.begin(), &v[0], sizeof(int) * v.size());
for (int i = 0; i < s*2; ++i)
assert (b[i] == i);
assert (b.size() == s*2);
assert (b.allocated() == s*2);
#if ENABLE_BUGCHECK_TEST #if ENABLE_BUGCHECK_TEST
try { int i = b[s]; fail ("must fail"); } try { int i = b[s]; fail ("must fail"); }
catch (Exception&) { } catch (Exception&) { }