Verwendung der Windows Energiesparfunktionen in .NET Software


Einführung in die Thematik

Im Jahr 2008 hat Gartner das Thema “Green IT” als das Top Strategische Technologie (Thema) identifiziert. http://www.gartner.com/it/page.jsp?id=530109. Im Jahr 2009 war „Green IT“ immerhin noch auf Platz 4 bei Gartner http://www.computerwoche.de/management/it-strategie/1909003/ .

Spätestens dadurch wurde das Thema als wichtiges Thema erkannt und seine Wichtigkeit hat sich bis heute stetig erhöht. Das ist es nicht überraschend: Mehrere Studien gehen davon aus, dass die anfallende CO2-Menge der weltweiten IT in etwa dem CO2-Ausstoß des internationalen Luftverkehrs entspricht.

Auf der deutschen Wikipedia wird „Green IT“ wie folgt definiert „ … Unter dem Stichwort Green IT (seltener auch Green ICT) versteht man Bestrebungen, die Nutzung von Informationstechnik (IT) bzw. Informations- und Kommunikationstechnologie (früher IKT oder IuK, engl. ICT) über deren gesamten Lebenszyklus hinweg umwelt- und ressourcenschonend zu gestalten, also vom Design der Systeme und zur Produktion der Komponenten über deren Verwendung bis zur Entsorgung, bzw. dem Recycling der Geräte. …“ http://de.wikipedia.org/wiki/Green_IT.

Als Softwareentwickler muss ich hier sofort Einspruch erheben! Diese Definition fokussiert aus meiner Sicht extrem auf die Hardware Aspekte der IT. Als Softwareentwickler weiss ich aber das die stromsparendsten Hardeware-Komponenten nur sinnvoll einsatzbar sind, wenn diese Funktionen auch optimal durch Software unterstützt werden. Welche Software ist das?

1. Das Betriebssystem, das Zugriff und energieeffizienten Umgang mit Stromsparhardware ermöglicht

2. Virtualisierungssoftware, die durch sinnvolle Lastverteilung die Hardware optimal ausnutzt und Hardware-Konsolidierung ermöglicht.

3. U.v.a.m. …

Natürlich kann man auch eigene Software so implementieren, dass sie nachhaltig mit den Hardwareressourcen umgeht. Durch den spezielle Entwurf von Softwareabläufen können Anwendungen entstehen, die auch Energieeffizienz berücksichtigen. D.h. schon im Entwurfsstadium und der Struktur einer Software sollte man für Energieeffizienz betrachten und planen. Architekturelle Themen können hier sein:

· Verteilte Architekturen zur Zentralisierung von Abläufen auf dem Server

· Bei lokalen hardware-intensiven Abläufen, die Nutzung von Multicore CPUs durch parallel Framework-Funktionen (.NET 4.0 – Task parallel library, Parallel Linq)

· Sinnvolle Entwicklung von nebenläufigen Aktivitäten (Asynchronität und Daemons/Dienste-Entwurf)

· …

Bei manchen solcher Abläufe müssen Informationen der Hardware zugänglich und man muss ggf. auch solche Energiesparfunktionen steuernd benutzen. Und auf diese Funktionen zuzugreifen, gibt es schon Lösungen, wie man als .NET Softwareentwickler diese Funktionen nutzen kann.

Weiterhin können Energiezustandsinformationen auch für den Entwurf mobiler Anwendungen genutzt werden (Batteriestatus …).

.NET Powermanagement Funktionen

Windows API Code Pack

Das Windows API Code Pack kann unter http://code.msdn.microsoft.com/WindowsAPICodePack heruntergeladen werden. Einige Funktionen in dieser Bibliothek beschäftigen sich mit Powermanagement. Mit diesen Funktionen kann man auf sehr viele Powermanagement relevante Informationen und Events zugreifen.

Diese fast rein lesenden Funktionen werden über die Klassen PowerManager und BatteryState zur Verfügung gestellt. Im Windows API Code Pack ist auch ein Beispielprogramm, welches die Verwendung der Klassen demonstriert. Das Beispiel ist in dem Verzeichnis C:\WindowsAPICodePack\Samples\PowerMgmtDemo\CS.

Die Solution gibt's auf .http://code.msdn.microsoft.com/DNGC

