Sachin k Rajput Ответов: 4

Программа C# работает медленно на нескольких экземплярах


Сейчас несколько дней я практикую некоторые программы на C#. У меня есть проблема в этой программе.

Я создал эту программу,и ее выполнение заняло 21 секунду, а загрузка моего процессора составляет 20% , а использование оперативной памяти-1 ГБ макс.

static void Main(string[] args)
        {
            string str = Console.ReadLine();

            if (str == "start")
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                for (int i = 1; i < 200000; i++)
                {
                   

                    Console.WriteLine("Acccessed Value" + i.ToString());
                    Console.WriteLine("Time " + sw.ElapsedMilliseconds);

                }
            }
            Console.Read();
        }


но когда я создаю 2 экземпляра этого приложения, это занимает 140 секунд, а загрузка процессора составляет 20 % , а использование оперативной памяти-1 ГБ макс.

Не могли бы вы помочь мне, как я могу запустить несколько экземпляров, которые займут 21 секунду, но могут использовать мою оперативную память и процессор максимально.

Что я уже пробовал:

static void Main(string[] args)
        {
            string str = Console.ReadLine();

            if (str == "start")
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                for (int i = 1; i < 200000; i++)
                {
                    

                    Console.WriteLine("Acccessed Value" + i.ToString());
                    Console.WriteLine("Time " + sw.ElapsedMilliseconds);

                }
            }
            Console.Read();
        }

Tomas Takac

Как именно вы провели тест "2 экземпляра" и как вы измерили эти 140 секунд?

Sachin k Rajput

Я запускаю два экземпляра с помощью "Debug" - запускаю как новый экземпляр, и время печатается в секундомере.

Richard MacCutchan

Выполнение любого кода в отладке займет гораздо больше времени, чем обычно. а поскольку Windows не является ОС реального времени, большинство таймингов не могут быть использованы для измерения производительности.

StM0n

Не могли бы вы просто запустить их в двух консольных окнах?.. просто любопытно...

Sachin k Rajput

пытался, но безуспешно..

StM0n

МММ ... консольный вывод Таким образом, что вы делаете, всегда немного голоден к ресурсам:) чего вы пытаетесь достичь... может быть, мы могли бы помочь вам в противном случае.

4 Ответов

Рейтинг:
2

#realJSOP

Я попробовал сделать это в основном по-вашему, и это заняло 39 секунд. Конечно, я не знаю содержания вашего класса секундомера, но все, что делает мой, - это возвращает a TimeSpan когда я звоню своему ElapsedTime метод. Я также делаю только один звонок в Console.Writeline с собой string.Concatконечное значение.

public class StopWatch
{
    public DateTime StartTime { get; set; }

    public void Start()
    {
        this.StartTime = DateTime.Now;
    }

    public TimeSpan ElapsedTime()
    {
        return (DateTime.Now - this.StartTime);
    }
}

static void Main(string[] args)
{
    string str = Console.ReadLine();

    if (str == "start")
    {
        StopWatch sw = new StopWatch();
        sw.Start();
        for (int i = 1; i < 200000; i++)
        {
            Console.WriteLine(string.Concat("Acccessed Value: ", i.ToString(), ", Time: ", sw.ElapsedTime().ToString()));
        }
    }
    Console.Read();
}


F-ES Sitecore

Секундомер - это часть .net framework, он находится в системе.Диагностика

Рейтинг:
1

#realJSOP

Из любопытства я попробовал многопоточный подход к запуску одного приложения. Это тоже 47 секунд.

static void Main(string[] args)
{
    string str = Console.ReadLine();

    if (str == "start")
    {
        StopWatch sw = new StopWatch();
        sw.Start();
        Parallel.Invoke(()=>
        {
            for (int i = 1; i < 200000; i++)
            {
                Console.WriteLine(string.Concat("Thread 1, Acccessed Value: ", i.ToString(), ", Time: ", sw.ElapsedTime().ToString()));
            }
        },
        ()=>
        {
            for (int i = 1; i < 200000; i++)
            {
                Console.WriteLine(string.Concat("Thread 2, Acccessed Value: ", i.ToString(), ", Time: ", sw.ElapsedTime().ToString()));
            }
        });
    }
    Console.Read();
}


Рейтинг:
1

