Создание PerformanceCounter занимает много времени

Я работаю над системой балансировки заряда, поэтому мне нужно знать заряд каждой машины. PerformanceCounter кажется правильным, но создание первого занимает от 38 до 60 секунд. Однако каждый последующий новый вызов Counter или NextValue происходит практически мгновенно.

Вот код, который я использую:

[TestClass]
public class PerfMon
{
    [TestMethod]
    public void SimpleCreationTest()
    {
        Stopwatch Time = new Stopwatch();
        Time.Start();
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds);

        // Create

        PerformanceCounter RAM = new PerformanceCounter("Memory", "Available MBytes");
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => RAM created");

        PerformanceCounter CPU = new PerformanceCounter("Processor", "% Processor Time", "_Total");
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => CPU created");

        PerformanceCounter GC = new PerformanceCounter(".NET CLR Memory", "% Time in GC", "_Global_");
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => GC created");

        // Read

        float Value = RAM.NextValue();
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => RAM value is : " + Value);

        Value = CPU.NextValue();
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => CPU value is : " + Value);

        Value = GC.NextValue();
        Debug.WriteLine("Time is : " + Time.ElapsedMilliseconds + " => GC value is : " + Value);
    }
}

Исследование

PerformanceCounter очень медленно подключается к удаленному серверу

Создание нового System.Diagnostics.PerformanceCounter выполняется очень медленно

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

Почему вызов PerformanceCounter является медленным?

http://craigandera.blogspot.fr/2005/06/performancecounter-constructor-horribly_21.html

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

Запуск Visual Studio в Администраторе "ускоряет" первое создание с 38 до 26 секунд, поэтому это также не решает проблему.


Спасибо за вашу помощь.

2 ответа

Я попробовал ваш код на моей машине и получил>2,5 секунды для конструктора PerformanceCounter. Я не смог отладить исходный код.NET (я использую VS2013 Express Edition, Windows 7 64b), но я провел серию экспериментов:

  1. Я вызвал конструктор по умолчанию для PerformanceCounter. Это выполняется мгновенно.
  2. С помощью perfmon я проверил сетевую активность. Я не видел ничего особенного.
  3. Я контролировал след памяти. Я увидел, что при вызове первого параметризованного конструктора я добавляю ~2,5 МБ в объем памяти, занимаемый кодом.
  4. Используя perfmon, я проверил, есть ли скачок в числе использованных мьютексов, семафоров и других объектов синхронизации. Ничего необычного не случилось.
  5. Я тестировал код в разное время, когда было активным разное количество процессов. Я видел, что есть большая вариация. Иногда я получаю 1,4 секунды, иногда 2,7, иногда 5 секунд.
  6. Я уже открыл сеанс мониторинга графического интерфейса и запустил код, но не увидел никакой выгоды.

Поэтому я считаю, что проблемы с установкой нет, и ответ заключается в том, что конструктор PerformanceCounter выполняет сложную работу, выполнение которой занимает много времени.

Все отслеживаемые события являются программными событиями, которые могут отслеживаться операционной системой. Поэтому я предполагаю, что при создании нового объекта PerformanceCounter ОС должна сгенерировать текущее состояние компьютера. Это, возможно, означает получение информации для всех процессов и, самое главное, сохранение этой информации в удобочитаемой и быстро доступной структуре. Я заметил, что чем больше у меня активных процессов, тем медленнее создается PerformanceCounter. Кроме того, чем больше у вас ядер, тем больше данных вам нужно собрать.

В последней отправленной вами ссылке есть комментарий, который, кажется, подтверждает эту теорию, но я полагаю, что часть спин-блокировки была оптимизирована с 2005 года. Вероятно, последним средством является отладка источника.NET для создания PerformanceCounter. Однако я думаю, что это только то, как это реализовано.

Что я хотел бы сделать, это создать объекты PerformanceCounter, которые мне нужны на этапе инициализации приложения.

Это то, что исправило это для меня:

Время установки счетчиков производительности в моем приложении уменьшилось с 2:30 до 20 секунд, благодаря чему оно выполнялось как 64-битный процесс. Интересно, что у меня была проблема с производительностью только в виртуальной машине Windows 2012. Нет проблем в Windows 10.

Другие вопросы по тегам