Skip to content

Commit f65650d

Browse files
committed
Reduce allocations in ImageSharpMiddleware.Invoke
* remove virtual dispatch and enumeration allocations for common path in ImageSharpMiddleware.Invoke
1 parent 52bcb16 commit f65650d

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

src/ImageSharp.Web/Middleware/ImageSharpMiddleware.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using System.IO;
1010
using System.Linq;
1111
using System.Text;
12-
using System.Threading;
1312
using System.Threading.Tasks;
1413
using Microsoft.AspNetCore.Http;
1514
using Microsoft.Extensions.Logging;
@@ -185,16 +184,24 @@ public ImageSharpMiddleware(
185184
public async Task Invoke(HttpContext context)
186185
#pragma warning restore IDE1006 // Naming Styles
187186
{
188-
IDictionary<string, string> commands = this.requestParser.ParseRequestCommands(context);
187+
// We expect to get concrete collection type which removes virtual dispatch concerns and enumerator allocations
188+
IDictionary<string, string> parsedCommands = this.requestParser.ParseRequestCommands(context);
189+
Dictionary<string, string> commands = parsedCommands as Dictionary<string, string> ?? new Dictionary<string, string>(parsedCommands, StringComparer.OrdinalIgnoreCase);
190+
189191
if (commands.Count > 0)
190192
{
191-
// Strip out any unknown commands.
192-
foreach (string command in new List<string>(commands.Keys))
193+
// Strip out any unknown commands, if needed.
194+
int index = 0;
195+
foreach (string command in commands.Keys)
193196
{
194197
if (!this.knownCommands.Contains(command))
195198
{
196-
commands.Remove(command);
199+
// Need to actually remove, allocates new list to allow modifications
200+
this.StripUnknownCommands(commands, startAtIndex: index);
201+
break;
197202
}
203+
204+
++index;
198205
}
199206
}
200207

@@ -239,6 +246,19 @@ await this.ProcessRequestAsync(
239246
commands);
240247
}
241248

249+
private void StripUnknownCommands(Dictionary<string, string> commands, int startAtIndex)
250+
{
251+
var keys = new List<string>(commands.Keys);
252+
for (var index = startAtIndex; index < keys.Count; index++)
253+
{
254+
string command = keys[index];
255+
if (!this.knownCommands.Contains(command))
256+
{
257+
commands.Remove(command);
258+
}
259+
}
260+
}
261+
242262
private async Task ProcessRequestAsync(
243263
HttpContext context,
244264
IImageResolver sourceImageResolver,

tests/ImageSharp.Web.Tests/Commands/PresetOnlyQueryCollectionRequestParserTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ public void PresetOnlyQueryCollectionRequestParserExtractsCommandsWithOtherCasin
5454
Assert.Equal(expected, actual);
5555
}
5656

57-
5857
[Fact]
5958
public void PresetOnlyQueryCollectionRequestParserCommandsWithoutPresetParam()
6059
{

0 commit comments

Comments
 (0)