Perché il mio codice single threading è più veloce del mio codice multithreading

Sep 01 2020

Ho scritto un semplice codice per acquisire alcuni valori chiave da una stringa json, ma quando vado a multi thread, per far sì che prenda rapidamente il valore più volte, diventa più lento ogni volta. Non sono abbastanza sicuro del motivo per cui sta accadendo, stavo pensando che potrebbe avere qualcosa a che fare con la mia CPU? L'aggiunta di una funzione di attesa sembra risolverlo, ma lo fa andare estremamente lento, sono senza idee e non sono sicuro di cosa lo stia causando.

Produzione:

Single Threaded
598
Elapsed=0.558
598
Elapsed=0.121
598
Elapsed=0.127
598
Elapsed=0.127
598
Elapsed=1.167
598
Elapsed=0.122
598
Elapsed=0.124
598
Elapsed=0.145
598
Elapsed=0.146
598
Elapsed=0.12
------------------------------
Multi Threading
598
Elapsed=0.129
598
Elapsed=0.179
598
Elapsed=0.227
598
Elapsed=0.299
598
Elapsed=0.326
598
Elapsed=0.396
598
Elapsed=0.427
598
Elapsed=0.505
598
Elapsed=0.525
598
Elapsed=0.703

private static void Test2() {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        using (WebClient wb = new WebClient()) {
            wb.Proxy = null;
            string data = wb.DownloadString("https://google.com");
            sw.Stop();
            Console.WriteLine("Elapsed={0}", (double)sw.ElapsedMilliseconds / 1000);
        }
    }
    static void Main(string[] args) {

        Console.WriteLine("Single Threaded");

        Test2();
        Test2();
        Test2();
        Test2();
        Test2();
        Test2();
        Test2();
        Test2();
        Test2();
        Test2();

        Console.WriteLine("------------------------------");
        Console.WriteLine("Multi Threading");

        for (int i = 0; i < 10; i++) {
            void Multi() {
                Test2();
            }
            new Thread(Multi).Start();
        }
        Console.Read();
    }

Risposte

4 RoarS. Sep 01 2020 at 17:50

Solo per il confronto; Ho fatto una piccola riscrittura usando il codice asincrono. Molto riutilizzo dal codice OP, so che ci sono cose vecchie, ma per ora manteniamole così.

Filettatura singola: trascorsa = 2.688

Multi thread: trascorso = 0,317

CPU AMD a 8 core

public class ThreadingTests
{
    private static async Task Test2()
    {
        await Task.Delay(1); // only here to make method async

        using var wb = new WebClient { Proxy = null };
        var data = wb.DownloadString("https://www.roblox.com/users/inventory/list-json?assetTypeId=41&cursor=&itemsPerPage=100&pageNumber=1&userId=539720021");
        dynamic parsed = JObject.Parse(data);
    }

    [Test]
    public async Task SingleTest()
    {
        Console.WriteLine("Single Threaded");
        var sw = new Stopwatch();
        sw.Start();

        for (var i = 0; i < 10; i++)
        {
            await Test2();
        }
        
        sw.Stop();
        Console.WriteLine("Elapsed={0}", (double)sw.ElapsedMilliseconds / 1000);
    }

    [Test]
    public async Task MultiTest()
    {
        Console.WriteLine("Multi Threaded");
        var sw = new Stopwatch();
        sw.Start();

        var taskList = new List<Task>();
        for (var i = 0; i < 10; i++)
        {
            taskList.Add(Test2());
        }

        await Task.WhenAll(taskList);

        sw.Stop();
        Console.WriteLine("Elapsed={0}", (double)sw.ElapsedMilliseconds / 1000);
    }
}