Optimizing TagBuilder.CreateSanitizedId to create buffer only when needed.

- Tested with a page containing 33% of invalid Ids which go through TagBuilder.CreateSanitizedId.
- Ran 10,000 requests with 20 in parallel and measured perf.
- Data before the change:
System.String allocated by CreateSanitizedId: 1.84 mb
System.Text.StringBuilder allocated by CreateSanitizedId: 1.68 mb
- Data after the change:
System.String allocated by CreateSanitizedId: 0.720 mb
System.Text.StringBuilder allocated by CreateSanitizedId: 0.560 mb

Around 60% improvement from the original case.
This commit is contained in:
sornaks 2015-06-29 16:47:59 -07:00
parent 4b18bfb494
commit 57f1ae755f
2 changed files with 39 additions and 2 deletions

View File

@ -77,16 +77,40 @@ namespace Microsoft.AspNet.Mvc.Rendering
return string.Empty;
}
// If there are no invalid characters in the string, then we don't have to create the buffer.
var firstIndexOfInvalidCharacter = 1;
for (; firstIndexOfInvalidCharacter < name.Length; firstIndexOfInvalidCharacter++)
{
if (!Html401IdUtil.IsValidIdCharacter(name[firstIndexOfInvalidCharacter]))
{
break;
}
}
var firstChar = name[0];
if (!Html401IdUtil.IsAsciiLetter(firstChar))
var startsWithAsciiLetter = Html401IdUtil.IsAsciiLetter(firstChar);
if (!startsWithAsciiLetter)
{
// The first character must be a letter according to the HTML 4.01 specification.
firstChar = 'z';
}
if (firstIndexOfInvalidCharacter == name.Length && startsWithAsciiLetter)
{
return name;
}
var stringBuffer = new StringBuilder(name.Length);
stringBuffer.Append(firstChar);
for (var index = 1; index < name.Length; index++)
// Characters until 'firstIndexOfInvalidCharacter' have already been checked for validity.
// So just copying them. This avoids running them through Html401IdUtil.IsValidIdCharacter again.
for (var index = 1; index < firstIndexOfInvalidCharacter; index++)
{
stringBuffer.Append(name[index]);
}
for (var index = firstIndexOfInvalidCharacter; index < name.Length; index++)
{
var thisChar = name[index];
if (Html401IdUtil.IsValidIdCharacter(thisChar))

View File

@ -116,5 +116,18 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
// Assert
Assert.Equal("HtmlEncode[[TestValue]]", tagBuilder.InnerHtml);
}
[Theory]
[InlineData("HelloWorld", "HelloWorld")]
[InlineData("¡HelloWorld", "zHelloWorld")]
[InlineData("Hello¡World", "Hello-World")]
public void CreateSanitizedIdCreatesId(string input, string output)
{
// Arrange
var result = TagBuilder.CreateSanitizedId(input, "-");
// Assert
Assert.Equal(output, result);
}
}
}