mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
[WIP] Implements reusable sample buffers across all components. This
produces a significant reduction in memory usage, especially for tuners like the airspy and hackrf that produce 10/20 MSPS sample rates. This is observed to be around 66% reduction in peak memory usage and provides a more stable memory utilization across time reducing stress on the garbage collector. Use of these reusable memory buffers will be pushed further down into the processing chain modules to ensure we keep new object creation to the lowest levels possible.
This commit is contained in:
@@ -17,10 +17,10 @@ package io.github.dsheirer.source.tuner.test;
|
||||
|
||||
import io.github.dsheirer.dsp.mixer.IOscillator;
|
||||
import io.github.dsheirer.dsp.mixer.LowPhaseNoiseOscillator;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.ComplexBuffer;
|
||||
import io.github.dsheirer.sample.complex.TimestampedComplexBuffer;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferBroadcaster;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferQueue;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -32,7 +32,7 @@ public class SampleGenerator
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(SampleGenerator.class);
|
||||
|
||||
private Broadcaster<ComplexBuffer> mComplexBufferBroadcaster = new Broadcaster<>();
|
||||
private ReusableBufferBroadcaster mComplexBufferBroadcaster = new ReusableBufferBroadcaster();
|
||||
private IOscillator mOscillator;
|
||||
private int mSweepUpdateInterval;
|
||||
private long mInterval;
|
||||
@@ -79,21 +79,6 @@ public class SampleGenerator
|
||||
this(sampleRate, frequency, interval, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the sample generator to reuse the same sample buffer each time instead of generating new samples for
|
||||
* each and every buffer. This is useful when you simply want to generate data to test or profile data flows and
|
||||
* are not concerned about the content of the buffers.
|
||||
*
|
||||
* The generator will create a new buffer of data each time that it detects that the sample size changes or when
|
||||
* the tone frequency changes.
|
||||
*
|
||||
* @param reuseBuffers set to true to turn on buffer reuse
|
||||
*/
|
||||
public void setReuseBuffers(boolean reuseBuffers)
|
||||
{
|
||||
mReuseBuffers = reuseBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the number of complex samples generated per interval
|
||||
*/
|
||||
@@ -139,7 +124,7 @@ public class SampleGenerator
|
||||
*
|
||||
* @param listener to receive complex sample buffers
|
||||
*/
|
||||
public void addListener(Listener<ComplexBuffer> listener)
|
||||
public void addListener(Listener<ReusableComplexBuffer> listener)
|
||||
{
|
||||
mComplexBufferBroadcaster.addListener(listener);
|
||||
|
||||
@@ -152,7 +137,7 @@ public class SampleGenerator
|
||||
/**
|
||||
* Removes the listener and stops the sample generator if there are no more listeners.
|
||||
*/
|
||||
public void removeListener(Listener<ComplexBuffer> listener)
|
||||
public void removeListener(Listener<ReusableComplexBuffer> listener)
|
||||
{
|
||||
mComplexBufferBroadcaster.removeListener(listener);
|
||||
|
||||
@@ -200,31 +185,18 @@ public class SampleGenerator
|
||||
public class Generator implements Runnable
|
||||
{
|
||||
private int mTriggerInterval = 0;
|
||||
private long mOscillatorFrequency = 1;
|
||||
private ComplexBuffer mReusableBuffer;
|
||||
private ReusableBufferQueue mReusableBufferQueue = new ReusableBufferQueue("** Sample Generator **");
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(mComplexBufferBroadcaster.hasListeners())
|
||||
{
|
||||
if(mReuseBuffers)
|
||||
{
|
||||
if(mReusableBuffer == null ||
|
||||
mReusableBuffer.getSamples().length != mSamplesPerInterval ||
|
||||
mOscillatorFrequency != mOscillator.getFrequency())
|
||||
{
|
||||
mOscillatorFrequency = (long)mOscillator.getFrequency();
|
||||
mReusableBuffer = new TimestampedComplexBuffer(mOscillator.generateComplex(mSamplesPerInterval));
|
||||
}
|
||||
ReusableComplexBuffer reusableComplexBuffer = mReusableBufferQueue.getBuffer(mSamplesPerInterval);
|
||||
|
||||
mComplexBufferBroadcaster.receive(mReusableBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
float[] samples = mOscillator.generateComplex(mSamplesPerInterval);
|
||||
mComplexBufferBroadcaster.receive(new TimestampedComplexBuffer(samples));
|
||||
}
|
||||
mOscillator.generateComplex(reusableComplexBuffer);
|
||||
|
||||
mComplexBufferBroadcaster.broadcast(reusableComplexBuffer.incrementUserCount());
|
||||
|
||||
if(mSweepUpdateInterval != 0)
|
||||
{
|
||||
|
||||
@@ -41,9 +41,6 @@ public class TestTuner extends Tuner
|
||||
|
||||
/**
|
||||
* Returns the tuner controller cast as a test tuner controller.
|
||||
*
|
||||
* Note: this is a temporary method until the tuner controller interface can be updated with the start(listener)
|
||||
* and stop() methods.
|
||||
*/
|
||||
public TestTunerController getTunerController()
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
package io.github.dsheirer.source.tuner.test;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.ComplexBuffer;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
import io.github.dsheirer.source.tuner.TunerController;
|
||||
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
|
||||
@@ -34,7 +34,7 @@ public class TestTunerController extends TunerController
|
||||
public static final long MAXIMUM_FREQUENCY = 1000000000l;
|
||||
public static final int SAMPLE_RATE = 800000;
|
||||
public static final int DC_NOISE_BANDWIDTH = 0;
|
||||
public static final double USABLE_BANDWIDTH = 1.00;
|
||||
public static final double USABLE_BANDWIDTH_PERCENTAGE = 1.00;
|
||||
|
||||
public static final int SPECTRAL_FRAME_RATE = 20;
|
||||
public static final long SAMPLE_GENERATION_INTERVAL = 1000 / SPECTRAL_FRAME_RATE;
|
||||
@@ -47,7 +47,7 @@ public class TestTunerController extends TunerController
|
||||
*/
|
||||
public TestTunerController()
|
||||
{
|
||||
super(MINIMUM_FREQUENCY, MAXIMUM_FREQUENCY, DC_NOISE_BANDWIDTH, USABLE_BANDWIDTH);
|
||||
super(MINIMUM_FREQUENCY, MAXIMUM_FREQUENCY, DC_NOISE_BANDWIDTH, USABLE_BANDWIDTH_PERCENTAGE);
|
||||
|
||||
int sweepRate = 0; //Hz per interval
|
||||
long initialToneFrequency = SAMPLE_RATE / 2 + 100;
|
||||
@@ -65,25 +65,14 @@ public class TestTunerController extends TunerController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample generator to reuse buffers instead of generating new buffers each time. Enable this setting
|
||||
* when you simply want to test/profile buffer data flows for consumer processes.
|
||||
*
|
||||
* @param reuseBuffers set to true to turn on buffer reuse
|
||||
*/
|
||||
public void setReuseBuffers(boolean reuseBuffers)
|
||||
{
|
||||
mSampleGenerator.setReuseBuffers(reuseBuffers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addComplexBufferListener(Listener<ComplexBuffer> listener)
|
||||
public void addBufferListener(Listener<ReusableComplexBuffer> listener)
|
||||
{
|
||||
mSampleGenerator.addListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeComplexBufferListener(Listener<ComplexBuffer> listener)
|
||||
public void removeBufferListener(Listener<ReusableComplexBuffer> listener)
|
||||
{
|
||||
mSampleGenerator.removeListener(listener);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user