[Mortscript]Ustawianie taktowania procesowa w zależności od aktywnej aplikacji

  • 5 Odpowiedzi
  • 3434 Wyświetleń

0 użytkowników i 1 Gość przegląda ten wątek.

*

Offline mr.deimos

  • **
  • 186
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900
Skrypt powstał z potrzeby. Większość z nas używa pewnie sterownika IPM od shkodera ustawiającego taktowanie procesora tosi "na sztywno" an 512 MHz. Po takim zabiegu G900 zachowuje się jak zupełnie inna maszyna :) Tak długo jak jest przez większość czasu uśpiona, nie ma żadnego problemu Ale niestety, jeśli jest włączona przez dłuższy czas na przykład w trakcie słuchania muzyki, to te 512MHz non-stop odbije się na czasie pracy na baterii. Fakt, że na czas słuchania muzyki można uztawić sobie mniejsze taktowanie przy pomocy xGuru (co też do tej pory robiłem), ale jest to nieco denerwujące na dłuższą metę. A dodatkowo, jeśli przy słuchaniu muzyki (ze zmniejszonym taktowaniem) akurat przyjdzie potrzeba napisać sms-a to można się wściec (przynajmniej w tmail-u i przy słuchaniu przez BT).

Wkurzyło mnie to, więc postanowiłem coś z tym zrobić :D Konfiguracja może być nieco kłopotliwa i wymaga pewnej znajomości mortscripta, ale wygląda na to, że spełnia swoje zadanie. Może ktoś będzie w stanie stworzyć coś nieco bardziej przyjaznego dla użytkownika działającego na podobnej zasadzie ;)
Skrypt (a właściwie skrypty) z załącznika działa w uproszczeniu następująco: co sekundę (czas jest konfigurowalny) sprawdza, czy któryś ze skonfigurowanych warunków jest spełniony (np. czy aktywne jest dane okno) i na tej podstawie ustawia prędkość procesora używając xguru.

A mówiąc bardziej szczegółowo:
W załączniku są 4 skrypty:
  • scaller.mscr - główny skrypt, jeśli wszystko działa jak należy to można wrzucić skrót do niego do autostartu
  • config.mscr - zawiera warunki, na podstawie których ustawiane jest taktowanie procesora. Po uruchomieniu wszystkie procedury w nim zawarte i tak są importowane do skryptu głównego, ale ze względu na przejrzystość i wygodę postanowiłem oddzielić tą część od głównej.
  • closeScaller.mscr - jak sama nazwa wskazuje - kończy sktypt skalujący taktowanie procesora - wolałem przygotować coś takiego na wszelki wypadek ;)
  • helper.mscr - sprawdza, czy scaller.mscr jest uruchomiony i w zależności od tego pozwala na jego zakończenie, uruchomienie lub zrestartowanie (koniczne po zmianie konfiguracji). Skrypt ten pozwala także na sprawdzenie (i skopiowanie do schowka) nazwy wybranego okna i nazwy odpowiedzialnego za nie procesu. Może się to przydać przy konfiguracji.
Proponuję wszystko rozpakować w pamięci głównej, np. do /Program Files. Oczywiście konieczne będzie też zainstalowanie mortscripta (o ile nie jest już zainstalowany lub wgotowany w rom).

Żeby wyjaśnić jak używać tego skryptu należałoby zacząć od wyjaśnienia w jaki sposób korzysta on z xGuru.
Program ten umożliwia wybór prędkości z poziomu wiersza poleceń. Składnia to xguru.exe #<numer ustawienia>, np xguru.exe #3. Numery ustawień można sprawdzić w menu xguru (pojawia się po odpaleniu go bez żadnego parametru) w sekcji speed/remove from menu lub speed/add to menu. Na przykład u mnie wygląda to tak:

Czyli parametr #1 ustawi 208MHz, #3 - 312MHz, #6 - 512MHz.


