Próbuję zwiększyć wydajność własnego systemumonitorować, aby opóźnić wykonanie części mojego kodu serwera w przypadku przeciążenia (uruchomienie niektórych usług internetowych w ramach IIS). Pierwszą rzeczą, którą próbuję rozwiązać, jest przeciążenie procesora.
Wiem o tym PerformanceCounter
problemy z inicjowaniem go przy pierwszym połączeniu z NextValue()
(widzieć to pytanie, między innymi), więc zaimplementowałem bardzo prostą klasę statyczną, która buforuje dane przez sekundę i faktycznie uzyskuje dostęp do PerformanceCounter
obiekt raz na sekundę lub krócej. Wiem, że obecnie nie jest bezpieczny wątkowo, ale nie martwię się tym w obecnej fazie prototypowania.
Powiedziawszy to wszystko, oto mój obecny kod:
public static class SystemPerformance
{
private static PerformanceCounter TotalProcessorTimeCounter =
new PerformanceCounter("Process", "% Processor Time", "_Total");
private static DateTime CacheRefreshed;
private static float CachedValue = 0f;
private const float MIN_DELTA_SECONDS = 1f;
public static float ReadCPU()
{
if ((DateTime.Now - CacheRefreshed).TotalSeconds > MIN_DELTA_SECONDS)
// Stale cache
return ReadFromCounter();
// Good cache
return CachedValue;
}
private static float ReadFromCounter()
{
CachedValue = TotalProcessorTimeCounter.NextValue();
CacheRefreshed = DateTime.Now;
return CachedValue;
}
}
... co jest miłe i eleganckie, dopóki go nie wykonam. Próbowałem uruchomić go na maszynie wirtualnej z systemem Windows 10 x64 z 4 rdzeniami, a na żelazku z systemem Windows 7 x64 z 4 rdzeniami - w obu przypadkach zwracana wartość oscyluje wokół 400, bez względu na to, co robię.
Typowe wartości, które otrzymuję, mieszczą się w zakresie395–401, z okazjonalnym spadkiem do 365 lub skokiem do 405. Wartości, które czytam, nie są w żaden sposób skorelowane z faktycznym obciążeniem procesora na żadnym z testowanych przeze mnie komputerów, jak pokazuje Menedżer zadań, Monitor wydajności, a nawet wspólne sens.
Metodologia testowania jest prosta: SystemPerformance.ReadCPU()
jest uruchamiany przez naciśnięcie przycisku w prostej formie systemu Windows, a dane wyjściowe są wyświetlane w polu tekstowym w tej samej formie. Naciskam ten przycisk, gdy procesor jest quasi-bezczynny, a także naciskam go, gdy inne procesy robią rzeczy i ładują procesor.
Co ja robię źle? Czy to ma zwracać użycie procesora tylko przez wątki mojej aplikacji? Czy źle interpretuję dane?
Odpowiedzi:
2 dla odpowiedzi № 1 new PerformanceCounter("Process", "% Processor Time", "_Total");
Tak, czas procesora zajęty przez _ Łączną liczbę procesów, w tym fałszywy „System bezczynności procesu”, który widzisz w Menedżerze zadań, zawsze będzie sumował się do 400% na czterordzeniowej maszynie.
Prawdopodobnie polubisz ten numer, jeśli takzmień „Process” na „Processor”. Jeśli chcesz dopasować wartość wyświetlaną przez Menedżera zadań, musisz zmienić „Proces” na „Informacje o procesorze”. Nowa kategoria, która próbuje wygenerować bardziej realistyczną liczbę, która jest kompensowana dla procesora z doładowaniem turbo, maszyn z węzłami NUMA i niższej wydajności uzyskiwanej z hiperwątków. Będziesz chciał przeczytać ten wpis na blogu za drobiazg.