uruk-project / Jwt

JSON Web Token implementation for .Net & .Net Core
MIT License
84 stars 13 forks source link

Use `Utf8JsonReader.ValueTextEquals` instead of bytes comparison #325

Closed ycrumeyrolle closed 5 years ago

ycrumeyrolle commented 5 years ago

Using Utf8JsonReader.ValueTextEquals() cause a drop of performance of about 400% compared to bytes comparison with the signature algorithm scenario. Using Encoding.UTF8.GetBytes(Utf8JsonReader.GetString()) cause a drop of performance of about 80% and an useless allocation of the string object. Using Utf8JsonReader.ValueSpan is fastest, but the value is not unescaped. If the header is represented as {"alg":"HS256"}it is fine, but if it is represented as {"alg":"\u0048\u0053\u0032\u0035\u0036"}, which is not very likely but possible, it will not be correctly interpreted.

An option would be to combine Utf8JsonReader.ValueSpan for most common scenario, and as fallback use Encoding.UTF8.GetBytes(Utf8JsonReader.GetString()). Another option would be to have a API like Utf8JsonReader.GetUtf8String() for extracting the UTF8 unescaped string as its byted representation, similar to the UTF8JsonReader.GetBytesFromBase64() API, but it may still cause some memory allocation. CC @ahsonkhan

Method data Mean Error StdDev Median Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
Utf8JsonReader.ValueTextEquals {"alg":"HS256"} 62.035 ns 1.2239 ns 2.2070 ns 62.457 ns 4.86 0.17 - - - -
Utf8JsonReader.ValueTextEquals {"alg":"FAKE"} 64.928 ns 1.5411 ns 1.5825 ns 64.911 ns 5.28 0.20 - - - -
Encodin_UTF8_GetBytes_Utf8JsonReader_GetString {"alg":"HS256"} 12.305 ns 0.2001 ns 0.1671 ns 12.298 ns 1.00 0.00 0.0010 - - 4 B
Encodin_UTF8_GetBytes_Utf8JsonReader_GetString {"alg":"FAKE"} 12.354 ns 0.2425 ns 0.2886 ns 12.287 ns 1.01 0.04 0.0010 - - 4 B
Utf8JsonReader_ValueSpan {"alg":"HS256"} 6.898 ns 0.1436 ns 0.3385 ns 6.731 ns 0.60 0.02 - - - -
Utf8JsonReader_ValueSpan {"alg":"FAKE"} 6.862 ns 0.1092 ns 0.1073 ns 6.844 ns 0.56 0.01 - - - -