Improve .NET 9.0+ locking performance (#3216)

This commit is contained in:
Mark Cilia Vincenti
2025-12-30 20:08:44 +01:00
committed by GitHub
parent fd6e3ad8df
commit 4e95dd7123
14 changed files with 31 additions and 16 deletions

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
namespace Discord.Commands
{
@@ -11,7 +12,7 @@ namespace Discord.Commands
private readonly ConcurrentDictionary<string, CommandMapNode> _nodes;
private readonly string _name;
private readonly object _lockObj = new object();
private readonly Lock _lockObj = new();
private ImmutableArray<CommandInfo> _commands;
public bool IsEmpty => _commands.Length == 0 && _nodes.Count == 0;

View File

@@ -19,5 +19,9 @@
<PackageReference Include="IDisposableAnalyzers" Version="4.0.8">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net9.0'))" Include="Backport.System.Threading.Lock" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

View File

@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Model = Discord.API.Interaction;
@@ -32,7 +33,7 @@ namespace Discord.Rest
/// </summary>
internal new RestCommandBaseData Data { get; private set; }
private object _lock = new object();
private readonly Lock _lock = new();
internal RestCommandBase(DiscordRestClient client, Model model)
: base(client, model.Id)

View File

@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DataModel = Discord.API.MessageComponentInteractionData;
using Model = Discord.API.Interaction;
@@ -24,7 +25,7 @@ namespace Discord.Rest
/// <inheritdoc cref="IComponentInteraction.Message"/>
public RestUserMessage Message { get; private set; }
private object _lock = new object();
private readonly Lock _lock = new();
internal RestMessageComponent(BaseDiscordClient client, Model model)
: base(client, model.Id)

View File

@@ -7,6 +7,7 @@ using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using DataModel = Discord.API.ModalInteractionData;
@@ -41,7 +42,7 @@ namespace Discord.Rest
return entity;
}
private object _lock = new object();
private readonly Lock _lock = new();
/// <summary>
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredUpdateMessage"/> if the modal was created

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DataModel = Discord.API.AutocompleteInteractionData;
using Model = Discord.API.Interaction;
@@ -19,7 +20,7 @@ namespace Discord.Rest
/// </summary>
public new RestAutocompleteInteractionData Data { get; }
private object _lock = new object();
private readonly Lock _lock = new();
internal RestAutocompleteInteraction(DiscordRestClient client, Model model)
: base(client, model.Id)

View File

@@ -17,7 +17,7 @@ namespace Discord.Net.Queue
{
private const int MinimumSleepTimeMs = 750;
private readonly object _lock;
private readonly Lock _lock;
private readonly RequestQueue _queue;
private int _semaphore;
private DateTimeOffset? _resetTick;
@@ -32,7 +32,7 @@ namespace Discord.Net.Queue
_queue = queue;
Id = id;
_lock = new object();
_lock = new();
if (request.Options.IsClientBucket)
WindowCount = ClientBucket.Get(request.Options.BucketId).WindowCount;

View File

@@ -21,7 +21,7 @@ namespace Discord.WebSocket
private ImmutableArray<StickerPack<SocketSticker>> _defaultStickers;
private int _totalShards;
private SemaphoreSlim[] _identifySemaphores;
private object _semaphoreResetLock;
private readonly Lock _semaphoreResetLock;
private Task _semaphoreResetTask;
private bool _isDisposed;
@@ -80,7 +80,7 @@ namespace Discord.WebSocket
if (ids != null && config.TotalShards == null)
throw new ArgumentException($"Custom ids are not supported when {nameof(config.TotalShards)} is not specified.");
_semaphoreResetLock = new object();
_semaphoreResetLock = new();
_shardIdsToIndex = new Dictionary<int, int>();
config.DisplayInitialLog = false;
_baseConfig = config;

View File

@@ -6,6 +6,7 @@ using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Model = Discord.API.Channel;
using ThreadMember = Discord.API.ThreadMember;
@@ -110,8 +111,8 @@ namespace Discord.WebSocket
private bool _usersDownloaded;
private readonly object _downloadLock = new object();
private readonly object _ownerLock = new object();
private readonly Lock _downloadLock = new();
private readonly Lock _ownerLock = new();
private ulong _ownerId;

View File

@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DataModel = Discord.API.MessageComponentInteractionData;
using Model = Discord.API.Interaction;
@@ -24,7 +25,7 @@ namespace Discord.WebSocket
/// <inheritdoc cref="IComponentInteraction.Message"/>
public SocketUserMessage Message { get; private set; }
private object _lock = new object();
private readonly Lock _lock = new();
public override bool HasResponded { get; internal set; } = false;
internal SocketMessageComponent(DiscordSocketClient client, Model model, ISocketMessageChannel channel, SocketUser user)

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using DataModel = Discord.API.ModalInteractionData;
@@ -66,7 +67,7 @@ namespace Discord.WebSocket
/// <inheritdoc/>
public override bool HasResponded { get; internal set; }
private object _lock = new object();
private readonly Lock _lock = new();
/// <inheritdoc/>
public override async Task RespondWithFilesAsync(

View File

@@ -2,6 +2,7 @@ using Discord.Rest;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using DataModel = Discord.API.AutocompleteInteractionData;
using Model = Discord.API.Interaction;
@@ -21,7 +22,7 @@ namespace Discord.WebSocket
/// <inheritdoc/>
public override bool HasResponded { get; internal set; }
private object _lock = new object();
private readonly Lock _lock = new();
internal SocketAutocompleteInteraction(DiscordSocketClient client, Model model, ISocketMessageChannel channel, SocketUser user)
: base(client, model.Id, channel, user)

View File

@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DataModel = Discord.API.ApplicationCommandInteractionData;
using Model = Discord.API.Interaction;
@@ -35,7 +36,7 @@ namespace Discord.WebSocket
/// <inheritdoc/>
public override bool HasResponded { get; internal set; }
private object _lock = new object();
private readonly Lock _lock = new();
internal SocketCommandBase(DiscordSocketClient client, Model model, ISocketMessageChannel channel, SocketUser user)
: base(client, model.Id, channel, user)

View File

@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Model = Discord.API.User;
namespace Discord.WebSocket
@@ -31,7 +32,7 @@ namespace Discord.WebSocket
/// <inheritdoc />
internal override SocketGlobalUser GlobalUser { get => this; set => throw new NotImplementedException(); }
private readonly object _lockObj = new object();
private readonly Lock _lockObj = new();
private ushort _references;
private SocketGlobalUser(DiscordSocketClient discord, ulong id)