java-topology/defects/ryujinx-0001/patch/ryujinx-0001.patch

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;
}