Programmēšana

CPU izmantošanas profilēšana Java lietojumprogrammā

2002. gada 8. novembris

J: Kā jūs varat noteikt CPU izmantošanu Java?

A: Tātad, šeit ir labās un sliktās ziņas. Sliktā ziņa ir tā, ka programmatiski pieprasīt CPU lietošanu nav iespējams, izmantojot tīru Java. Tam vienkārši nav API. Var izmantot ieteikto alternatīvu Runtime.exec () lai noteiktu JVM procesa ID (PID), izsauciet ārēju, platformai raksturīgu komandu, piemēram, ps, un parsē savu produkciju interesējošajam PID. Bet šī pieeja labākajā gadījumā ir trausla.

Labā ziņa ir tā, ka uzticamu risinājumu var panākt, izejot ārpus Java un uzrakstot dažas C koda rindas, kas integrējas ar Java lietojumprogrammu, izmantojot Java Native Interface (JNI). Es parādīšu zemāk, cik viegli tas ir, izveidojot vienkāršu JNI bibliotēku Win32 platformai. Resursu sadaļā ir saite uz bibliotēku, kuru varat pielāgot savām vajadzībām, un piesūtiet citām platformām.

Kopumā JNI ir nedaudz sarežģīti izmantot. Tomēr, zvanot tikai vienā virzienā - no Java uz vietējo kodu - un sazinoties, izmantojot primitīvus datu tipus, viss paliek vienkārši. Par JNI ir daudz labu atsauču (sk. Resursus), tāpēc es šeit nesniedzu JNI apmācību; Es tikai ieskicēju savus ieviešanas soļus.

Es sāku ar klases izveidošanu com.vladium.utils.SystemInformation deklarē vietējo metodi, kas atgriež pašreizējā procesā līdz šim izmantotā CPU laika milisekundu skaitu:

 public static native long getProcessCPUTime (); 

Es izmantoju JDK rīku javah, lai manai nākamajai vietējai ieviešanai izveidotu šādu C galveni:

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

Lielākajā daļā Win32 platformu šo metodi var ieviest, izmantojot GetProcessTimes () sistēmas izsaukums un burtiski ir trīs C koda rindiņas:

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); atgriezties (jlong) ((fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime)) / (s_numberOfProcessors * 10000)); } 

Šī metode pievieno CPU laiku, kas pavadīts kodola un lietotāja koda izpildei pašreizējā procesa vārdā, normalizē to pēc procesoru skaita un rezultātu pārvērš milisekundēs. The fileTimeToInt64 () ir palīga funkcija, kas pārveido FILETIME struktūra līdz 64 bitu veselam skaitlim un s_currentProcess un s_numberOfProcessors ir globālie mainīgie, kurus var ērti inicializēt JNI metodē, kas tiek izsaukta vienreiz, kad JVM ielādē vietējo bibliotēku:

statiskā HANDLE s_currentProcess; static int s_numberOfProcessors; JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * rezervēts) {SYSTEM_INFO systemInfo; s_currentProcess = GetCurrentProcess (); GetSystemInfo (& systemInfo); s_numberOfProcessors = systemInfo.dwNumberOfProcessors; atgriezties JNI_VERSION_1_2; } 

Ņemiet vērā, ka, ja jūs ieviešat getProcessCPUTime () Unix platformā jūs, iespējams, izmantojat getrusage sistēmas izsaukums kā sākumpunkts.

