在构造之后,应用程序经常访问Uri的各种组件,这一点也得到了改进。特别是,像HttpClient这样的类型通常有一个重复用于发出请求的Uri。HttpClient实现将访问Uri。属性的路径和查询,以发送作为HTTP请求的一部分(例如,GET /dotnet/runtime HTTP/1.1),在过去,这意味着为每个请求重新创建Uri的部分字符串。感谢dotnet/runtime#36460,它现在被缓存(就像IdnHost一样):
PathAndQuery .NET FW 4.8 17.936 ns 1.00 56 B
PathAndQuery .NET Core 3.1 30.891 ns 1.72 56 B
PathAndQuery .NET 5.0 2.854 ns 0.16 –
除此之外,还有许多代码与uri交互的方式,其中许多都得到了改进。例如,dotnet/corefx#41772改进了Uri。EscapeDataString和Uri。EscapeUriString,它根据RFC 3986和RFC 3987对字符串进行转义。这两种方法都依赖于使用不安全代码的共享 helpers,通过char[]来回切换,并且在Unicode处理方面有很多复杂性。这个PR重写了这个 helpers来利用.NET的新特性,比如span和符文,以使escape操作既安全又快速。对于某些输入,增益不大,但是对于涉及Unicode的输入,甚至对于长ASCII输入,增益就很大了。
Escape .NET FW 4.8 False 6,162.59 us 1.00 60616272 B
Escape .NET Core 3.1 False 6,483.85 us 1.06 60612025 B
Escape .NET 5.0 False 243.09 us 0.04 240045 B
Escape .NET FW 4.8 True 86.93 us 1.00 –
Escape .NET Core 3.1 True 122.06 us 1.40 –
Escape .NET 5.0 True 14.04 us 0.16 –
为Uri.UnescapeDataString提供了相应的改进。这一改变包括使用已经向量化的IndexOf而不是手动的基于指针的循环,以确定需要进行非转义的字符的第一个位置,然后避免一些不必要的代码,并在可行的情况下使用堆栈分配而不是堆分配。虽然使所有操作更快,最大的收益是字符串unescape无关,这意味着EscapeDataString操作没有逃避,只是返回其输入(这种情况也随后帮助进一步dotnet/corefx#41684,使原来的字符串返回时不需要改变):
Unescape .NET FW 4.8 847.44 ns 1.00
Unescape .NET Core 3.1 846.84 ns 1.00
Unescape .NET 5.0 21.84 ns 0.03
dotnet/runtime#36444和dotnet/runtime#32713使比较uri和执行相关操作(比如将它们放入字典)变得更快,尤其是相对uri。
Sum .NET FW 4.8 330.25 us 1.00
Sum .NET Core 3.1 47.64 us 0.14
Sum .NET 5.0 18.87 us 0.06