Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么通过GCLatencyMode.LowLatency最小化垃圾收集会对执行时间产生负面影响?_C#_Multithreading_Memory Management_Garbage Collection_Heap - Fatal编程技术网

C# 为什么通过GCLatencyMode.LowLatency最小化垃圾收集会对执行时间产生负面影响?

C# 为什么通过GCLatencyMode.LowLatency最小化垃圾收集会对执行时间产生负面影响?,c#,multithreading,memory-management,garbage-collection,heap,C#,Multithreading,Memory Management,Garbage Collection,Heap,我不明白为什么将GCSettings.LatencyMode设置为GCLatencyMode.LowLatency会对执行时间产生负面影响 请考虑下面的代码。请注意,我在线程池中有足够的线程,因此我确保这里没有引入延迟。另外,我在这台机器上有足够的内存。在Interactive和LowLatency中运行的差异会导致LowLatency的执行时间增加3倍 class Program { static void Main(string[] args) { //cap

我不明白为什么将
GCSettings.LatencyMode
设置为
GCLatencyMode.LowLatency
会对执行时间产生负面影响

请考虑下面的代码。请注意,我在线程池中有足够的线程,因此我确保这里没有引入延迟。另外,我在这台机器上有足够的内存。在

Interactive
LowLatency
中运行的差异会导致
LowLatency
的执行时间增加3倍

class Program
{
    static void Main(string[] args)
    {
        //capture current latency mode
        var currentLatencyMode = GCSettings.LatencyMode;

        //set low latency mode to minimize garbage collection
        GCSettings.LatencyMode = GCLatencyMode.LowLatency;

        var watch = new Stopwatch();
        var numberTasksToSpinOff = 4;
        var numberItems = 20000;
        var random = new Random((int)DateTime.Now.Ticks);
        var dataPoints = Enumerable.Range(1, numberItems).Select(x => random.NextDouble()).ToList();
        var workers = new List<Worker>();

        //structure workers
        for (int i = 1; i <= numberTasksToSpinOff; i++)
        {
            workers.Add(new Worker(i, dataPoints));
        }

        //start timer
        watch.Restart();

        //parallel work
        if (workers.Any())
        {
            var processorCount = Environment.ProcessorCount;
            var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = processorCount };
            Parallel.ForEach(workers, parallelOptions, DoSomeWork);
        }

        //stop timer
        watch.Stop();

        //reset latency mode
        GCSettings.LatencyMode = currentLatencyMode;

        Console.WriteLine($"Time it took to complete in Milliseconds: {watch.ElapsedMilliseconds}");
        Console.WriteLine("Press key to quit");
        Console.ReadLine();
    }

    private static void DoSomeWork(Worker worker)
    {
        Console.WriteLine($"WorkerId: {worker.WorkerId} -> New Tasks spun off with in Thread Id: {Thread.CurrentThread.ManagedThreadId}");

        var indexPos = 0;
        foreach (var dp in worker.DataPoints)
        {
            var subset = worker.DataPoints.Skip(indexPos).Take(worker.DataPoints.Count - indexPos).ToList();
            indexPos++;
        }
    }
}

public class Worker
{
    public int WorkerId { get; set; }
    public List<double> DataPoints { get; set; }

    public Worker(int workerId, List<double> dataPoints)
    {
        WorkerId = workerId;
        DataPoints = dataPoints;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
//捕获当前延迟模式
var currentLatencyMode=GCSettings.LatencyMode;
//设置低延迟模式以最小化垃圾收集
GCSettings.LatencyMode=GCLatencyMode.LowLatency;
var watch=新秒表();
var numberTasksToSpinOff=4;
var numberItems=20000;
var random=new random((int)DateTime.Now.Ticks);
var dataPoints=Enumerable.Range(1,numberItems).Select(x=>random.NextDouble()).ToList();
var workers=新列表();
//结构工人

对于(int i=1;i这里没有免费的午餐,垃圾收集器必须做一项工作,并尝试考虑您的顾虑。但是,没有一种方法适合所有人(特别是在试图突破其限制时)

要回收对象,垃圾收集器必须停止所有正在执行的 应用程序中的线程。在某些情况下,例如 应用程序检索数据或显示内容,这是一个完整的垃圾 收集可能发生在关键时间,并影响性能。您 可以通过设置
GCSettings.LatencyMode属性设置为
System.Runtime.GCLatencyMode

更进一步

LowLatency抑制第2代收集并仅执行 第0代和第1代集合。它只能在短时间内使用 时间。在较长的时间内,如果系统处于内存压力下, 垃圾收集器将触发一个收集,该收集可以 暂停应用程序并中断时间关键型操作。此 此设置仅适用于工作站垃圾回收

在低延迟期间,第2代收集将被抑制,除非发生以下情况:

  • 系统从操作系统接收内存不足通知
  • 应用程序代码通过调用GC.Collect方法并为generation参数指定2来诱导收集
使用低延迟的指导原则

使用低级延迟模式时,请考虑以下准则:

  • 保持低延迟的时间段尽可能短

  • 避免在低延迟期间分配大量内存。由于垃圾收集,可能会发生内存不足通知 回收更少的对象

  • 在低延迟模式下,尽量减少分配的数量,尤其是分配到大型对象堆和 固定对象

  • 请注意可能正在分配的线程。由于LatencyMode属性设置是进程范围的,因此可以生成 可能正在分配的任何线程上的OutOfMemoryException

  • 根据指南(并考虑到您之前的问题),您显然试图在其预期理想操作条件下使用它

    我认为对你来说最重要的一点是1和3,显然垃圾收集器要么是被一个
    gc.collect
    命令强制清理,要么是它觉得需要清理你正在分配的大量内存,即11 Gig


    这里的关键是,如果不知道垃圾收集器的确切内部结构和工作原理,也不知道您正在做什么以及原因,那么除了“在您的情况下,它确实会影响执行时间”之外,您的问题可能永远不会有一个理想的答案

    这里没有免费的午餐,垃圾收集器必须做好工作,并尽力考虑您的顾虑。然而,这里没有一刀切的办法(特别是在试图突破其限制时)

    要回收对象,垃圾收集器必须停止所有正在执行的 应用程序中的线程。在某些情况下,例如 应用程序检索数据或显示内容,这是一个完整的垃圾 收集可能发生在关键时间,并影响性能。您 可以通过设置
    GCSettings.LatencyMode属性设置为
    
    System.Runtime.GCLatencyMode

    更进一步

    LowLatency抑制第2代收集并仅执行 第0代和第1代集合。它只能在短时间内使用 时间。在较长的时间内,如果系统处于内存压力下, 垃圾收集器将触发一个收集,该收集可以 暂停应用程序并中断时间关键型操作。此 此设置仅适用于工作站垃圾回收

    在低延迟期间,第2代收集将被抑制,除非发生以下情况:

    • 系统从操作系统接收内存不足通知
    • 应用程序代码通过调用GC.Collect方法并为generation参数指定2来诱导收集
    使用低延迟的指导原则

    使用低级延迟模式时,请考虑以下准则:

  • 保持低延迟的时间段尽可能短

  • 避免在低延迟期间分配大量内存。低内存