Skip to content

System.Net.WebProxy Bypass regex list reconstructed for every call to IsBypassed #73703

@onehourlate

Description

@onehourlate

Description

System.Net.WebProxy takes a list of strings for Uris that should bypass the proxy.
This list of strings is compiled into a list of Regex by the method UpdateRegexList

This method is called in the constructor and in the BypassList property setter.
This is normal.

However, this method is also called in IsMatchInBypassList, which is called by IsBypassed
This feels wrong. I don't see why it needs to systematically refresh the regex list in this call.
It re-allocates the array and all the regex, for no reason (as far as I can see anyway).

Regression?

This behavior seems to be copy-pasted from the .Net Framework code, which is also wrong.
https://referencesource.microsoft.com/#system/net/system/Net/webproxy.cs

Analysis

The following code shows a significant difference between the proxy1 et proxy2 execution time
(typically ~230ms vs ~2100ms)
Since the call to IsBypassed returns true for the first regex, the length of the Bypasslist should not matter.

Uri uri = new Uri("https://a.com/");

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
bool r1 = true;
System.Net.WebProxy proxy1 = new System.Net.WebProxy("http://localhost:9999", true, new string[] { "a" });
sw.Restart();
for (int i = 0; i < 100000; i++) {
    r1 &= proxy1.IsBypassed(uri);
}
sw.Stop();
Console.WriteLine($"Proxy1 : {sw.ElapsedMilliseconds}ms ({r1})");

bool r2 = true;
System.Net.WebProxy proxy2 = new System.Net.WebProxy("http://localhost:9999", true, new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" });
sw.Restart();
for (int i = 0; i < 100000; i++) {
    r2 &= proxy2.IsBypassed(uri);

}
sw.Stop();
Console.WriteLine($"Proxy2 : {sw.ElapsedMilliseconds}ms ({r2})");

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions