Programovanie

Profilovanie využitia procesora z aplikácie Java

8. novembra 2002

Otázka: Ako určíte využitie procesora v prostredí Java?

A: Takže, tu sú dobré správy a zlé správy. Zlou správou je, že programové dopytovanie po CPU nie je možné pomocou čistej Javy. Na to jednoducho neexistuje API. Môže sa použiť navrhovaná alternatíva Runtime.exec () na určenie ID procesu (PID) JVM zavolajte externý príkaz špecifický pre platformu psa analyzovať jeho výstup na záujmový PID. Tento prístup je však prinajlepšom krehký.

Dobrou správou však je, že spoľahlivé riešenie je možné dosiahnuť tak, že vystúpite z prostredia Java a napíšete niekoľko riadkov kódu C, ktoré sa integrujú s aplikáciou Java cez natívne rozhranie Java (JNI). Nižšie uvádzam, aké ľahké je to vytvorením jednoduchej knižnice JNI pre platformu Win32. Sekcia Zdroje obsahuje odkaz na knižnicu, ktorú si môžete prispôsobiť pre svoje vlastné potreby, a na port k iným platformám.

Všeobecne je JNI trochu zložité na použitie. Keď však voláte iba jedným smerom - z Javy do natívneho kódu - a komunikujete pomocou primitívnych dátových typov, zostáva to jednoduché. Na JNI existuje veľa dobrých referencií (pozri Zdroje), takže tu neposkytujem výukový program JNI; Iba načrtnem moje implementačné kroky.

Začínam vytvorením triedy com.vladium.utils.SystemInformation ktorá deklaruje natívnu metódu, ktorá vracia počet milisekúnd času procesora, ktorý aktuálny proces doteraz použil:

 public static native long getProcessCPUTime (); 

Používam nástroj javah z JDK na vytvorenie nasledujúcej hlavičky C pre svoju budúcu natívnu implementáciu:

JNIEXPORT jlong ​​JNICALL Java_com_vladium_utils_SystemInformation_getProcessCPUTime (JNIEnv * env, jclass cls) 

Na väčšine platforiem Win32 možno túto metódu implementovať pomocou GetProcessTimes () systémové volanie a sú to doslova tri riadky kódu C:

JNIEXPORT jlong ​​JNICALL Java_com_vladium_utils_SystemInformation_getProcessCPUTime (JNIEnv * env, jclass cls) {FILETIME creationTime, exitTime, kernelTime, userTime; GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime); return (jlong) ((fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime)) / (s_numberOfProcessors * 10 000)); } 

Táto metóda zvyšuje čas procesora strávený vykonávaním kódu jadra a používateľa v mene súčasného procesu, normalizuje ho podľa počtu procesorov a prevádza výsledok na milisekundy. The fileTimeToInt64 () je pomocná funkcia, ktorá prevádza FILETIME štruktúra na 64-bitové celé číslo a s_currentProcess a s_numberOfProcessors sú globálne premenné, ktoré sa dajú pohodlne inicializovať v metóde JNI, ktorá sa volá raz, keď JVM načíta natívnu knižnicu:

static HANDLE s_currentProcess; static int s_numberOfProcessors; JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * rezervované) {SYSTEM_INFO systemInfo; s_currentProcess = GetCurrentProcess (); GetSystemInfo (& systemInfo); s_numberOfProcessors = systemInfo.dwNumberOfProcessors; návrat JNI_VERSION_1_2; } 

Upozorňujeme, že ak implementujete getProcessCPUTime () na platforme Unix by ste pravdepodobne používali getrusage systémový hovor ako váš východiskový bod.