Na początku trzeba zadeklarować w ustawieniach skryptu scaller.mscr z których ustawień xguru planujemy korzystać. Domyślna konfiguracja wygląda następująco:
SpeedSetting["default"]=5
SpeedSetting[1]=6
SpeedSetting[2]=3
Oznacza to, że korzystam z 3 ustawień prędkości: 5 oznaczające 442MHz jest prędkością domyślną ustawioną przez większość czasu. 6 i 3, czyli 512 i 312MHz są prędkościami ustawianymi kiedy spełnione będą pewne kryteria. Xguru obsługuje do 8 ustawień prędkości, ten skrypt też byłby w stanie tyle obsłużyć. Wystarczyłoby zadeklarować dodatkowe prędkości jako SpeedSetting[3], SpeedSetting[4] itp.
Warunki, na podstawie których ustawiana jest jedna z tych prędkości są zdefiniowane w pliku config.mscr. Każdy z warunków ma postać procedury mortscripta:
Sub SpeedX_AppsettingY
<code>
Return(BOOL)
endSub
gdzie X jest numerem ustawienia prędkości xguru, która ma być wybrana kiedy warunek jest spełniony.
Y jest kolejnym numerem warunku dla danej prędkości (numeracja zaczyna się od 1 i musi być ciągła: 2, 3, 4 itp.).
Czyli jeśli używamy dwóch ustawień prędkości (3 i 6) i dla obu mamy po dwa warunki, to config.mscr powinien zawierać cztery procedury: Speed3_AppSetting1, Speed3_AppSetting2, Speed6_AppSetting1 oraz Speed6_AppSetting2. Dla każdej prędkości zadeklarowanej przez SpeedSetting* musi istnieć przynajmniej jeden warunek.
<code> może być dowolnym kodem mortscripta - może to byś sprawdzanie czy dane okno jest aktywne, czytanie rejestru - jakikolwiek poprawny kod mortscripta. Oczywiście lepiej za mocno go nie komplikować - w końcu te procedury są wywoływane dość często i nie powinny zajmować za dużo czasu CPU ;)
Każda procedura musi zwracać wartość logiczną TRUE lub FALSE (albo 0 jako false lub liczbę różną od zera jako true) jako argument funkcji Return()
Jeśli procedura zwraca TRUE, odpowiadająca jej prędkość jest ustawiana, w przeciwnym przypadku nie.

Przykład:
Sub Speed3_AppSetting1
Return(WndActive("Desktop"))
EndSub
WndActive("Desktop") zwróci wartość TRUE kiedy aktywny jest ekran Today. Wobec tego sens całej procedury jest taki, że kiedy aktywny jest ekran Today, ustawiona zostanie prędkość 3 (czyli 312MHz).

Ale możliwości są znacznie większe, na przykład:
Sub Speed6_AppSetting2
ActiveProc=ActiveProcess()
Return(ActiveProc eq "tmail.exe" && WndActive("SMS \ MMS") && screen("landscape"))
EndSub
Ten warunek z kolei spowoduje ustawienie prędkości 6, czyli 512MHz kiedy aktywna jest aplikacja tmail.exe, a konkretnie okno SMS/MMS, ale tylko wtedy kiedy ekran jest w orientacji poziomej, czyli kiedy jest rozłożona klawiatura. Jeśli klawiatura jest złożona, warunek nie jest spełniony i procesor będzie taktowany domyślną prędkością.
Kilka innych przykładów jest skonfigurowanych w pliku config.mscr

Po skonfigurowaniu procedur trzeba jeszcze podać ile ich jest dla poszczególnych ustawień prędkości. Odpowiadają za to ustawienia z pliku scaller.mscr:
NumApps[3]=2
NumApps[6]=3
Liczba w nawiasach kwadratowych jest numerem ustawienia xguru. liczba po znaku równości ilością skonfigurowanych dla niej warunków w config.mscr. Ilość warunków musi być zdefiniowana dla każdej zadeklarowanej wcześniej prędkości (SpeedSetting*).

Pozostałe ustawienia:
xGuruPath="\Windows"Ścieżka do xguru. Jeśli program jest wgotowany to siedzi w \windows. Nie jestem pewien gdzie trafi jeśli jest instalowany z caba.

