Re: Создание объектов в параллельных потоках
От: Sinix  
Дата: 08.07.15 13:56
Оценка: 294 (5)
Здравствуйте, VladD2, Вы писали:

VD>И что будет на клиентском? Не замедлит ли это общую работу?


На практике эффекта нет. 40 млн объектов, release x64, 4.5.1, no debugger. GC latency на server gc не влияет, на клиентском не проверял.

ServerGC:
Run
        inline:  1956ms, ips:          20 444 768,79 | Mem: 937 502,13 kb, GC 0/1/2: 3/1/0 => 40000000
      parallel:  1620ms, ips:          24 690 082,37 | Mem: 937 546,36 kb, GC 0/1/2: 2/1/0 => 40000000
Done.

ClientGC:
Run
        inline:  2805ms, ips:          14 256 367,55 | Mem: 937 502,15 kb, GC 0/1/2: 156/81/3 => 40000000
      parallel:  2440ms, ips:          16 388 567,70 | Mem: 937 525,05 kb, GC 0/1/2: 154/53/1 => 40000000
Done.


  Код
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Runtime;
using System.Threading.Tasks;

public class Program
{
    const int AllocSize = 40 * 1000 * 1000;

    class A
    {
        object refValue;
        public A(object o) { refValue = o; }
    }

    static object[] dummyObjects = Enumerable.Range(1, 1000).Cast<object>().ToArray();
    static void Fill(A[] data, int start, int end)
    {
        for (int i = start; i < end; i++)
        {
            data[i] = new A(dummyObjects[0]);
        }
    }

    static A[] data1;

    static void Main()
    {
        var mode = GCSettings.LatencyMode;
        Console.WindowWidth = 120;
        Console.WindowHeight = 35;
        Console.WriteLine("Run");

        data1 = new A[AllocSize];
        Measure("inline", () =>
        {
            //GCSettings.LatencyMode = GCLatencyMode.Batch;
            Fill(data1, 0, data1.Length);
            //GCSettings.LatencyMode = mode;

            return data1.Length;
        });

        data1 = new A[AllocSize];
        Measure("parallel", () =>
        {
            //GCSettings.LatencyMode = GCLatencyMode.Batch;
            var rangePartitioner = Partitioner.Create(0, data1.Length);
            Parallel.ForEach(rangePartitioner, range =>
            {
                Fill(data1, range.Item1, range.Item2);
            });
            //GCSettings.LatencyMode = mode;

            return data1.Length;
        });

        Console.Write("Done.");
        Console.ReadKey();
    }

    static void Measure(string name, Func<long> callback)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        var mem = GC.GetTotalMemory(true);
        var gc00 = GC.CollectionCount(0);
        var gc01 = GC.CollectionCount(1);
        var gc02 = GC.CollectionCount(2);

        var sw = Stopwatch.StartNew();
        var result = callback();
        sw.Stop();

        var mem2 = GC.GetTotalMemory(false);
        var gc10 = GC.CollectionCount(0);
        var gc11 = GC.CollectionCount(1);
        var gc12 = GC.CollectionCount(2);

        var memDelta = (mem2 - mem) / 1024.0;
        var gcDelta0 = gc10 - gc00;
        var gcDelta1 = gc11 - gc01;
        var gcDelta2 = gc12 - gc02;

        Console.WriteLine(
            "{0,14}: {1,5}ms, ips: {2,22:N} | Mem: {3,6:N2} kb, GC 0/1/2: {4}/{5}/{6} => {7,6}",
            name, sw.ElapsedMilliseconds, result / sw.Elapsed.TotalSeconds, memDelta, gcDelta0, gcDelta1, gcDelta2, result);
    }
}

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <runtime>
      <gcServer enabled="true"/>
    </runtime>
</configuration>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.