2

In mono 4.6.2 / linux, I'm noticing huge differences between the speed wget can download files, vs webclient.DownloadString, so I made a little test to investigate. Why is wget significantly faster than C#? From my own experiments, it's faster to swallow the overhead of downloading using wget, reading in the files manually, and finally deleting the downloaded files, than simply using .DownloadString. Am I using the HttpWebRequest incorrectly?

Update: On mono/linux, it would seem that using AutomaticDecompression makes no difference at all. I can't see any problems reported about it in mono though.

Update2: Due to a typo, I didn't notice that the native WebClient class is far faster than a simple extended class. Why does mono have a huge performance gap between a simple extended class and its parent?

class WC1 : System.Net.WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        var r = (HttpWebRequest) base.GetWebRequest(address);
        r.Pipelined = true;
        r.KeepAlive = true;
        r.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;

        return r;
    }
}

class WC2 : System.Net.WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        var r = (HttpWebRequest)base.GetWebRequest(address);
        r.Pipelined = true;
        r.KeepAlive = false;
        r.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;

        return r;
    }
}

class WC3 : System.Net.WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        var r = (HttpWebRequest)base.GetWebRequest(address);
        r.Pipelined = false;
        r.KeepAlive = true;
        r.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;

        return r;
    }
}

class WC4 : System.Net.WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        var r = (HttpWebRequest)base.GetWebRequest(address);
        r.Pipelined = false;
        r.KeepAlive = false;
        r.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;

        return r;
    }
}

class Program
{
    static List<string> CreateUrls(int c)
    {
        var urls = new List<string>();
        for (var i = 0; i < c; i++)
        {
            urls.Add("http://foo.com/?" + i);
        }
        return urls;
    }

    static TimeSpan Test(WebClient wc, IEnumerable<string> urls)
    {
        var sw = new System.Diagnostics.Stopwatch();

        sw.Start();

        foreach (var u in urls)
        {
            wc.DownloadString(u);
            Console.Write(".");
        }

        sw.Stop();
        return sw.Elapsed;
    }

    static void Main(string[] args)
    {
        var urlsPerTest = 200;
        var urls = CreateUrls(urlsPerTest * 6);


        var wc1 = new WC1();
        var urls1 = urls.Take(urlsPerTest);
        var elapsed1 = Test(wc1, urls1);
        Console.WriteLine("WC1:" + elapsed1);

        var wc2 = new WC2();
        var urls2 = urls.Skip(urlsPerTest * 1).Take(urlsPerTest);
        var elapsed2 = Test(wc2, urls2);
        Console.WriteLine("WC2:" + elapsed2);

        var wc3 = new WC3();
        var urls3 = urls.Skip(urlsPerTest * 2).Take(urlsPerTest);
        var elapsed3 = Test(wc3, urls3);
        Console.WriteLine("WC3:" + elapsed3);

        var wc4 = new WC4();
        var urls4 = urls.Skip(urlsPerTest * 3).Take(urlsPerTest);
        var elapsed4 = Test(wc4, urls4);
        Console.WriteLine("WC4:" + elapsed4);

        var wc5 = new WebClient();
        var urls5 = urls.Skip(urlsPerTest * 4).Take(urlsPerTest);
        var elapsed5 = Test(wc5, urls5);
        Console.WriteLine("Webclient:" + elapsed5);


        var urls6 = urls.Skip(urlsPerTest * 5).Take(urlsPerTest);
        File.WriteAllLines("/tmp/foo.txt", urls6);

        var sw = new Stopwatch();
        sw.Start();
        var p = new Process();
        p.StartInfo = new ProcessStartInfo();
        p.StartInfo.Arguments = "--silent -i /tmp/foo.txt";
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.FileName = "wget";
        p.StartInfo.WorkingDirectory = "/tmp";
        p.StartInfo.UseShellExecute = false;
        p.Start();
        p.WaitForExit();

        sw.Stop();
        File.Delete("/tmp/foo.txt");

        Console.WriteLine("Wget:" + sw.Elapsed);

        Console.ReadLine();
    }
}

output

WC1:00:01:20.6518416
WC2:00:01:16.3561090
WC3:00:01:18.4278756
WC4:00:01:25.5372973
Webclient:00:01:04.6749124
Wget:00:01:03.4862053
user3791372
  • 4,445
  • 6
  • 44
  • 78

0 Answers0