From: Daniel King Date: Thu, 13 Feb 2014 20:16:17 +0000 (+0000) Subject: Preallocate memory before samples are received. X-Git-Tag: pulseview-0.2.0~70 X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=commitdiff_plain;h=27d7c96b57d967edd8bcde9bb5570d573a0ef474 Preallocate memory before samples are received. Preallocating memory for samples when a capture is started improves performance during the capture, as realloc() is called only once. --- diff --git a/pv/data/analogsnapshot.cpp b/pv/data/analogsnapshot.cpp index 4907d795..4d4f5d67 100644 --- a/pv/data/analogsnapshot.cpp +++ b/pv/data/analogsnapshot.cpp @@ -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 lock(_mutex); memset(_envelope_levels, 0, sizeof(_envelope_levels)); } diff --git a/pv/data/analogsnapshot.h b/pv/data/analogsnapshot.h index 9c7f4d51..b60c2ce7 100644 --- a/pv/data/analogsnapshot.h +++ b/pv/data/analogsnapshot.h @@ -66,7 +66,7 @@ private: static const uint64_t EnvelopeDataUnit; public: - AnalogSnapshot(); + AnalogSnapshot(uint64_t expected_num_samples = 0); virtual ~AnalogSnapshot(); diff --git a/pv/data/logicsnapshot.cpp b/pv/data/logicsnapshot.cpp index f203e8b6..754a456c 100644 --- a/pv/data/logicsnapshot.cpp +++ b/pv/data/logicsnapshot.cpp @@ -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 lock(_mutex); memset(_mip_map, 0, sizeof(_mip_map)); append_payload(logic); diff --git a/pv/data/logicsnapshot.h b/pv/data/logicsnapshot.h index ecff5edc..50fb6f83 100644 --- a/pv/data/logicsnapshot.h +++ b/pv/data/logicsnapshot.h @@ -58,7 +58,8 @@ public: typedef std::pair EdgePair; public: - LogicSnapshot(const sr_datafeed_logic &logic); + LogicSnapshot(const sr_datafeed_logic &logic, + uint64_t expected_num_samples = 0); virtual ~LogicSnapshot(); diff --git a/pv/data/snapshot.cpp b/pv/data/snapshot.cpp index 85f54e78..6ba39d2f 100644 --- a/pv/data/snapshot.cpp +++ b/pv/data/snapshot.cpp @@ -33,6 +33,7 @@ namespace data { Snapshot::Snapshot(int unit_size) : _data(NULL), _sample_count(0), + _capacity(0), _unit_size(unit_size) { lock_guard 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 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 lock(_mutex); + return _capacity; +} + void Snapshot::append_data(void *data, uint64_t samples) { lock_guard 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; diff --git a/pv/data/snapshot.h b/pv/data/snapshot.h index 1758d4cd..1f1ca3cf 100644 --- a/pv/data/snapshot.h +++ b/pv/data/snapshot.h @@ -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; }; diff --git a/pv/devinst.cpp b/pv/devinst.cpp index 4480c43f..b28fce08 100644 --- a/pv/devinst.cpp +++ b/pv/devinst.cpp @@ -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 diff --git a/pv/devinst.h b/pv/devinst.h index 0ce76745..e57a4e44 100644 --- a/pv/devinst.h +++ b/pv/devinst.h @@ -29,6 +29,8 @@ #include +#include + 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(); diff --git a/pv/sigsession.cpp b/pv/sigsession.cpp index 5da1551f..10ea4ffb 100644 --- a/pv/sigsession.cpp +++ b/pv/sigsession.cpp @@ -645,7 +645,7 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic) // Create a new data snapshot _cur_logic_snapshot = shared_ptr( - 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( - new data::AnalogSnapshot()); + new data::AnalogSnapshot(_dev_inst->get_sample_limit())); _cur_analog_snapshots[probe] = snapshot; // Find the annalog data associated with the probe