Правильный способ измерения распределения памяти с помощью задач - PullRequest
0 голосов
/ 23 апреля 2019

Мне нужно уменьшить количество задач, созданных / выполненных в небольшом фрагменте кода, потому что существует потенциально большое выделение памяти.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TaskMemoryUsage
{
    class Program
    {
        static void Main(string[] args)
        {
            int availableTaskCount = Environment.ProcessorCount;
            OriginalCalculationMethod();
            FirstCalculationMethod(availableTaskCount);
            SecondCalculationMethod(availableTaskCount);
            Console.ReadKey();
        }

        static TaskResult Calculate(int i)
        {
            //a lot of complicated calculations are made here
            return new TaskResult();
        }

        static List<TaskResult> OriginalCalculationMethod()
        {
            List<Task<TaskResult>> workersArray = new List<Task<TaskResult>>();
            long memStart = GC.GetTotalMemory(true);
            for (int i = 0; i < 10000; ++i)
            {
                workersArray.Add(
                        Task.Factory.StartNew(
                            new Func<TaskResult>(() => Calculate(i))
                    ));
            }
            Task.WaitAll(workersArray.ToArray());

            long memEnd = GC.GetTotalMemory(true);
            Console.WriteLine($"DIFFERENCE = {memEnd - memStart}");

            return workersArray.Select(s => s.Result).ToList(); 
        }

        static List<TaskResult> FirstCalculationMethod(int availableTaskCount)
        {           
            long memStart = GC.GetTotalMemory(true);
            using (SemaphoreSlim semaphore = new SemaphoreSlim(availableTaskCount))
            {
                List<Task<TaskResult>> tasks = new List<Task<TaskResult>>();
                for (int i = 0; i < 10000; ++i)
                {
                    Task<TaskResult> task = Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            semaphore.Wait();
                            return Calculate(i);
                        }
                        finally
                        {
                            semaphore.Release();
                        }
                    });
                    tasks.Add(task);
                }
                Task.WaitAll(tasks.ToArray());
                long memEnd = GC.GetTotalMemory(true);
                Console.WriteLine($"DIFFERENCE = {memEnd - memStart}");

                return tasks.Select(s => s.Result).ToList();
            }
        }


        static List<TaskResult> SecondCalculationMethod(int availableTaskCount)
        {
            List<Task<TaskResult>> workersArray = new List<Task<TaskResult>>();
            List<TaskResult> tasksResults = new List<TaskResult>();
            long memStart = GC.GetTotalMemory(true);
            for (int i = 0; i < 10000; ++i)
            {
                workersArray.Add(Task.Factory.StartNew(new Func<TaskResult>(() => Calculate(i))
                                                                ));
                if (workersArray.Count >= availableTaskCount)
                {
                    Task.WaitAll(workersArray.ToArray());
                    tasksResults.AddRange(workersArray.Select(t => t.Result));
                    workersArray.Clear();
                }
            }

            Task.WaitAll(workersArray.ToArray());
            long memEnd = GC.GetTotalMemory(true);
            Console.WriteLine($"DIFFERENCE = {memEnd - memStart}");

            return tasksResults;
        }
    }

    class TaskResult
    {
        public double[] calculationResult;
    }
}

Я получил лучшие результаты для последнего решения, но я не уверен, чтоизмерьте его правильно, поэтому я хочу спросить, правильно ли я измеряю выделение памяти для этой проблемы и правильны ли мои решения или существуют ли более эффективные решения для сокращения выделения памяти, которое потребляется сразу.

...