]> sigrok.org Git - pulseview.git/commitdiff
Preallocate memory before samples are received.
authorDaniel King <redacted>
Thu, 13 Feb 2014 20:16:17 +0000 (20:16 +0000)
committerJoel Holdsworth <redacted>
Fri, 14 Feb 2014 17:31:51 +0000 (17:31 +0000)
Preallocating memory for samples when a capture is started improves performance during the capture, as realloc() is called only once.

pv/data/analogsnapshot.cpp
pv/data/analogsnapshot.h
pv/data/logicsnapshot.cpp
pv/data/logicsnapshot.h
pv/data/snapshot.cpp
pv/data/snapshot.h
pv/devinst.cpp
pv/devinst.h
pv/sigsession.cpp

index 4907d7954a186af7c6d7b5f0c2c8447714edc32a..4d4f5d67b8866b4d29aa754c595cf15c2cdd235b 100644 (file)
@@ -47,9 +47,11 @@ const float AnalogSnapshot::LogEnvelopeScaleFactor =
        logf(EnvelopeScaleFactor);
 const uint64_t AnalogSnapshot::EnvelopeDataUnit = 64*1024;     // bytes
 
-AnalogSnapshot::AnalogSnapshot() :
+AnalogSnapshot::AnalogSnapshot(const uint64_t expected_num_samples) :
        Snapshot(sizeof(float))
 {
+       set_capacity(expected_num_samples);
+
        lock_guard<recursive_mutex> lock(_mutex);
        memset(_envelope_levels, 0, sizeof(_envelope_levels));
 }
index 9c7f4d51ae982bc76cad204995cbcbbc380ec241..b60c2ce72580c4fdf51d84940f0e836216759bae 100644 (file)
@@ -66,7 +66,7 @@ private:
        static const uint64_t EnvelopeDataUnit;
 
 public:
-       AnalogSnapshot();
+       AnalogSnapshot(uint64_t expected_num_samples = 0);
 
        virtual ~AnalogSnapshot();
 
index f203e8b674fb57fb37c556edc593c5e1798873a8..754a456cc8f2e6c078cfd5a46e8b1c756571f79a 100644 (file)
@@ -43,10 +43,13 @@ const int LogicSnapshot::MipMapScaleFactor = 1 << MipMapScalePower;
 const float LogicSnapshot::LogMipMapScaleFactor = logf(MipMapScaleFactor);
 const uint64_t LogicSnapshot::MipMapDataUnit = 64*1024;        // bytes
 
