Skip to content

Commit a5b0da1

Browse files
Merge pull request #181 from lahma/faster-invoke
Reduce allocations in ImageSharpMiddleware.Invoke for common case
2 parents 11caa09 + 86568cd commit a5b0da1

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

src/ImageSharp.Web/Middleware/ImageSharpMiddleware.cs

Lines changed: 27 additions & 7 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;
@@ -161,7 +160,7 @@ public ImageSharpMiddleware(
161160
? CultureInfo.InvariantCulture
162161
: CultureInfo.CurrentCulture;
163162

164-
var commands = new HashSet<string>();
163+
var commands = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
165164
foreach (IImageWebProcessor processor in this.processors)
166165
{
167166
foreach (string command in processor.Commands)
@@ -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
{
194-
if (!this.knownCommands.Contains(command, StringComparer.OrdinalIgnoreCase))
197+
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 (int 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
{

tests/ImageSharp.Web.Tests/Processing/PhysicalFileSystemCacheServerTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ namespace SixLabors.ImageSharp.Web.Tests.Processing
1616
public class PhysicalFileSystemCacheServerTests : ServerTestBase<PhysicalFileSystemCacheTestServerFixture>
1717
{
1818
private const int Width = 20;
19-
private static readonly string Command = "?width=" + Width + "&v=" + Guid.NewGuid().ToString();
20-
private static readonly string Command2 = "?width=" + (Width + 1) + "&v=" + Guid.NewGuid().ToString();
19+
private static readonly string Command = "?invalidcommand=qwerty&width=" + Width + "&v=" + Guid.NewGuid().ToString();
20+
private static readonly string Command2 = "?invalidcommand=qwerty&width=" + (Width + 1) + "&v=" + Guid.NewGuid().ToString();
2121

2222
public PhysicalFileSystemCacheServerTests(PhysicalFileSystemCacheTestServerFixture fixture)
2323
: base(fixture)

0 commit comments

Comments
 (0)