Am ersten Userinterface der Anwendung man eine Reihe von Informationen, die man mit den oben genannten Klassen lesen kann. Alle Funktionen dieser Klassen können ohne administrative Berechtigungen ausgeführt werden.

clip_image001

Abbildung 1 - PowerMgmtDemo UI 1

Das zweite UI zeigt, wie man über Zustandsinformationen die Abläufe im Programm steuern kann. In diesem Fall kann man einen Hintergrund Task startet, die Dateien indiziert. Wenn der PowerSourceStatus auf UPS oder Batterie ist, kann der Thread nicht gestartet werden oder der laufende Thread wird beendet.

clip_image002

Abbildung 2 - PowerMgmtDemo UI 2

Die Klasse PowerManager hat folgende Properties:

· BatteryLifePercent – gibt in Prozent den Ladestatus der Batterie (falls vorhanden zurück).

· IsBatteryPresent – gibt zurück, ob eine Batterie im Computer vorhanden ist.

· IsBatteryShortTerm – gibt zurück, ob der Ladezustand der Batterie im kritischen Bereich ist.

· IsMonitorOn - gibt zurück, ob der Monitor an ist. (In diesem Screenshot „no“ – Notebook mit RDP Betrieb.)

· IsUpsPresent – gibt zurück, ob eine UPS Stromversorgung am System installiert ist.

· MonitorRequired – gibt zurück, ob das System den Bildschirm benötigt.

· PowerPersonality – gibt das eingestellt Powerscheme zurück – funktioniert nur bei den Windows Default Schemes. „Custom“ Schemes werden nicht erkannt.

· PowerSource – gibt zurück, woher der Computer den Strom bezieht. UPS, Batterie, Power.

· RequestBlockSleep – setzt oder gibt zurück, das verhindert wird, dass der Computer in einen Energiesparzustand geht.

Die Klasse PowerManager hat folgende Events:

· BatteryLifePercentChanged – wird gefeuert, wenn sich der Ladezustand der Batterie ändert.

· IsMonitorOnChanged – wird gefeuert, wenn sich der Monitorstatus ändert.

· PowerPersonalityChanged - wird gefeuert, wenn sich das aktive Powerscheme ändert.

· PowerSourceChanged – wird gefeuert, wenn sich die Energiequelle geändert hat.

· SystemBusyChanged – wird gefeuert, wenn sich das System in einen Ruhezustand begibt oder verlässt.

Die Klasse PowerManager hat folgende Methode:

· GetCurrentBatteryState – gibt den aktuellen Batteriestatus zurück.

Die Klasse Batteriestatus enthält die Zustandsinformationen der Batterie (Ladezustand, erwartet Entladungszeit, … - siehe UI 1 – Battery State).

Weitere PowerManagement Funktionen

Die PowerManagement Klassen geben bis auf eine Funktion einen rein lesenden Zugriff auf die Energiesparfunktionen. Es gibt aber im Windows Betriebssystem noch eine ganze Reihe von weitere API für PowerManagement. Eine Liste, was für WIN32 Funktionen es gibt, findet man hier: http://msdn.microsoft.com/en-us/library/aa373163(v=VS.85).aspx .

Einige dieser Funktionen habe ich im Rahmen eines Projektes benötigt und unter .NET nutzbar gemacht. Diese WIN32 Funktionen sind über den .NET PINVOKE Mechanismus zugreifbar. http://msdn.microsoft.com/en-us/library/aa446536.aspx.

Ein kleine einfache Beispiellösung demonstriert, die Anwendung einiger Funktionen. Die Bedienoberfläche der Anwendung sieht wie folgt aus. Im Beispielprogramm wurde kein Wert auf Fehlerbehandlung, … gelegt.

Die Solution gibt's auf .http://code.msdn.microsoft.com/DNGC

clip_image003

Abbildung 3 PowerSaverSampleCode

Die Anwendung listet alle im Betriebssystem konfigurierten Powerschemes auf und stellt sie in einer Listbox und einer ComboBox dar. Das aktive Powerscheme wird als selektiertes Element in der Listbox dargestellt.

Im Gegensatz zu den Windows API Code Pack werden auch Custom-Schemes mit dem richtigen Namen dargestellt. Wenn man die Auswahl der ComboBox ändert wird das aktive Powerscheme auf die Selektion umgestellt.