#realJSOP

И, наконец, я подумал, что совместное использование одного и того же секундомера может вызвать какие-то самоиндуцированные задержки, поэтому я сделал это, что привело к тому, что прошло около 49 секунд.

static void Main(string[] args)
{
    string str = Console.ReadLine();

    if (str == "start")
    {
        StopWatch sw = new StopWatch();
        sw.Start();
        Parallel.Invoke(()=>RunTask(1), ()=>RunTask(2));
    }
    Console.Read();
}

private static void RunTask(int taskno)
{
    StopWatch sw = new StopWatch();
    sw.Start();
    string taskNumber = taskno.ToString();
    for (int i = 1; i < 200000; i++)
    {
        Console.WriteLine(string.Concat("Thread ", taskNumber," , Acccessed Value: ", i.ToString(), ", Time: ", sw.ElapsedTime().ToString()));
    }
}


Sachin k Rajput

Спасибо за ваши предложения, но вы можете заметить, что один поток занимает 21 секунду, а два потока-42+ секунды.Я пробовал эти подходы, но не смог довести их до 20+ секунд.

Dave Kreskowiak

На каком оборудовании вы это делаете? Процессор, материнская плата, видеокарта ...

#realJSOP

Вы не получите два приложения, которые пишут на консоль 200 тысяч раз, чтобы закончить работу за 21 секунду. Я сократил его до 0,002 секунды, записав на консоль только один раз в конце цикла. Это ваш лучший вариант, если вы ищете производительность. Короче говоря, хватит возиться с консолью.

F-ES Sitecore

Вы понимаете, что процессор может делать только одну вещь одновременно? Если для выполнения одной задачи требуется 20 секунд, то выполнение двух из этих задач одновременно займет более 40 секунд...20 секунд для каждой задачи, а затем время сверху каждый раз, когда поток должен включаться и выходить из контекста. Многопоточность только ускорит работу, если код может работать на отдельных процессорах или ядрах, и этот уровень обработки диктуется ОС, она решает, где работает ваш код, это ее работа.

http://stackoverflow.com/questions/32343/how-do-i-spawn-threads-on-different-cpu-cores

Dave Kreskowiak

Существует масса факторов, влияющих на выполнение вашего приложения. Некоторые из них уже упоминались.

Кроме того, Windows предоставляет текущему активному (сфокусированному) приложению больший приоритет по сравнению с фоновыми приложениями. Ваш фоновый экземпляр будет работать медленнее, чем экземпляр переднего плана.

Консоли имеют экранные буферы, размер которых можно изменить, чтобы они были довольно большими. Чем больше буфер, тем больше данных должно быть перемещено для каждой строки, добавленной в консоль. Я держу свои консольные окна на уровне 120 столбцов в ширину и 5000 строк в глубину. На моей текущей машине (2 ядра, гиперпоточность) запуск одного экземпляра вашего приложения занимает 25 секунд. Два экземпляра занимают около 140 секунд.

Вы ничего не можете сделать, чтобы изменить это. Консольный доступ-это просто ... медленный.

Я не знаю, чего ты ждешь и в чем, по-твоему, проблема. То, что ты видишь, нормально.

Рейтинг:
1

#realJSOP

Мое окончательное решение-время выполнения составляет 0,002 секунды (я бы назвал это "незначительным" с точки зрения затраченного времени):

static void Main(string[] args)
{
    string str = Console.ReadLine().ToLower();

    if (str.Contains("start"))
    {
        StopWatch sw = new StopWatch();
        sw.Start();
        if (str.EndsWith("p"))
        {
            Parallel.Invoke(()=>RunTask(1), ()=>RunTask(2));
        }
        else
        {
            RunTask();
        }
    }
    Console.Read();
}

private static void RunTask(int taskno=0)
{
    StopWatch sw = new StopWatch();
    sw.Start();
    string taskNumber = taskno.ToString();
    for (int i = 1; i < 200000; i++)
    {
    }
    Console.WriteLine(string.Concat("Thread ", taskNumber," , Elapsed: ", sw.ElapsedTime().ToString()));
}

Положи это в свою трубку и выкури.

Кстати, если вы настаиваете на том, чтобы задача заняла 21 секунду, проще говоря Thread.Sleep(21000) в конце концов Main().