Pourquoi mon code de thread unique est-il plus rapide que mon code multithreading

Sep 01 2020

J'ai écrit un code simple pour récupérer des valeurs clés d'une chaîne json, mais lorsque je passe à plusieurs threads, pour qu'il saisisse rapidement la valeur plusieurs fois, cela ralentit à chaque fois. Je ne sais pas trop pourquoi cela se produit, je pensais que cela aurait pu avoir quelque chose à voir avec mon processeur? L'ajout d'une fonction d'attente semble le résoudre, mais le rend extrêmement lent, je n'ai plus d'idées et je ne suis pas sûr de la cause.

Production:

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();
    }

Réponses

4 RoarS. Sep 01 2020 at 17:50

Juste pour comparer; J'ai fait une petite réécriture en utilisant du code asynchrone. Beaucoup de réutilisation du code OP, je sais qu'il y a du vieux truc, mais gardons ça comme ça pour le moment.

Filetage simple: écoulé = 2,688

Multi fileté: écoulé = 0,317

Processeur AMD 8 cœurs

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);
    }
}