Hello! I'm trying to deal with serious performance drops in the application.
Drawdowns about which there is a speech appear periodically. Mostly, the iterations are worked out rather quickly, but they are diluted with iterations, which take much longer. Since the application has a graphical display of information, it all looks very twitchy and requires adjustment.
Please look at the following code:
while (true) { var rng = new Random(1); var concurrenBag = new ConcurrentBag<ICollection<(int X, int Y)>>(); Parallel.For(0, 20000, i => { var entry = new List<(int X, int Y)>(); // Π·Π΄Π΅ΡΡ Π΄Π΅ΠΌΠΎΠ½ΡΡΡΠΈΡΡΡΡΡΡ ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ Π°ΡΠΏΠ΅ΠΊΡΡ ΡΠ΅Π°Π»ΡΠ½ΠΎΠ³ΠΎ Π°Π»Π³ΠΎΡΠΈΡΠΌΠ° var r = rng.Next(0, 3); // ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ 20ΠΊ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ² Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΡ ΠΏΠ°ΡΡ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°Ρ for (var j = 0; j < r; j++) // ΠΈΠ½ΠΎΠ³Π΄Π° Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡΡΡ null'Ρ, ΠΈΠ½ΠΎΠ³Π΄Π° ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΡ Ρ 1 Π·Π°ΠΏΠΈΡΡΡ, ΡΠ°ΡΠ΅ - Ρ 2-ΠΌΡ { // Π²ΡΠ΅ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΡΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌΠΈ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΈΠ΄ΡΡ Π² ConcurrentBag entry.Add((j, j * j)); } if (entry.Count == 0) entry = null; concurrenBag.Add(entry); }); var sw = Stopwatch.StartNew(); var results = concurrenBag.ToList().AsParallel().Where(x => x != null).SelectMany(x => x).Distinct().ToList(); // ΠΊΠ°ΠΊ Π²ΡΡΡΠ½ΠΈΠ»ΠΎΡΡ, ΠΏΡΠΎΡΠ°Π΄ΠΊΠΈ Π² ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ Π²Π΅Π΄ΡΡ Π½Π° ΡΡΡ ΡΡΡΠΎΡΠΊΡ var time = sw.ElapsedMilliseconds; Console.WriteLine($"CB count: {concurrenBag.Count:00000}, result count: {results.Count:00}, time: {time:000}"); Thread.Sleep(1000); } The above code leads to the following result in the console:
CB count: 20000, result count: 02, time: 032 <- 32ΠΌΡ, Π΄Π»Ρ ΠΏΠ΅ΡΠ²ΠΎΠΉ ΠΈΡΠ΅ΡΠ°ΡΠΈΠΈ Ρ ΡΡΠ΅ΡΠΎΠΌ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΈ Π²ΡΠ΅Π³ΠΎ ΡΠ°ΠΊΠΎΠ³ΠΎ ΡΡΠΎ Π½ΠΎΡΠΌΠ° CB count: 20000, result count: 02, time: 004 CB count: 20000, result count: 02, time: 014 <- 14ΠΌΡ, ΡΠΆΠ΅ Π½Π΅ Π½ΠΎΡΠΌΠ° CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 004 CB count: 20000, result count: 02, time: 004 CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 015 <- ΠΊΠ°ΠΊ Π²ΠΈΠ΄Π½ΠΎ, ΠΏΠΎΠ²ΡΠΎΡΡΠ΅ΡΡΡ ΠΊΠ°ΠΆΠ΄ΡΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΈΡΠ΅ΡΠ°ΡΠΈΠΉ CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 019 CB count: 20000, result count: 02, time: 004 CB count: 20000, result count: 02, time: 004 CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 014 CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 004 CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 008 CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 004 CB count: 20000, result count: 02, time: 011 CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 003 CB count: 20000, result count: 02, time: 004 I think the idea is clear. In a real application, each "normal" iteration takes 10-15ms, and "subsiding" occur every 6-8 iterations and take up to 150ms
Initially, I assumed that the problem could be with business logic, but you can run the example above and get about the same results. Now I assume that something is wrong with the way I use Parallel.For , AsParallel() or ConcurrentBag , but I have no idea what exactly is wrong.
.ToList().AsParallel()- tym32167Enumerable.Range(...).AsParallel().SelectMany(...)?- Pavel Mayorovpreprocessed.AsParallel()and jump! Why do you needParallel.For? - Pavel MayorovGC.Collect();before your measurements (although it does not guarantee anything), well, plus Paul - tym32167