Skip to content

Commit

Permalink
Performance improvements (#746)
Browse files Browse the repository at this point in the history
* Misc minor performance improvements

* Use more concise loop syntax

* Use more concise Collection sort syntax

* Use StringUtils pad methods

* Optimize some loops and double-map-lookups

* Optimize array instantiation

There are two styles to convert a collection to an array: either
using a pre-sized array (like c.toArray(new String[c.size()])) or
using an empty array (like c.toArray(new String[0]).

In older Java versions using pre-sized array was recommended,
as the reflection call which is necessary to create an array
of proper size was quite slow. However since late updates of
OpenJDK 6 this call was intrinsified, making the performance
of the empty array version the same and sometimes even better,
compared to the pre-sized version. Also passing pre-sized array
is dangerous for a concurrent or synchronized collection as
a data race is possible between the size and toArray call
which may result in extra nulls at the end of the array,
if the collection was concurrently shrunk during the operation.

* Cleanup string concatenation

* Use EnumMap where possible

* Use FastMath instead of Math

* Initialize complex things only once

* Reduce method size to aloow more JIT inlining

* remove map of short->float

* Move field to local variable

* Cleanup Map lookup

Co-authored-by: Rob Ekl <[email protected]>
  • Loading branch information
robekl and robekl-z authored Apr 25, 2020
1 parent 649258b commit 39f6d6c
Show file tree
Hide file tree
Showing 186 changed files with 2,855 additions and 3,479 deletions.
44 changes: 16 additions & 28 deletions src/main/java/io/github/dsheirer/alias/AliasList.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.*;

/**
* List of aliases that share the same alias list name and provides convenient methods for looking up alias
Expand All @@ -60,8 +54,8 @@
public class AliasList implements Listener<AliasEvent>
{
private final static Logger mLog = LoggerFactory.getLogger(AliasList.class);
private Map<Protocol,TalkgroupAliasList> mTalkgroupProtocolMap = new HashMap<>();
private Map<Protocol,RadioAliasList> mRadioProtocolMap = new HashMap<>();
private Map<Protocol,TalkgroupAliasList> mTalkgroupProtocolMap = new EnumMap<>(Protocol.class);
private Map<Protocol,RadioAliasList> mRadioProtocolMap = new EnumMap<>(Protocol.class);
private Map<String,Alias> mESNMap = new HashMap<>();
private Map<Integer,Alias> mStatusMap = new HashMap<>();
private boolean mHasAliasActions = false;
Expand Down Expand Up @@ -487,15 +481,7 @@ public List<BroadcastChannel> getBroadcastChannels(IdentifierCollection identifi
*/
public static void remove(Alias alias, Map map)
{
Iterator<Map.Entry> it = map.entrySet().iterator();

while(it.hasNext())
{
if(it.next().getValue().equals(alias))
{
it.remove();
}
}
map.entrySet().removeIf(entry -> alias.equals(((Map.Entry)entry).getValue()));
}


Expand All @@ -515,16 +501,17 @@ public Alias getAlias(TalkgroupIdentifier identifier)
{
int value = identifier.getValue();

if(mTalkgroupAliasMap.containsKey(value))
Alias mapValue = mTalkgroupAliasMap.get(value);
if (mapValue != null)
{
return mTalkgroupAliasMap.get(value);
return mapValue;
}

for(TalkgroupRange talkgroupRange: mTalkgroupRangeAliasMap.keySet())
for(Map.Entry<TalkgroupRange, Alias> entry : mTalkgroupRangeAliasMap.entrySet())
{
if(talkgroupRange.contains(value))
if(entry.getKey().contains(value))
{
return mTalkgroupRangeAliasMap.get(talkgroupRange);
return entry.getValue();
}
}

Expand Down Expand Up @@ -601,16 +588,17 @@ public Alias getAlias(RadioIdentifier identifier)
{
int value = identifier.getValue();

if(mRadioAliasMap.containsKey(value))
Alias mapValue = mRadioAliasMap.get(value);
if(mapValue != null)
{
return mRadioAliasMap.get(value);
return mapValue;
}

for(RadioRange radioRange: mRadioRangeAliasMap.keySet())
for(Map.Entry<RadioRange, Alias> entry : mRadioRangeAliasMap.entrySet())
{
if(radioRange.contains(value))
if(entry.getKey().contains(value))
{
return mRadioRangeAliasMap.get(radioRange);
return entry.getValue();
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/io/github/dsheirer/alias/AliasModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ public AliasList getAliasList(String name)
return new AliasList(name);
}

if(mAliasListMap.containsKey(name))
{
return mAliasListMap.get(name);
AliasList mapValue = mAliasListMap.get(name);
if (mapValue != null) {
return mapValue;
}

AliasList aliasList = new AliasList(name);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/io/github/dsheirer/alias/AliasNameEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public void actionPerformed(ActionEvent e)
else
{
mGroupCombo.setModel(new DefaultComboBoxModel<String>(
groups.toArray(new String[groups.size()])));
groups.toArray(new String[0])));
;
}
}
Expand Down Expand Up @@ -243,7 +243,7 @@ public void setItem(Alias alias)
else
{
mListCombo.setModel(new DefaultComboBoxModel<String>(
listNames.toArray(new String[listNames.size()])));
listNames.toArray(new String[0])));
;
}

Expand All @@ -258,7 +258,7 @@ public void setItem(Alias alias)
else
{
mGroupCombo.setModel(new DefaultComboBoxModel<String>(
groupNames.toArray(new String[groupNames.size()])));
groupNames.toArray(new String[0])));
;
}

