95 lines
4 KiB
Diff
95 lines
4 KiB
Diff
# UNDF: UNDF-2026-000001053
|
|
# UNDF: UNDF-2026-XXXXXXXXX
|
|
--- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocketPollManager.cs
|
|
+++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocketPollManager.cs
|
|
@@ -1,6 +1,6 @@
|
|
using Ryujinx.Common.Logging;
|
|
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
|
|
-using System.Collections.Generic;
|
|
+using System.Collections.Generic;
|
|
using System.Net.Sockets;
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
|
@@ -71,13 +71,19 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
|
try
|
|
{
|
|
int actualTimeoutMicroseconds = timeoutMilliseconds == -1 ? -1 : timeoutMilliseconds * 1000;
|
|
|
|
Socket.Select(readEvents, writeEvents, errorEvents, actualTimeoutMicroseconds);
|
|
}
|
|
catch (SocketException exception)
|
|
{
|
|
return WinSockHelper.ConvertError((WsaError)exception.ErrorCode);
|
|
}
|
|
|
|
+ // Convert to HashSet after Socket.Select() trims each list to ready sockets.
|
|
+ // List.Contains() is O(S) per call; HashSet.Contains() is O(1).
|
|
+ // Without this, the result loop below is O(E * S) where E = event count,
|
|
+ // S = ready-socket count in each list. At E=500 sockets, cost is ~250,000 ops.
|
|
+ HashSet<Socket> readSet = new(readEvents);
|
|
+ HashSet<Socket> writeSet = new(writeEvents);
|
|
+ HashSet<Socket> errorSet = new(errorEvents);
|
|
+
|
|
foreach (PollEvent evnt in events)
|
|
{
|
|
Socket socket = ((ManagedSocket)evnt.FileDescriptor).Socket;
|
|
@@ -85,17 +91,17 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
|
PollEventTypeMask outputEvents = evnt.Data.OutputEvents & ~evnt.Data.InputEvents;
|
|
|
|
- if (errorEvents.Contains(socket))
|
|
+ if (errorSet.Contains(socket))
|
|
{
|
|
outputEvents |= PollEventTypeMask.Error;
|
|
|
|
if (!socket.Connected || !socket.IsBound)
|
|
{
|
|
outputEvents |= PollEventTypeMask.Disconnected;
|
|
}
|
|
}
|
|
|
|
- if (readEvents.Contains(socket))
|
|
+ if (readSet.Contains(socket))
|
|
{
|
|
if ((evnt.Data.InputEvents & PollEventTypeMask.Input) != 0)
|
|
{
|
|
outputEvents |= PollEventTypeMask.Input;
|
|
}
|
|
}
|
|
|
|
- if (writeEvents.Contains(socket))
|
|
+ if (writeSet.Contains(socket))
|
|
{
|
|
outputEvents |= PollEventTypeMask.Output;
|
|
}
|
|
@@ -119,6 +125,11 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
|
|
|
Socket.Select(readEvents, writeEvents, errorEvents, timeout);
|
|
|
|
+ // Same O(E*S) -> O(E+S) fix for Select().
|
|
+ HashSet<Socket> readSet = new(readEvents);
|
|
+ HashSet<Socket> writeSet = new(writeEvents);
|
|
+ HashSet<Socket> errorSet = new(errorEvents);
|
|
+
|
|
updatedCount = readEvents.Count + writeEvents.Count + errorEvents.Count;
|
|
|
|
foreach (PollEvent pollEvent in events)
|
|
@@ -126,15 +137,15 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
|
ManagedSocket socket = (ManagedSocket)pollEvent.FileDescriptor;
|
|
|
|
- if (readEvents.Contains(socket.Socket))
|
|
+ if (readSet.Contains(socket.Socket))
|
|
{
|
|
pollEvent.Data.OutputEvents |= PollEventTypeMask.Input;
|
|
}
|
|
|
|
- if (writeEvents.Contains(socket.Socket))
|
|
+ if (writeSet.Contains(socket.Socket))
|
|
{
|
|
pollEvent.Data.OutputEvents |= PollEventTypeMask.Output;
|
|
}
|
|
|
|
- if (errorEvents.Contains(socket.Socket))
|
|
+ if (errorSet.Contains(socket.Socket))
|
|
{
|
|
pollEvent.Data.OutputEvents |= PollEventTypeMask.Error;
|
|
}
|