Improve perf of TryGetAsciiString

This commit is contained in:
moozzyk 2016-06-01 16:17:56 -07:00
parent 9667907515
commit 6e46d9757d
1 changed files with 41 additions and 42 deletions

View File

@ -8,73 +8,72 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure
public static unsafe bool TryGetAsciiString(byte* input, char* output, int count) public static unsafe bool TryGetAsciiString(byte* input, char* output, int count)
{ {
var i = 0; var i = 0;
int orValue = 0; sbyte* signedInput = (sbyte*)input;
bool hasZero = false;
bool isValid = true;
while (i < count - 11) while (i < count - 11)
{ {
orValue |= *input | *(input + 1) | *(input + 2) | *(input + 3) | *(input + 4) | *(input + 5) | isValid = isValid && *signedInput > 0 && *(signedInput + 1) > 0 && *(signedInput + 2) > 0 &&
*(input + 6) | *(input + 7) | *(input + 8) | *(input + 9) | *(input + 10) | *(input + 11); *(signedInput + 3) > 0 && *(signedInput + 4) > 0 && *(signedInput + 5) > 0 && *(signedInput + 6) > 0 &&
hasZero = hasZero || *input == 0 || *(input + 1) == 0 || *(input + 2) == 0 || *(input + 3) == 0 || *(signedInput + 7) > 0 && *(signedInput + 8) > 0 && *(signedInput + 9) > 0 && *(signedInput + 10) > 0 &&
*(input + 4) == 0 || *(input + 5) == 0 || *(input + 6) == 0 || *(input + 7) == 0 || *(signedInput + 11) > 0;
*(input + 8) == 0 || *(input + 9) == 0 || *(input + 10) == 0 || *(input + 11) == 0;
i += 12; i += 12;
*(output) = (char)*(input); *(output) = (char)*(signedInput);
*(output + 1) = (char)*(input + 1); *(output + 1) = (char)*(signedInput + 1);
*(output + 2) = (char)*(input + 2); *(output + 2) = (char)*(signedInput + 2);
*(output + 3) = (char)*(input + 3); *(output + 3) = (char)*(signedInput + 3);
*(output + 4) = (char)*(input + 4); *(output + 4) = (char)*(signedInput + 4);
*(output + 5) = (char)*(input + 5); *(output + 5) = (char)*(signedInput + 5);
*(output + 6) = (char)*(input + 6); *(output + 6) = (char)*(signedInput + 6);
*(output + 7) = (char)*(input + 7); *(output + 7) = (char)*(signedInput + 7);
*(output + 8) = (char)*(input + 8); *(output + 8) = (char)*(signedInput + 8);
*(output + 9) = (char)*(input + 9); *(output + 9) = (char)*(signedInput + 9);
*(output + 10) = (char)*(input + 10); *(output + 10) = (char)*(signedInput + 10);
*(output + 11) = (char)*(input + 11); *(output + 11) = (char)*(signedInput + 11);
output += 12; output += 12;
input += 12; signedInput += 12;
} }
if (i < count - 5) if (i < count - 5)
{ {
orValue |= *input | *(input + 1) | *(input + 2) | *(input + 3) | *(input + 4) | *(input + 5); isValid = isValid && *signedInput > 0 && *(signedInput + 1) > 0 && *(signedInput + 2) > 0 &&
hasZero = hasZero || *input == 0 || *(input + 1) == 0 || *(input + 2) == 0 || *(input + 3) == 0 || *(signedInput + 3) > 0 && *(signedInput + 4) > 0 && *(signedInput + 5) > 0;
*(input + 4) == 0 || *(input + 5) == 0;
i += 6; i += 6;
*(output) = (char)*(input); *(output) = (char)*(signedInput);
*(output + 1) = (char)*(input + 1); *(output + 1) = (char)*(signedInput + 1);
*(output + 2) = (char)*(input + 2); *(output + 2) = (char)*(signedInput + 2);
*(output + 3) = (char)*(input + 3); *(output + 3) = (char)*(signedInput + 3);
*(output + 4) = (char)*(input + 4); *(output + 4) = (char)*(signedInput + 4);
*(output + 5) = (char)*(input + 5); *(output + 5) = (char)*(signedInput + 5);
output += 6; output += 6;
input += 6; signedInput += 6;
} }
if (i < count - 3) if (i < count - 3)
{ {
orValue |= *input | *(input + 1) | *(input + 2) | *(input + 3); isValid = isValid && *signedInput > 0 && *(signedInput + 1) > 0 && *(signedInput + 2) > 0 &&
hasZero = hasZero || *input == 0 || *(input + 1) == 0 || *(input + 2) == 0 || *(input + 3) == 0; *(signedInput + 3) > 0;
i += 4; i += 4;
*(output) = (char)*(input); *(output) = (char)*(signedInput);
*(output + 1) = (char)*(input + 1); *(output + 1) = (char)*(signedInput + 1);
*(output + 2) = (char)*(input + 2); *(output + 2) = (char)*(signedInput + 2);
*(output + 3) = (char)*(input + 3); *(output + 3) = (char)*(signedInput + 3);
output += 4; output += 4;
input += 4; signedInput += 4;
} }
while (i < count) while (i < count)
{ {
orValue |= *input; isValid = isValid && *signedInput > 0;
hasZero = hasZero || *input == 0;
i++; i++;
*output = (char)*input; *output = (char)*signedInput;
output++; output++;
input++; signedInput++;
} }
return (orValue & 0x80) == 0 && !hasZero; return isValid;
} }
} }
} }