Expand Down
10 changes: 5 additions & 5 deletions src/main/java/io/github/dsheirer/alias/MultipleAliasEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,15 @@ public void setItem(List<Alias> item)
List<String> listNames = mAliasModel.getListNames();
listNames.add(0, "");
mListCombo.setModel(new DefaultComboBoxModel<String>(
listNames.toArray(new String[listNames.size()])));
listNames.toArray(new String[0])));

List<String> groupNames = mAliasModel.getGroupNames();
groupNames.add(0, "");
mGroupCombo.setModel(new DefaultComboBoxModel<String>(
groupNames.toArray(new String[groupNames.size()])));
groupNames.toArray(new String[0])));

List<String> streamNames = mBroadcastModel.getBroadcastConfigurationNames();
mStreamCombo.setModel(new DefaultComboBoxModel<String>(streamNames.toArray(new String[streamNames.size()])));
mStreamCombo.setModel(new DefaultComboBoxModel<String>(streamNames.toArray(new String[0])));

mIconCombo.setModel(new DefaultComboBoxModel<>(mIconManager.getIcons()));

Expand All @@ -300,12 +300,12 @@ public void reset()
List<String> listNames = mAliasModel.getListNames();
listNames.add(0, "");
mListCombo.setModel(new DefaultComboBoxModel<String>(
listNames.toArray(new String[listNames.size()])));
listNames.toArray(new String[0])));

List<String> groupNames = mAliasModel.getGroupNames();
groupNames.add(0, "");
mGroupCombo.setModel(new DefaultComboBoxModel<String>(
groupNames.toArray(new String[groupNames.size()])));
groupNames.toArray(new String[0])));

mButtonColor.setForeground(getForeground());
mButtonColor.setBackground(getBackground());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,7 @@ public void setItem( Alias alias )

List<AliasAction> actions = alias.getAction();

Collections.sort( actions, new Comparator<AliasAction>()
{
@Override
public int compare( AliasAction o1, AliasAction o2 )
{
return o1.toString().compareTo( o2.toString() );
}
} );
actions.sort(Comparator.comparing(Object::toString));

for( AliasAction action: actions )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,7 @@ public void setItem(Alias alias)

List<AliasID> ids = alias.getId();

Collections.sort(ids, new Comparator<AliasID>()
{
@Override
public int compare(AliasID o1, AliasID o2)
{
return o1.toString().compareTo(o2.toString());
}
});
ids.sort(Comparator.comparing(Object::toString));