CheckDelay=1000Czas jaki mija pomiędzy kolejnym sprawdzaniem czy któryś z warunków zdefiniowanych w config.mscr jest spełniony (w milisekundach). Ustawione domyślnie dwie sekundy wydają się rozsądną wartością. Jeśli użyje się  wielu ustawień prędkości/warónków, może nie zaszkodzi nieco zwiększyć tego czasu.

ShowSpeedChanges=FALSEPo ustawieniu na True przy każdym wywołaniu xguru będzie wyświetlane przez sekundę okno informujące o ustawionej prędkości. Przydaje się do sprawdzenia, czy nowo skonfigurowany warunek działa jak należy.

W celu ograniczenia zużycia zasobów Xguru jest uruchamiany tylko wtedy, kiedy jest taka potrzeba (czyli kiedy trzeba zmienić prędkość). Prędkości zdefiniowane jako późniejsze w tablicy SpeedSetting* mają wyższy priorytet. Na przykład, jeśli przy prędkościach zdefiniowanych w przykładzie spełnione byłyby warunki:

Sub Speed3_AppSetting2
ActiveProc=ActiveProcess()
Return(ActiveProc eq "tmail.exe")
EndSub

Sub Speed6_AppSetting2
ActiveProc=ActiveProcess()
Return(ActiveProc eq "tmail.exe" && WndActive("SMS \ MMS") && screen("landscape"))
EndSub
(Oba będą spełnione jeśli będzie aktywne okno SMS/MMS programu tmail, ponieważ aktywnym procesem jest też wtedy tmail.exe), ustawiona zostałaby prędkość #3, czyli 312MHz ponieważ została ona zadeklarowana z wyższym indeksem w tablicy SpeedSetting.

Z pobieżnych testów wynika, że  działający cały czas w tle skrypt zużywa w porywach do 6% czasu procesora (a przez większość czasu jest uśpiony, czyli 0%), więc nie powinien spowodować jakichkolwiek zauważalnych spowolnień. Oczywiście wszystko zależy od ilości zdefiniowanych warunków, ale mimo wszystko zużycie czasu CPU nie powinno być zbyt wysokie.
Aha, skrypt i komentarze są po angielsku. Po prostu nie lubię się przerzucać między językami (np. komendy po angielsku, nazwy zmiennych i komentarze po polsku) - takie durne przyzwyczajenie. Dlatego starałem się pisać wszystko tutaj.

Uff, to chyba byłoby tyle - opis zajął chyba więcej czasu niż tworzenie samego skryptu :P mam nadzieje że wyszło toto w miarę zrozumiale i komuś się przyda :)
« Ostatnia zmiana: Czerwiec 20, 2009, 00:14:28 wysłana przez mr.deimos »

*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Ale mi wygląda, że masz błąd jednak. W tej pętli foreach przelatujesz wszystkie funkcje testujące począwszy od najwyższego progu ustawienia ( 6 przy Twoim konfigu ) i ustawiasz SpeedChange=spd_iter w zależnosci od rezultatu testu warunku. Rozważ scenariusz: najpierw funkcja wyższego warunku głosuje za poziomem 6 a potem niższego za poziomem 3 W rezultacie otrzymujesz poziom 3 jako prędkość do ustawienia. Wszystko działa oczywiście poprawnie, dopóki warunki nie aktywują się jednocześnie, co jednak przy możliwości konfiguracji dostarczonej przez użytkowników nie musi być spełnione.
Druga uwaga - niepotrzebnie przelatujesz wszystkie testy z każdym razem kiedy sprawdzasz.

Możesz np zrobić tak - na początku skryptu jednorazowo obliczasz te nazwy funkcji:

conds[0]=""
nCond=0

#   Cycling trough all used speed settings.   spd_iter - speed setting iterator
   ForEach spd_iter in array (SpeedSetting)