Vraciame sa k Java, načítam natívnu knižnicu (silib.dll na Win32) je najlepšie dosiahnuť pomocou statického inicializátora v Systémové informácie trieda:

 súkromný statický konečný reťazec SILIB = "silib"; static {try {System.loadLibrary (SILIB); } catch (UnsatisfiedLinkError e) {System.out.println ("native lib '" + SILIB + "" sa nenašiel v' java.library.path ': "+ System.getProperty (" java.library.path ")); hod e; // opätovné vyhodenie}} 

Poznač si to getProcessCPUTime () vráti čas CPU použitý od vytvorenia procesu JVM. Samotné tieto údaje nie sú zvlášť užitočné na profilovanie. Potrebujem viac užitočných metód Java na zaznamenávanie dátových snímok v rôznych časoch a hlásenie využitia procesora medzi dvoma časovými bodmi:

 verejná statická konečná trieda CPUUsageSnapshot {súkromná CPUUsageSnapshot (dlhá doba, dlhá CPUTime) {m_time = čas; m_CPUTime = CPUTime; } verejné posledné dlhé m_time, m_CPUTime; } // koniec vnorenej triedy public static CPUUsageSnapshot makeCPUUsageSnapshot () {vrátiť nový CPUUsageSnapshot (System.currentTimeMillis (), getProcessCPUTime ()); } public static double getProcessCPUUsage (CPUUsageSnapshot start, CPUUsageSnapshot end) {return ((double) (end.m_CPUTime - start.m_CPUTime)) / (end.m_time - start.m_time); } 

„CPU monitor API“ je takmer pripravené na použitie! Na záver vytvorím triedu vlákien singleton, CPUUsageThread, ktorá automaticky sníma údajové snímky v pravidelných intervaloch (predvolene 0,5 sekundy) a hlási ich množine poslucháčov udalostí využívania CPU (známy vzor pozorovateľa). The CPUmon class je demonštračný poslucháč, ktorý jednoducho vytlačí využitie CPU na System.out:

 public static void main (String [] args) vyvolá Exception {if (args.length == 0) throw new IllegalArgumentException ("usage: CPUmon"); CPUUsageThread monitor = CPUUsageThread.getCPUThreadUsageThread (); CPUmon _this = nový CPUmon (); Aplikácia triedy = Class.forName (args [0]); Metóda appmain = app.getMethod ("main", nová trieda [] {reťazec []. Trieda}); Reťazec [] zariadenia = nový Reťazec [args.length - 1]; System.arraycopy (args, 1, prístroje, 0, prístroje. Dĺžka); monitor.addUsageEventListener (_this); monitor.start (); appmain.invoke (null, new Object [] {applgs}); } 

Navyše, CPUmon.main () "zabalí" ďalšiu hlavnú triedu Java s jediným účelom spustenia CPUUsageThread pred spustením pôvodnej aplikácie.

Ako ukážka som bežal CPUmon s ukážkou SwingSet2 Swing od JDK 1.3.1 (nezabudnite si nainštalovať silib.dll na miesto pokryté buď CESTA Premenná prostredia OS alebo java.library.path Vlastnosť Java):

> java -Djava.library.path =. -cp silib.jar; (môj inštalačný adresár JDK) \ demo \ jfc \ SwingSet2 \ SwingSet2.jar CPUmon SwingSet2 [PID: 339] využitie CPU: 46,8% [PID: 339] využitie CPU: 51,4% [PID: 339] CPU využitie: 54,8% (pri načítaní demo využíva takmer 100% jedného z dvoch CPU na mojom stroji) ... [PID: 339] využitie CPU: 46,8% [PID: 339] využitie CPU: 0% [PID: 339] Využitie CPU: 0% (ukážka dokončila načítanie všetkých svojich panelov a je väčšinou nečinná) ... [PID: 339] Využitie CPU: 100% [PID: 339] Využitie CPU: 98,4% [PID: 339] CPU využitie: 97% (prešiel som na panel ColorChooserDemo, na ktorom bola spustená animácia náročná na procesor, ktorá využívala obidva moje procesory) ... [PID: 339] využitie CPU: 81,4% [PID: 339] využitie CPU: 50% [PID : 339] Využitie procesora: 50% (pomocou Správcu úloh systému Windows NT som upravil afinitu procesora pre proces „java“ tak, aby používal jeden procesor) ... 

Rovnaké čísla použitia samozrejme môžem sledovať prostredníctvom správcu úloh, ale tu ide o to, že teraz mám programový spôsob zaznamenávania rovnakých údajov. Bude sa hodiť pre dlhodobé testy a diagnostiku serverových aplikácií. Celá knižnica (k dispozícii v zdrojoch) pridáva niekoľko ďalších užitočných natívnych metód, vrátane metódy na získanie PID procesu (pre integráciu s externými nástrojmi).

Vladimir Roubtsov programuje viac ako 12 rokov v rôznych jazykoch vrátane Javy od roku 1995. V súčasnosti vyvíja podnikový softvér ako senior vývojár pre Trilogy v texaskom Austine. Pri kódovaní pre zábavu Vladimir vyvíja softvérové ​​nástroje založené na kódovaní bajtov Java alebo prístrojovom vybavení zdrojového kódu.

Získajte viac informácií o tejto téme

  • Stiahnite si kompletnú knižnicu, ktorá je priložená k tomuto článku

    //images.techhive.com/downloads/idge/imported/article/jvw/2002/11/01-qa-1108-cpu.zip

  • Špecifikácia JNI a návody

    //java.sun.com/j2se/1.4/docs/guide/jni/index.html

  • Dobrý prehľad o JNI nájdete v dokumente Stuarta Dabbsa Hallowaya Vývoj komponentov pre platformu Java (Addison-Wesley, december 2001; ISBN0201753065)

    //www.amazon.com/exec/obidos/ASIN/0201753065/javaworld

  • V časti „Java Tip 92Použite rozhranie JVM Profiler na presné načasovanie“ Jesper Gortz skúma alternatívny smer profilovania využitia CPU. (Používanie JVMPI si však vyžaduje viac práce s výpočtom využitia procesora pre celý proces v porovnaní s riešením tohto článku)

    //www.javaworld.com/javaworld/javatips/jw-javatip92.html

  • Viď Java Q&A indexová stránka pre úplný katalóg otázok a odpovedí

    //www.javaworld.com/columns/jw-qna-index.shtml

  • Viac ako 100 bystrých tipov pre jazyk Java nájdete na stránke JavaWorld 's Tipy pre Java indexová stránka

    //www.javaworld.com/columns/jw-tips-index.shtml

  • Prejdite si Core Java časť JavaWorld 's Aktuálny index

    //www.javaworld.com/channel_content/jw-core-index.shtml

  • Získajte viac odpovedí na vaše otázky v našom Java začiatočník diskusia

    //forums.devworld.com/webx?50@@.ee6b804

  • Zaregistrovať JavaWorldbezplatné týždenné e-mailové bulletiny

    //www.javaworld.com/subscribe

  • Množstvo článkov týkajúcich sa IT z našich sesterských publikácií nájdete na .net

Tento príbeh, „Profilovanie využitia procesora v rámci aplikácie Java“, bol pôvodne publikovaný spoločnosťou JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found