Im unteren Teil der Anwendung wird für jeden Processorkern einige Informationen dargestellt. Diese Informationen sind einige der im Windows Betriebssystem vorhanden Performancecounter, die in diesem Fall, die Energeisparzustände der CPU erkennen lassen. Die Taktfrequenz der CPU gibt indirekt Auskunft über Energieverbrauch. Wenn im Computer eine CPU mit Intel SpeedStep Technology ist, kann die CPU bei erkannter Untätigkeit den Taktfrequenz und damit den Energieverbrauch senken http://en.wikipedia.org/wiki/SpeedStep. Wenn der untätige Zustand länger dauert, kann die CPU sogar „geparkt“ werden.

Folgende Funktionen werden zur Realisierung der Bedienoberfläche genutzt:

- Win32.ListPowerSchemes – listet alle im Betriebssystem konfigurierten Powerschemes mit Name und Guid auf (auch für Customschemes).

- Win32. GetCurrentPowerScheme – gibt den Namen, des aktiven Powerschemes zurück (auch für Customschemes).

- Win32.SetPowerScheme – ändert das angegebene Powerscheme.

Die Ermittelung der Anzahl der physischen und logischen CPUs eines Systems kann übers das Property „Enivronment.ProcessorCount“ ermittelt werden. Wenn man mehr Informationen zu den im Computer vorhandenen CPUs benötig, kann man auch die Klasse ROOT.CIMV2.Win32.Processor benutzen. Im nachfolgenden Beispiel wird gezeigt, wie man mit dieser Klasse zum Beispiel die maximale CPU-Frequenz des Computers ermittelt. Auf diese Weise könnte man auch die Anzahl der CPUs ermitteln.

            ROOT.CIMV2.Win32.Processor.ProcessorCollection pColl = ROOT.CIMV2.Win32.Processor.GetInstances();
            if (pColl!=null && pColl.Count > 0)
            {
                foreach (ROOT.CIMV2.Win32.Processor processor in pColl)
                {
                    maxCpuFrequency = processor.MaxClockSpeed;
                    break;
                }
            }

Die Informationen über den Processorzustand können mit Listen von System.Diagnostics.PerfomanceCounter Instanzen gelesen werden. Hier erfolgt die Initialisierung der Performancecounter.

       private void InitPerformanceCounter()
        {
            pcProcessorFreqency = new List<PerformanceCounter>();
            pcProcessorParkingStatus = new List<PerformanceCounter>();

            for ( int i = 0; i < Environment.ProcessorCount; i++ )
            {
                PerformanceCounter pf = new PerformanceCounter();
                pf.BeginInit();
                pf.CategoryName = "Processor Information";
                pf.CounterName = "Processor Frequency";
                pf.InstanceName = "0," + i;
                pf.ReadOnly = true;
                pf.EndInit();

                pcProcessorFreqency.Add( pf );

                pf = new PerformanceCounter();
                pf.BeginInit();
                pf.CategoryName = "Processor Information";
                pf.CounterName = "Parking Status";
                pf.InstanceName = "0," + i;
                pf.ReadOnly = true;
                pf.EndInit();

                pcProcessorParkingStatus.Add( pf );
            }
        }

Es gibt noch einige weitere Funktionen, die für eine Stromsparanwendung sinnvoll sein können.

Mit der folgenden Codesequenz kann man einen Computer in den Schlafzustand bringen:

  Win32.SetSuspendState(false, true, false); 
  Win32.SetSystemPowerState(true, true);  

Wenn im BIOS des Computers die Funktion “Wake on LAN” aktiviert ist, kann solch ein “schlafen gelegter” Computer via LAN Zugriff gestartet werden. Dazu muss ein „magic Packet“ gesendet werden. http://en.wikipedia.org/wiki/Wake-on-LAN.

Mit der Funktion Win32.StopScreenSaverIfRunning kann man einen laufenden Screensaver ausschalten.

        public static void StopScreenSaverIfRunning()
        {
            if ( GetScreenSaverRunning() )
            {
                SendMessage( GetForegroundWindow(), WM_CLOSE, IntPtr.Zero, IntPtr.Zero );
            }
        }

Mit der Funktion Win32. GetScreenSaverRunning kann man den Screensaver einschalten.

        public static bool GetScreenSaverRunning()
        {
            bool isRunning = false;
            SystemParametersInfo( (int) SPI.SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0 );
            return isRunning;
        }

 

GunnarD

Skip to main content