Atgriešanās pie Java, vietējās bibliotēkas ielāde (silib.dll operētājsistēmā Win32) vislabāk var sasniegt, izmantojot statisko inicializētāju Sistēmas informācija klase:

 privāta statiska fināla virkne SILIB = "silib"; statisks {mēģiniet {System.loadLibrary (SILIB); } catch (UnsatisfiedLinkError e) {System.out.println ("native lib" "+ SILIB +" "nav atrodams 'java.library.path':" + System.getProperty ("java.library.path")); iemest e; // atkārtots metiens}} 

Pieraksti to getProcessCPUTime () atgriež CPU laiku, kas izmantots kopš JVM procesa izveides. Pats par sevi šie dati nav īpaši noderīgi profilēšanai. Man ir nepieciešamas vairāk Java metožu, lai dažādos laikos ierakstītu datu momentuzņēmumus un ziņotu par CPU lietošanu starp jebkuriem diviem laika punktiem:

 public static final class CPUUsageSnapshot {private CPUUsageSnapshot (ilgs laiks, ilgs CPUTime) {m_time = laiks; m_CPUTime = CPUTime; } public final long m_time, m_CPUTime; } // ligzdotās klases beigas public static CPUUsageSnapshot makeCPUUsageSnapshot () {return new 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 monitora API" ir gandrīz gatavs lietošanai! Kā pēdējo pieskārienu es izveidoju vienreizēju pavedienu klasi, CPUUsageThread, kas automātiski uzņem datu momentuzņēmumus ar regulāriem intervāliem (pēc noklusējuma 0,5 sekundes) un ziņo par tiem CPU lietošanas notikumu klausītāju kopai (pazīstamais Observer modelis). The CPUmon klase ir demonstrācijas klausītājs, kas vienkārši izdrukā CPU lietojumu System.out:

 public static void main (String [] args) izmet izņēmumu {if (args.length == 0) mest jaunu IllegalArgumentException ("lietojums: CPUmon"); CPUUsageThread monitor = CPUUsageThread.getCPUThreadUsageThread (); CPUmon _this = jauns CPUmon (); Klases lietotne = Class.forName (argumenti [0]); Metode appmain = app.getMethod ("main", jauna klase [] {String []. Klase}); Stīga [] appargs = jauna virkne [args.length - 1]; System.arraycopy (args, 1, appargs, 0, appargs.length); monitor.addUsageEventListener (_šis); monitor.start (); appmain.invoke (null, jauns objekts [] {appargs}); } 

Turklāt CPUmon.main () "ietin" citu Java galveno klasi ar vienīgo mērķi sākt CPUUsageThread pirms sākotnējās lietojumprogrammas palaišanas.

Kā paraugdemonstrējumu es skrēju CPUmon ar SwingSet2 Swing demonstrāciju no JDK 1.3.1 (neaizmirstiet instalēt silib.dll vietā, uz kuru attiecas vai nu CELS OS vides mainīgais vai java.library.path Java īpašums):

> java -Djava.library.path =. -cp silib.jar; (mans JDK instalēšanas rež.) \ demo \ jfc \ SwingSet2 \ SwingSet2.jar CPUmon SwingSet2 [PID: 339] CPU lietojums: 46.8% [PID: 339] CPU lietojums: 51.4% [PID: 339] CPU lietojums: 54,8% (ielādes laikā demonstrācijā tiek izmantoti gandrīz 100% viens no diviem manas mašīnas CPU) ... [PID: 339] Procesora lietojums: 46,8% [PID: 339] Procesora lietojums: 0% [PID: 339] CPU lietojums: 0% (demonstrācija ir pabeigusi visu paneļu ielādi un lielākoties dīkstāvē) ... [PID: 339] CPU izmantošana: 100% [PID: 339] CPU izmantošana: 98.4% [PID: 339] CPU lietojums: 97% (es pārslēdzos uz paneli ColorChooserDemo, kurā darbojās intensīva procesora animācija, kurā izmantoti abi mani CPU) ... [PID: 339] Procesora lietojums: 81.4% [PID: 339] Procesora lietojums: 50% [PID : 339] Procesora izmantošana: 50% (es izmantoju Windows NT uzdevumu pārvaldnieku, lai pielāgotu CPU afinitāti "java" procesam, lai izmantotu vienu procesoru) ... 

Protams, es varu skatīties tos pašus lietošanas numurus, izmantojot uzdevumu pārvaldnieku, taču šeit ir tas, ka man tagad ir programmatisks veids, kā ierakstīt tos pašus datus. Tas noderēs ilgstošos testos un servera lietojumprogrammu diagnostikā. Pilna bibliotēka (pieejama resursos) pievieno dažas citas noderīgas vietējās metodes, tostarp vienu procesa PID iegūšanai (integrēšanai ar ārējiem rīkiem).

Vladimirs Roubcovs vairāk nekā 12 gadus ir programmējis dažādās valodās, ieskaitot Java kopš 1995. gada. Pašlaik viņš izstrādā uzņēmuma programmatūru kā Trilogy vecākais izstrādātājs Ostinā, Teksasā. Kodējot izklaides nolūkos, Vladimirs izstrādā programmatūras rīkus, kuru pamatā ir Java baitu kods vai pirmkodu instrumenti.

Uzziniet vairāk par šo tēmu

  • Lejupielādējiet visu bibliotēku, kas pievienota šim rakstam

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

  • JNI specifikācija un konsultācijas

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

  • Lai iegūtu labu pārskatu par JNI, skatiet Stjuarta Daba Haloveja grāmatu Komponentu izstrāde Java platformai (Addison-Wesley, 2001. gada decembris; ISBN0201753065)

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

  • Sadaļā "Java Tip 92Use JVM Profiler Interface for Precise Timing" Jesper Gortz pēta alternatīvu CPU lietošanas profilēšanas virzienu. (Tomēr, izmantojot JVMPI, ir nepieciešams vairāk darba, lai aprēķinātu procesora lietojumu visam procesam, salīdzinot ar šī raksta risinājumu)

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

  • Skatīt Java jautājumi un atbildes rādītāja lapa pilnam jautājumu un atbilžu katalogam

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

  • Lai iegūtu vairāk nekā 100 ieskatīgus Java padomus, apmeklējiet vietni JavaWorld 's Java padomi rādītāja lapa

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

  • Pārlūkot Java kodols sadaļa JavaWorld 's Aktuālais rādītājs

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

  • Saņemiet atbildes uz vairākiem jautājumiem mūsu vietnē Java iesācējs diskusija

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

  • Pierakstieties JavaWorldbezmaksas iknedēļas e-pasta biļeteni

    //www.javaworld.com/subscribe

  • Jūs atradīsit daudz ar IT saistītu rakstu no mūsu māsas publikācijām vietnē .net

Šo stāstu "Procesora lietojuma profilēšana Java lietojumprogrammā" sākotnēji publicēja JavaWorld.

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