#      Cycling trough all app settings (from config.mscr)   
      For AppNum=1 to NumApps[spd_iter]
         conds[nCond]="Speed" & spd_iter & "_AppSetting" & AppNum
         nCond+=1
      Next
   EndForEach

A potem w pętli głównej sprawdzasz:

   i=0  ret=false
   While ( i<nCond and not ret )
      CallFunction(conds,ret)
      If(ret <> FALSE)
         SpeedChange=spd_iter
      EndIf
      i+=1
   EndWhile
   
W tym miejscu wiesz pewnie co dalej więc nie będę się rozpisywał :)

Masz tutaj ograniczenie w wywoływaniu tych funkcji testujących oraz operacje sklejania napisów usuwasz poza pętlę. Testy robisz dość często więc zawsze to jakaś oszczędność :)

*

Offline mr.deimos

  • **
  • 186
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900
Ale mi wygląda, że masz błąd jednak. W tej pętli foreach przelatujesz wszystkie funkcje testujące począwszy od najwyższego progu ustawienia ( 6 przy Twoim konfigu ) i ustawiasz SpeedChange=spd_iter w zależnosci od rezultatu testu warunku. Rozważ scenariusz: najpierw funkcja wyższego warunku głosuje za poziomem 6 a potem niższego za poziomem 3 W rezultacie otrzymujesz poziom 3 jako prędkość do ustawienia.
Właściwie to takie zachowanie jest zamierzone. Pod koniec poprzedniego postu napisałem, że prędkości zdefiniowane później mają wyższy priorytet. Ale kolejność definicji prędkości jest dowolna - możesz sobie zadeklarować prędkość 512MHz jako drugą, dzięki czemu będzie miała wyższy priorytet i w razie wątpliwości to ona zostanie wybrana.
Pętla sprawdzająca warunki przelatuje przez ustawienia prędkości w kolejności ich zadeklarowania. Więc w moim przypadku najpierw jest testowany warunek na prędkość '6', później na prędkość '3'. Jeśli pierwszy warunek zostanie spełniony, do SpeedChange jest przypisywana aktualna wartość spd_iter. Może nazwałem tą zmienną dość niefortunnie,bo tak na prawdę nie będzie ona iteratorem, a zawartością kolejnych pój tablicy SpeedSetting (od pierwszego aż do ostatniego niepustego). Wobec tego przy pierwszym przejściu pętli SpeedChange może u mnie zostać ustawiony na '6'. Jeśli przy drugim przejściu któryś z warunków będzie spełniony to SpeedChange zostanie nadpisany wartością '3'. I właśnie coś takiego chciałem uzyskać. Możesz dzięki temu np. stworzyć warunek ustawiający prędkość 512MHz jeśli jest włączony odtwarzacz, oraz drugi ustawiający 312 jeśli jest włączony odtwarzacz i odtwarzanie jest zatrzymane. Kiedy odtwarzacz faktycznie gra, spełniony jest tylko jeden warunek (na 512MHz), więc nie ma problemu. Kiedy zatrzymamy film/muzykę, spełnione są oba ((odtwarzacz jest aktywny) i (jest aktywny i nie odtwarza)). Wobec tego zostaje ustawiona prędkość z wyższym priorytetem, czyli 312MHz w moim przypadku.

Cytuj
Druga uwaga - niepotrzebnie przelatujesz wszystkie testy z każdym razem kiedy sprawdzasz.
Hmm, niezbyt rozumiem o co chodzi z niepotrzebnym przelatywaniem wszystkich testów - robione są tylko te, które są wymagane (wynika to z zadeklarowanych w tablicy SpeedSettings* prędkości i ilości ustawień dla każdej z nich (NumApps*).
Co do każdorazowego generowania nazw funkcji "w locie" - faktycznie, można to załatwić na początku. Dzięki za podpowiedź :)

Aha, oczywiście równie dobrze można wszystkie warunki dla danej prędkości wwalić do jednej funkcji, która na podstawie ich wszystkich zwróci TRUE lub FALSE, ale uznałem, że rozbicie tego na wiele warunków będzie łatwiejsze dla mniej doświadczonych użytkowników mortscripta.