for(AliasID id : ids)
{
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/io/github/dsheirer/alias/id/WildcardID.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package io.github.dsheirer.alias.id;

import org.apache.commons.lang3.Validate;
import org.apache.commons.math3.util.FastMath;

import java.util.regex.Pattern;

Expand Down Expand Up @@ -95,12 +96,12 @@ private int calculateWeight()
{
if(mValue.substring(x, x + 1).equals(WILDCARD))
{
weight += (int)(Math.pow(2, mValue.length() - x - 1)); //Position weight
weight += (int)(FastMath.pow(2, mValue.length() - x - 1)); //Position weight
characterCount++;
}
}

weight += (int)(Math.pow(2, characterCount)) * 1000; //Character count weight
weight += (int)(FastMath.pow(2, characterCount)) * 1000; //Character count weight

return weight;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private void initGUI()

List<String> channelNames = mBroadcastModel.getBroadcastConfigurationNames();

mBroadcastConfigurations = new JComboBox<String>(channelNames.toArray(new String[channelNames.size()]));
mBroadcastConfigurations = new JComboBox<String>(channelNames.toArray(new String[0]));
mBroadcastConfigurations.addActionListener(new ActionListener()
{
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -38,7 +39,7 @@
public class RadioFormatter
{
private final static Logger mLog = LoggerFactory.getLogger(RadioFormatter.class);
private static Map<Protocol,IntegerFormatter> mFormatterMap = new HashMap<>();
private static Map<Protocol,IntegerFormatter> mFormatterMap = new EnumMap<>(Protocol.class);

static
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -41,7 +42,7 @@
public class TalkgroupFormatter
{
private final static Logger mLog = LoggerFactory.getLogger(TalkgroupFormatter.class);
private static Map<Protocol,IntegerFormatter> mFormatterMap = new HashMap<>();
private static Map<Protocol,IntegerFormatter> mFormatterMap = new EnumMap<>(Protocol.class);

static
{
Expand Down
5 changes: 1 addition & 4 deletions src/main/java/io/github/dsheirer/audio/AudioSegment.java
Original file line number Diff line number Diff line change
Expand Up @@ -384,10 +384,7 @@ public void addIdentifier(Identifier identifier)
}

//Add all broadcast channels for the alias ... let the set handle duplication.
for(BroadcastChannel broadcastChannel: alias.getBroadcastChannels())
{
mBroadcastChannels.add(broadcastChannel);
}
mBroadcastChannels.addAll(alias.getBroadcastChannels());

//Only assign a playback priority if it is lower priority than the current setting.
int playbackPriority = alias.getPlaybackPriority();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.github.dsheirer.identifier.IdentifierCollection;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.util.ThreadPool;
import org.apache.commons.math3.util.FastMath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -360,7 +361,7 @@ public void run()
//Trim length to whole-frame intervals (144 byte frame)
bytesToStream -= (bytesToStream % 144);

int length = Math.min(bytesToStream, mInputStream.available());
int length = FastMath.min(bytesToStream, mInputStream.available());

byte[] audio = new byte[length];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public void run()
mLog.info("RR User:" + userInfo.getUserName() + " Expiration Date:" + userInfo.getExpirationDate());
List<UserFeedBroadcast> feeds = service.getUserFeeds();

mUserFeedBroadcastList.setListData(feeds.toArray(new UserFeedBroadcast[feeds.size()]));
mUserFeedBroadcastList.setListData(feeds.toArray(new UserFeedBroadcast[0]));
}
catch(RadioReferenceException rre)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import io.github.dsheirer.identifier.Role;
import io.github.dsheirer.properties.SystemProperties;
import io.github.dsheirer.util.ThreadPool;
import org.apache.commons.math3.util.FastMath;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
Expand Down Expand Up @@ -363,7 +364,7 @@ private List<UltravoxMessage> getMetadataMessages(IdentifierCollection identifie

int pointer = 0;
int messageCounter = 1;
int messageCount = (int) Math.ceil((double) xml.length / (double) (mMaxPayloadSize - 6));
int messageCount = (int) FastMath.ceil((double) xml.length / (double) (mMaxPayloadSize - 6));

if(messageCount > 32)
{
Expand All @@ -375,7 +376,7 @@ private List<UltravoxMessage> getMetadataMessages(IdentifierCollection identifie

while(pointer < xml.length && messageCounter <= messageCount)
{
int payloadSize = Math.min(mMaxPayloadSize - 6, xml.length - pointer);
int payloadSize = FastMath.min(mMaxPayloadSize - 6, xml.length - pointer);

byte[] payload = new byte[payloadSize + 6];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import net.sourceforge.lame.lowlevel.LameEncoder;
import net.sourceforge.lame.mp3.Lame;
import net.sourceforge.lame.mp3.MPEGMode;
import org.apache.commons.math3.util.FastMath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -59,7 +60,7 @@ public byte[] convert(List<float[]> audioPackets)

byte[] pcmBytes = AudioUtils.convertTo16BitSamples(audioPackets);

int pcmBufferSize = Math.min(mMP3Buffer.length, pcmBytes.length);
int pcmBufferSize = FastMath.min(mMP3Buffer.length, pcmBytes.length);

int mp3BufferSize = 0;

Expand All @@ -70,7 +71,7 @@ public byte[] convert(List<float[]> audioPackets)
while (0 < (mp3BufferSize = mEncoder.encodeBuffer(pcmBytes, pcmBytesPosition, pcmBufferSize, mMP3Buffer)))
{
pcmBytesPosition += pcmBufferSize;
pcmBufferSize = Math.min(mMP3Buffer.length, pcmBytes.length - pcmBytesPosition);
pcmBufferSize = FastMath.min(mMP3Buffer.length, pcmBytes.length - pcmBytesPosition);
mMP3Stream.write(mMP3Buffer, 0, mp3BufferSize);
}

Expand All @@ -89,7 +90,7 @@ public byte[] convertAudio(List<float[]> audioBuffers)

byte[] pcmBytes = AudioUtils.convert(audioBuffers);

int pcmBufferSize = Math.min(mMP3Buffer.length, pcmBytes.length);
int pcmBufferSize = FastMath.min(mMP3Buffer.length, pcmBytes.length);

int mp3BufferSize = 0;

Expand All @@ -100,7 +101,7 @@ public byte[] convertAudio(List<float[]> audioBuffers)
while (0 < (mp3BufferSize = mEncoder.encodeBuffer(pcmBytes, pcmBytesPosition, pcmBufferSize, mMP3Buffer)))
{
pcmBytesPosition += pcmBufferSize;
pcmBufferSize = Math.min(mMP3Buffer.length, pcmBytes.length - pcmBytesPosition);
pcmBufferSize = FastMath.min(mMP3Buffer.length, pcmBytes.length - pcmBytesPosition);
mMP3Stream.write(mMP3Buffer, 0, mp3BufferSize);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ else if(audioSegment.isLinked())
//Sort audio segments by playback priority and assign to empty audio outputs
if(!mAudioSegments.isEmpty())
{
Collections.sort(mAudioSegments, Comparator.comparingInt(o -> o.monitorPriorityProperty().get()));
mAudioSegments.sort(Comparator.comparingInt(o -> o.monitorPriorityProperty().get()));

//Assign empty audio outputs first
for(AudioOutput audioOutput: mAudioOutputs)
Expand Down Expand Up @@ -347,14 +347,7 @@ public List<AudioOutput> getAudioOutputs()
{
List<AudioOutput> outputs = new ArrayList<>(mAudioOutputs);

Collections.sort(outputs, new Comparator<AudioOutput>()
{
@Override
public int compare(AudioOutput first, AudioOutput second)
{
return first.getChannelName().compareTo(second.getChannelName());
}
});
outputs.sort(Comparator.comparing(AudioOutput::getChannelName));

return outputs;
}
Expand Down
Loading

0 comments on commit 39f6d6c

Please sign in to comment.