Resolves issue with application memory growth and thread pool

saturation.

Each tunerchannelsource was sharing a thread pool and as the processing
load increased, the thread pool was not expanding and the processing
tasks were backing up, causing the buffers to grow with unprocessed
data.

Changed so that each tuner channel source is handed a thread pool to use
for processing incoming sample data.  Processing chain maintains the
thread pool and starts the channel source.  This allows traffic channels
to reuse the thread pool across multiple iterations.
This commit is contained in:
denny
2016-02-15 09:46:33 -05:00
parent d8a20b5adb
commit dd22397f75
17 changed files with 70 additions and 62 deletions

View File

@@ -19,7 +19,8 @@ package module;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import message.IMessageListener;
@@ -61,7 +62,7 @@ import audio.metadata.Metadata;
import audio.squelch.ISquelchStateListener;
import audio.squelch.ISquelchStateProvider;
import audio.squelch.SquelchState;
import controller.ThreadPoolManager;
import controller.NamingThreadFactory;
import controller.channel.ChannelEvent;
import controller.channel.IChannelEventListener;
import controller.channel.IChannelEventProvider;
@@ -99,15 +100,17 @@ public class ProcessingChain implements IChannelEventListener
private Broadcaster<RealBuffer> mRealBufferBroadcaster = new Broadcaster<>();
private Broadcaster<SquelchState> mSquelchStateBroadcaster = new Broadcaster<>();
// private ThreadPoolManager mThreadPoolManager;
private ScheduledExecutorService mScheduledExecutorService;
private AtomicBoolean mRunning = new AtomicBoolean();
protected Source mSource;
private List<Module> mModules = new ArrayList<>();
private IFrequencyCorrectionController mFrequencyCorrectionController;
public ProcessingChain()
public ProcessingChain( String name )
{
mScheduledExecutorService = Executors.newScheduledThreadPool( 1,
new NamingThreadFactory( "channel " + name ) );
}
public void dispose()
@@ -121,6 +124,9 @@ public class ProcessingChain implements IChannelEventListener
mModules.clear();
mScheduledExecutorService.shutdownNow();
mScheduledExecutorService = null;
mFrequencyCorrectionController = null;
mAudioPacketBroadcaster.dispose();
@@ -432,9 +438,11 @@ public class ProcessingChain implements IChannelEventListener
* of the decoder state's */
if( mSource instanceof TunerChannelSource )
{
TunerChannelSource tunerChannelSource = (TunerChannelSource)mSource;
try
{
long frequency = ((TunerChannelSource)mSource).getFrequency();
long frequency = tunerChannelSource.getFrequency();
mDecoderStateEventBroadcaster.broadcast(
new DecoderStateEvent( this, Event.SOURCE_FREQUENCY,
@@ -444,6 +452,8 @@ public class ProcessingChain implements IChannelEventListener
{
mLog.error( "Error getting frequency from tuner channel source", e );
}
tunerChannelSource.start( mScheduledExecutorService );
}
}
else

View File

@@ -91,6 +91,15 @@ public class TrafficChannelManager extends Module
@Override
public void dispose()
{
mLog.debug( "dispose() on traffic channel manager" );
for( Channel trafficChannel: mTrafficChannelPool )
{
trafficChannel.setEnabled( false );
trafficChannel.dispose();
}
mTrafficChannelPool.clear();
mCallEventListener = null;
mResourceManager = null;
mDecodeConfiguration = null;