Skip to content

Commit

Permalink
Improve performance of NetworkSession.SendBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
FlaggAC committed Jul 25, 2024
1 parent 7c90c0c commit 9fac991
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Source/ACE.Server/Network/NetworkBundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal class NetworkBundle
private bool propChanged;

public bool NeedsSending => propChanged || messages.Count > 0;

public int MessageCount => messages.Count;
public bool HasMoreMessages => messages.Count > 0;

private Queue<GameMessage> messages = new Queue<GameMessage>();
Expand Down
89 changes: 55 additions & 34 deletions Source/ACE.Server/Network/NetworkSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -809,39 +809,52 @@ private void SendBundle(NetworkBundle bundle, GameMessageGroup group)
{
packetLog.DebugFormat("[{0}] Sending Bundle", session.LoggingIdentifier);

bool writeOptionalHeaders = true;

List<MessageFragment> fragments = new List<MessageFragment>();

// Pull all messages out and create MessageFragment objects
while (bundle.HasMoreMessages)
{
var message = bundle.Dequeue();
var totalFragments = bundle.MessageCount;
var fragments = new MessageFragment[totalFragments];
for (int i = 0; i < totalFragments; i++)
fragments[i] = new MessageFragment(bundle.Dequeue(), ConnectionData.FragmentSequence++);

var fragment = new MessageFragment(message, ConnectionData.FragmentSequence++);
fragments.Add(fragment);
}
packetLog.DebugFormat("[{0}] Bundle Fragment Count: {1}", session.LoggingIdentifier, totalFragments);

packetLog.DebugFormat("[{0}] Bundle Fragment Count: {1}", session.LoggingIdentifier, fragments.Count);
var hdrSize = PacketFragmentHeader.HeaderSize;
int processedCount = 0;
int lowerBoundIdx = 0;
int seekIdx = 0;
bool writeOptionalHeaders = true;

// Loop through while we have fragements
while (fragments.Count > 0 || writeOptionalHeaders)
while (processedCount < totalFragments || writeOptionalHeaders)
{
if (isReleased)
return;

ServerPacket packet = new ServerPacket();
PacketHeader packetHeader = packet.Header;

if (fragments.Count > 0)
if (processedCount < totalFragments)
packetHeader.Flags |= PacketHeaderFlags.BlobFragments;

if (bundle.EncryptedChecksum)
packetHeader.Flags |= PacketHeaderFlags.EncryptedChecksum;

int availableSpace = ServerPacket.MaxPacketSize;
seekIdx = lowerBoundIdx;

// Pull first message and see if it is a large one
var firstMessage = fragments.FirstOrDefault();
MessageFragment firstMessage = null;
while (seekIdx < totalFragments)
{
firstMessage = fragments[seekIdx];
if (firstMessage != null)
break;
seekIdx++;
lowerBoundIdx++;
}

if (firstMessage != null)
{
int availableSpace = ServerPacket.MaxPacketSize;

// If a large message send only this one, filling the whole packet
if (firstMessage.DataRemaining >= availableSpace)
{
Expand All @@ -850,7 +863,11 @@ private void SendBundle(NetworkBundle bundle, GameMessageGroup group)
packet.Fragments.Add(spf);
availableSpace -= spf.Length;
if (firstMessage.DataRemaining <= 0)
fragments.Remove(firstMessage);
{
processedCount++;
lowerBoundIdx++;
fragments[seekIdx++] = null;
}
}
// Otherwise we'll write any optional headers and process any small messages that will fit
else
Expand All @@ -863,23 +880,28 @@ private void SendBundle(NetworkBundle bundle, GameMessageGroup group)
availableSpace -= (int)packet.Data.Length;
}

// Create a list to remove completed messages after iterator
List<MessageFragment> removeList = new List<MessageFragment>();

foreach (MessageFragment fragment in fragments)
while (seekIdx < totalFragments)
{
var fragment = fragments[seekIdx];
if (fragment == null)
{
seekIdx++;
continue;
}

bool fragmentSkipped = false;


// Is this a large fragment and does it have a tail that needs sending?
if (!fragment.TailSent && availableSpace >= fragment.TailSize)
if (availableSpace >= hdrSize && !fragment.TailSent && availableSpace >= fragment.TailSize)
{
packetLog.DebugFormat("[{0}] Sending tail fragment", session.LoggingIdentifier);
ServerPacketFragment spf = fragment.GetTailFragment();
packet.Fragments.Add(spf);
availableSpace -= spf.Length;
}
// Otherwise will this message fit in the remaining space?
else if (availableSpace >= fragment.NextSize)
else if (availableSpace >= hdrSize && availableSpace >= fragment.NextSize)
{
packetLog.DebugFormat("[{0}] Sending small message", session.LoggingIdentifier);
ServerPacketFragment spf = fragment.GetNextFragment();
Expand All @@ -891,28 +913,27 @@ private void SendBundle(NetworkBundle bundle, GameMessageGroup group)

// If message is out of data, set to remove it
if (fragment.DataRemaining <= 0)
removeList.Add(fragment);
{
processedCount++;
if (seekIdx == lowerBoundIdx)
lowerBoundIdx++;
fragments[seekIdx] = null;
}

// UIQueue messages must go out in order. Otherwise, you might see an NPC's tells in an order that doesn't match their defined emotes.
if (fragmentSkipped && group == GameMessageGroup.UIQueue)
break;
}

// Remove all completed messages
fragments.RemoveAll(x => removeList.Contains(x));
seekIdx++;
}
}
}
// If no messages, write optional headers
else
else if (writeOptionalHeaders)
{
packetLog.DebugFormat("[{0}] No messages, just sending optional headers", session.LoggingIdentifier);
if (writeOptionalHeaders)
{
writeOptionalHeaders = false;
WriteOptionalHeaders(bundle, packet);
if (packet.Data != null)
availableSpace -= (int)packet.Data.Length;
}
writeOptionalHeaders = false;
WriteOptionalHeaders(bundle, packet);
}
EnqueueSend(packet);
}
Expand Down

0 comments on commit 9fac991

Please sign in to comment.