Changeset - 29bd9e9a44b0
[Not reviewed]
default
0 2 0
Hasan Yavuz ÖZDERYA - 8 years ago 2017-11-07 06:11:21
hy@ozderya.net
cache bounding rectangle instead of re-calculating at every reading

improves performance significantly for big buffers
2 files changed with 36 insertions and 23 deletions:
0 comments (0 inline, 0 general)
src/framebuffer.cpp
Show inline comments
 
/*
 
  Copyright © 2015 Hasan Yavuz Özderya
 
  Copyright © 2017 Hasan Yavuz Özderya
 

	
 
  This file is part of serialplot.
 

	
 
  serialplot is free software: you can redistribute it and/or modify
 
  it under the terms of the GNU General Public License as published by
 
  the Free Software Foundation, either version 3 of the License, or
 
  (at your option) any later version.
 

	
 
  serialplot is distributed in the hope that it will be useful,
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  GNU General Public License for more details.
 
@@ -16,25 +16,26 @@
 
  You should have received a copy of the GNU General Public License
 
  along with serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#include "framebuffer.h"
 

	
 
FrameBuffer::FrameBuffer(size_t size)
 
{
 
    _size = size;
 
    data = new double[_size]();
 
    headIndex = 0;
 

	
 
    _boundingRect.setCoords(0, 0, size, 0);
 
    brInvalid = false;
 
    _brCache.setCoords(0, 0, size, 0);
 
}
 

	
 
FrameBuffer::~FrameBuffer()
 
{
 
    delete[] data;
 
}
 

	
 
void FrameBuffer::resize(size_t size)
 
{
 
    int offset = size - _size;
 
    if (offset == 0) return;
 

	
 
@@ -54,26 +55,26 @@ void FrameBuffer::resize(size_t size)
 
        for (int i = 0; i < fill_start; i++)
 
        {
 
            newData[i] = 0;
 
        }
 
    }
 

	
 
    // data is ready, clean and re-point
 
    delete data;
 
    data = newData;
 
    headIndex = 0;
 
    _size = size;
 

	
 
    // update the bounding rectangle
 
    _boundingRect.setRight(_size);
 
    // invalidate bounding rectangle
 
    brInvalid = true;
 
}
 

	
 
void FrameBuffer::addSamples(double* samples, size_t size)
 
{
 
    unsigned shift = size;
 
    if (shift < _size)
 
    {
 
        unsigned x = _size - headIndex; // distance of `head` to end
 

	
 
        if (shift <= x) // there is enough room at the end of array
 
        {
 
            for (size_t i = 0; i < shift; i++)
 
@@ -104,51 +105,61 @@ void FrameBuffer::addSamples(double* sam
 
        }
 
    }
 
    else // number of new samples equal or bigger than current size
 
    {
 
        int x = shift - _size;
 
        for (size_t i = 0; i < _size; i++)
 
        {
 
            data[i] = samples[i+x];
 
        }
 
        headIndex = 0;
 
    }
 

	
 
    // update bounding rectangle
 
    // invalidate cache
 
    brInvalid = true;
 
}
 

	
 
void FrameBuffer::clear()
 
{
 
    for (size_t i=0; i < _size; i++) data[i] = 0.;
 

	
 
    _brCache.setCoords(0, 0, _size, 0);
 
}
 

	
 
size_t FrameBuffer::size() const
 
{
 
    return _size;
 
}
 

	
 
QRectF FrameBuffer::boundingRect() const
 
{
 
    if (brInvalid) updateBoundingRect();
 
    return _brCache;
 
}
 

	
 
void FrameBuffer::updateBoundingRect() const
 
{
 
    double minValue = data[0];
 
    double maxValue = data[0];
 
    for (size_t i = 0; i < _size; i++)
 
    {
 
        if (data[i] > maxValue)
 
        {
 
            maxValue = data[i];
 
        }
 
        else if (data[i] < minValue)
 
        {
 
            minValue = data[i];
 
        }
 
    }
 
    _boundingRect.setTop(minValue);
 
    _boundingRect.setBottom(maxValue);
 
}
 

	
 
void FrameBuffer::clear()
 
{
 
    for (size_t i=0; i < _size; i++) data[i] = 0.;
 
}
 
    _brCache.setTop(minValue);
 
    _brCache.setBottom(maxValue);
 

	
 
size_t FrameBuffer::size() const
 
{
 
    return _size;
 
}
 

	
 
QRectF FrameBuffer::boundingRect() const
 
{
 
    return _boundingRect;
 
    brInvalid = false;
 
}
 

	
 
double FrameBuffer::sample(size_t i) const
 
{
 
    size_t index = headIndex + i;
 
    if (index >= _size) index -= _size;
 
    return data[index];
 
}
src/framebuffer.h
Show inline comments
 
/*
 
  Copyright © 2015 Hasan Yavuz Özderya
 
  Copyright © 2017 Hasan Yavuz Özderya
 

	
 
  This file is part of serialplot.
 

	
 
  serialplot is free software: you can redistribute it and/or modify
 
  it under the terms of the GNU General Public License as published by
 
  the Free Software Foundation, either version 3 of the License, or
 
  (at your option) any later version.
 

	
 
  serialplot is distributed in the hope that it will be useful,
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  GNU General Public License for more details.
 
@@ -34,16 +34,18 @@ public:
 
    void clear(); // fill 0
 

	
 
    // QwtSeriesData related implementations
 
    size_t size() const;
 
    QRectF boundingRect() const;
 
    double sample(size_t i) const;
 

	
 
private:
 
    size_t _size; // size of `data`
 
    double* data;
 
    size_t headIndex; // indicates the actual `0` index of the ring buffer
 

	
 
    QRectF _boundingRect;
 
    mutable bool brInvalid; ///< Indicates that bounding rectangle needs to be re-calculated
 
    mutable QRectF _brCache; ///< Cache for boundingRect()
 
    void updateBoundingRect() const; ///< Updates bounding rectangle cache
 
};
 

	
 
#endif // FRAMEBUFFER_H
0 comments (0 inline, 0 general)