*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Podział warunków na osobne funkcje akurat uważam za dobry pomysł. I kod jest czysty w ten spośób
Z tym "przelatywaniem" chodziło mi o to, że wywołujesz wszystkie funkcje testowe ( zdefiniowane w konfigu ) nawet jeśli ta logika działania jest taka jak piszesz, to faktycznie możesz tego uniknąć ( iterujesz od końca tej tablicy co podrzuciłem ) Ale spójrz na całe zagadnienie Mamy w istocie taką przykładową tabelkę

Aktywne warunki ( dające w danym momencie true ):

Warunek ( ID, np po nazwie funkcji )  Zapotrzebowanie na prędkość

C1,   6
C2,   5
C3,   3

Najbardziej logiczne jest wybieranie prędkości jako maksimum ( najwyższej ) z drugiej kolumny, a nie na podstawie jakiś dziwnie dobieranych sekwencji. Bo z tego co piszesz to mi wygląda, że miałeś taki pomysł żeby te warunki były niezależne od siebie. Np user1 tworzy swój zestaw user2 swój i obaj mogą się wymieniać/dzielić poszczególnymi warunkami w razie potrzeby.

*

Offline mr.deimos

  • **
  • 186
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900
Z tym "przelatywaniem" chodziło mi o to, że wywołujesz wszystkie funkcje testowe ( zdefiniowane w konfigu ) nawet jeśli ta logika działania jest taka jak piszesz, to faktycznie możesz tego uniknąć
Ok, już załapałem - faktycznie masz rację. Jak będę miał chwilę to poprawię i wrzucę nową wersję :)

Cytuj
Najbardziej logiczne jest wybieranie prędkości jako maksimum ( najwyższej ) z drugiej kolumny, a nie na podstawie jakiś dziwnie dobieranych sekwencji. Bo z tego co piszesz to mi wygląda, że miałeś taki pomysł żeby te warunki były niezależne od siebie. Np user1 tworzy swój zestaw user2 swój i obaj mogą się wymieniać/dzielić poszczególnymi warunkami w razie potrzeby.
Tak właściwie to skrypt powstał do użytku własnego - wkurzały mnie problemy z sms-ami przy underclockingu i A2DP ;)
Akurat ten definiowalny priorytet prędkości to zostawię, bo bardziej mi zależy na oszczędności baterii niż maksymalnej wydajności, a to nie każdemu musi pasować. Dlatego jak ktoś ze skryptu skorzysta to będzie mógł sam sobie ustawić z jakich prędkości chce korzystać i które mają być najważniejsze.
A sam skrypt raczej nie nadaje się do wymieniania się konfiguracjami - według mnie w momencie kiedy konfig zawiera więcej niż jakieś 30 warunków całość przestaje mieć sens. Do takiego zastosowania najlepiej byłoby napisać program o podobnym działaniu i z solidnym graficznym konfiguratorem. Byłoby to znacznie szybsze i mniej zasobożerne niż interpretowany na bieżąco mortscript. Ale sklecenia czegoś takiego to już niestety się nie podejmę. Po pierwsze - prawdopodobnie niedługo się z G900 rozstanę (krótki odpoczynek od WinMo ;) ), a pod drugie - taki program w moim wykonaniu nie byłby zbyt wydajny i prawdopodobnie nie do końca stabilny - pod WinMo praktycznie w ogóle nie programowałem więc nieco brak mi doświadczenia w tej kwestii :)

*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Twój pomysł na odpalanie xguru jest całkiem sensowny i może być nie tylko na tosi wykorzystany. Xguru pracuje przecież także na innych PDA. Paradoksalnie taki program z konfiguratorem mógłby być gorszy bo tutaj w warunkach masz dostęp do wszystkiego (mówię o funkcjach) a tak to jakieś uproszczone warunki wchodziłyby w grę. Sprawdzanie warunków co jedna 1s to za bardzo nie powinno proca obciążyć Twoim skryptem