-
Notifications
You must be signed in to change notification settings - Fork 550
Perf optimization for Bilibili provider #1071
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, do you have any numbers showing the actual impact of the changes?
src/AspNet.Security.OAuth.Bilibili/BilibiliAuthenticationHandler.cs
Outdated
Show resolved
Hide resolved
src/AspNet.Security.OAuth.Bilibili/BilibiliAuthenticationHandler.cs
Outdated
Show resolved
Hide resolved
src/AspNet.Security.OAuth.Bilibili/BilibiliAuthenticationHandler.cs
Outdated
Show resolved
Hide resolved
src/AspNet.Security.OAuth.Bilibili/BilibiliAuthenticationHandler.cs
Outdated
Show resolved
Hide resolved
src/AspNet.Security.OAuth.Bilibili/BilibiliAuthenticationHandler.cs
Outdated
Show resolved
Hide resolved
src/AspNet.Security.OAuth.Bilibili/BilibiliAuthenticationHandler.cs
Outdated
Show resolved
Hide resolved
|
It is not easy to write a precise microbenchmark. I tested a simplified and somewhat crude version. The result is the following:
The src codes: [MemoryDiagnoser]
public class DictLinqVsSortList
{
private const string ClientId = "Bilibili_Cheers";
private readonly string Timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
[Benchmark(Baseline = true)]
public string DictLinq()
{
Dictionary<string, string> d = new(7)
{
{ "access-token", "1234567890" },
{ "x-bili-accesskeyid", ClientId },
{ "x-bili-content-md5", "d41d8cd98f00b204e9800998ecf8427e" }, // It's a GET request so there's no content, so we send the MD5 hash of an empty string
{ "x-bili-signature-method", "HMAC-SHA256" },
{ "x-bili-signature-nonce", GenerateNonce() },
{ "x-bili-signature-version", "2.0" },
{ "x-bili-timestamp", Timestamp }
};
var headers = d
.Where(h => h.Key.StartsWith("x-bili-", StringComparison.OrdinalIgnoreCase))
.OrderBy(h => h.Key)
.Select(h => $"{h.Key}:{string.Join(",", h.Value)}")
.ToList();
return string.Join('\n', headers);
}
[Benchmark]
public string SortList()
{
SortedList<string, string> s = new(6, StringComparer.OrdinalIgnoreCase)
{
{ "x-bili-accesskeyid", ClientId },
{ "x-bili-content-md5", "d41d8cd98f00b204e9800998ecf8427e" }, // It's a GET request so there's no content, so we send the MD5 hash of an empty string
{ "x-bili-signature-method", "HMAC-SHA256" },
{ "x-bili-signature-nonce", GenerateNonce() },
{ "x-bili-signature-version", "2.0" },
{ "x-bili-timestamp", Timestamp }
};
return BuildSignatureString(s);
static string BuildSignatureString(SortedList<string, string> xbiliHeaders)
{
var sb = new StringBuilder(256); // 256 is an estimated size for the plain text
foreach ((var name, var value) in xbiliHeaders)
{
sb.Append(name)
.Append(':')
.Append(value)
.Append('\n');
}
return sb.ToString(0, sb.Length - 1); // Ignore the last '\n'
}
}
private static string GenerateNonce()
{
Span<byte> bytes = stackalloc byte[256 / 8];
RandomNumberGenerator.Fill(bytes);
return Base64Url.EncodeToString(bytes);
}
}I do allocate an extra The fastest way should be generating the sorted Also, the |
|
Thanks for putting together the benchmark - ~2x throughput and memory improvement is a nice win. I'll merge this now, but I won't release it today so there's not two releases in one day 😄 |
|
Thanks. There's no rush for the next release. I just think that library-level code should be as performance-friendly as possible, and I'm willing to make a contribution 😄 . |
As stated in the title.