-LogicSnapshot::LogicSnapshot(const sr_datafeed_logic &logic) :
+LogicSnapshot::LogicSnapshot(const sr_datafeed_logic &logic,
+                             const uint64_t expected_num_samples) :
        Snapshot(logic.unitsize),
        _last_append_sample(0)
 {
+       set_capacity(expected_num_samples);
+
        lock_guard<recursive_mutex> lock(_mutex);
        memset(_mip_map, 0, sizeof(_mip_map));
        append_payload(logic);
index ecff5edc089c61846c400c400cb7c1192303a8fa..50fb6f8335b97e883007f45bfa9e26207dc30a47 100644 (file)
@@ -58,7 +58,8 @@ public:
        typedef std::pair<int64_t, bool> EdgePair;
 
 public:
-       LogicSnapshot(const sr_datafeed_logic &logic);
+       LogicSnapshot(const sr_datafeed_logic &logic,
+                     uint64_t expected_num_samples = 0);
 
        virtual ~LogicSnapshot();
 
index 85f54e784a1174cc0023ae687964ddc6c9ef6165..6ba39d2fe9ef57b32f8e67747ccdc65d25dbf170 100644 (file)
@@ -33,6 +33,7 @@ namespace data {
 Snapshot::Snapshot(int unit_size) :
        _data(NULL),
        _sample_count(0),
+       _capacity(0),
        _unit_size(unit_size)
 {
        lock_guard<recursive_mutex> lock(_mutex);
@@ -56,11 +57,35 @@ int Snapshot::unit_size() const
        return _unit_size;
 }
 
+void Snapshot::set_capacity(const uint64_t new_capacity)
+{
+       lock_guard<recursive_mutex> lock(_mutex);
+
+       assert(_capacity >= _sample_count);
+       if (new_capacity > _capacity) {
+               _capacity = new_capacity;
+               _data = realloc(_data, (new_capacity * _unit_size) + sizeof(uint64_t));
+       }
+}
+
+uint64_t Snapshot::capacity() const
+{
+       lock_guard<recursive_mutex> lock(_mutex);
+       return _capacity;
+}
+
 void Snapshot::append_data(void *data, uint64_t samples)
 {
        lock_guard<recursive_mutex> lock(_mutex);
-       _data = realloc(_data, (_sample_count + samples) * _unit_size +
-               sizeof(uint64_t));
+
+       assert(_capacity >= _sample_count);
+
+       // Ensure there's enough capacity to copy.
+       const uint64_t free_space = _capacity - _sample_count;
+       if (free_space < samples) {
+               set_capacity(_sample_count + samples);
+       }
+
        memcpy((uint8_t*)_data + _sample_count * _unit_size,
                data, samples * _unit_size);
        _sample_count += samples;
index 1758d4cddaa7720f35a02449d344b311274cfcc1..1f1ca3cf0b8539e7387c5211434123ce98ee42f4 100644 (file)
@@ -39,6 +39,33 @@ public:
 
        int unit_size() const;
 
+       /**
+        * @brief Increase the capacity of the snapshot.
+        *
+        * Increasing the capacity allows samples to be appended without needing
+        * to reallocate memory.
+        *
+        * For the best efficiency @c set_capacity() should be called once before
+        * @c append_data() is called to set up the snapshot with the expected number
+        * of samples that will be appended in total.
+        *
+        * @note The capacity will automatically be increased when @c append_data()
+        * is called if there is not enough capacity in the buffer to store the samples.
+        *
+        * @param[in] new_capacity The new capacity of the snapshot. If this value is
+        *      smaller or equal than the current capacity then the method has no effect.
+        */
+       void set_capacity(uint64_t new_capacity);
+
+       /**
+        * @brief Get the current capacity of the snapshot.
+        *
+        * The capacity can be increased by calling @c set_capacity().
+        *
+        * @return The current capacity of the snapshot.
+        */
+       uint64_t capacity() const;
+
 protected:
        void append_data(void *data, uint64_t samples);
 
@@ -46,6 +73,7 @@ protected:
        mutable boost::recursive_mutex _mutex;
        void *_data;
        uint64_t _sample_count;
+       uint64_t _capacity;
        int _unit_size;
 };
 
index 4480c43fdb995234cb516cd1127ab632e4949ffb..b28fce08269f4c3f238d01c8fd016e5aecb560ec 100644 (file)
@@ -106,4 +106,17 @@ void DevInst::enable_probe(const sr_probe *probe, bool enable)
        assert(0);
 }
 
+uint64_t DevInst::get_sample_limit()
+{
+       uint64_t sample_limit;
+       GVariant* gvar = get_config(NULL, SR_CONF_LIMIT_SAMPLES);
+       if (gvar != NULL) {
+               sample_limit = g_variant_get_uint64(gvar);
+               g_variant_unref(gvar);
+       } else {
+               sample_limit = 0U;
+       }
+       return sample_limit;
+}
+
 } // pv
index 0ce767452742c691f38b9caf58fa39d35bcfd90c..e57a4e44e112a06c35428642804b3f2906f42142 100644 (file)
@@ -29,6 +29,8 @@
 
 #include <glib.h>
 
+#include <stdint.h>
+
 struct sr_dev_inst;
 struct sr_probe;
 struct sr_probe_group;
@@ -54,6 +56,14 @@ public:
 
        void enable_probe(const sr_probe *probe, bool enable = true);
 
+       /**
+        * @brief Gets the sample limit from the driver.
+        *
+        * @return The returned sample limit from the driver, or 0 if the
+        *      sample limit could not be read.
+        */
+       uint64_t get_sample_limit();
+
 signals:
        void config_changed();
 
index 5da1551fc51cee4e1e5e3f539654359280933c37..10ea4ffbea6dc1ad4e171b9054289e938fad66f0 100644 (file)
@@ -645,7 +645,7 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic)
 
                // Create a new data snapshot
                _cur_logic_snapshot = shared_ptr<data::LogicSnapshot>(
-                       new data::LogicSnapshot(logic));
+                       new data::LogicSnapshot(logic, _dev_inst->get_sample_limit()));
                _logic_data->push_snapshot(_cur_logic_snapshot);
        }
        else
@@ -687,7 +687,7 @@ void SigSession::feed_in_analog(const sr_datafeed_analog &analog)
 
                        // Create a snapshot, keep it in the maps of probes
                        snapshot = shared_ptr<data::AnalogSnapshot>(
-                               new data::AnalogSnapshot());
+                               new data::AnalogSnapshot(_dev_inst->get_sample_limit()));
                        _cur_analog_snapshots[probe] = snapshot;
 
                        // Find the annalog data associated with the probe