2012. május 9., szerda

nanotime

Olykor szükségünk lehet arra, hogy megmérjük, mennyi ideig hajtódott végre egy függvényünk. Erre a System osztályban van 2 hasznos statikus metódus. Egyfelől van a currentTimeMillis(), ami milliszekundumban adja vissza az aktuális időt, illetve van a nanoTime(), ami viszont már nanoszekundumos pontossággal. Csak hogy átlássuk az SI mértékegység-rendszer releváns részét:

milli: 10-3
mikro: 10-6
nano:  10-9

Vagyis 1 nanoszekundum = 10-9 másodperc.

A mérési feladat elég szimpla:
long t = System.nanoTime();
valami();
t = System.nanoTime() - t;

És meg is kapjuk, hogy a függvény hány nanoszekundum alatt futott le. Ezzel csak az a baj, hogy ha kiíratunk egy ilyen számot önmagában, ránézésre nem egyszerű megmondani, hogy most ez hány másodperc vagy esetleg perc volt. Érdemes tehát kreálni egy függvényt, ami szépen megformázza ezt a long-ot, és kiköhög nekünk egy olvasható String-et. :-)

/**
 * Transforms a time in nanoseconsds to a readable text.
 * Output format: MM:SS.MS,mS'nS
 * @param time Time to format.
 * @param showMicro Include microseconds in the text?
 * @param showNano Include nanoseconds in the text?
 * @return The time as text.
 */
public static String formatNanoTime(long time,
                                    boolean showMicro,
                                    boolean showNano) {
    long nanosec = time % 1000;
    long microsec = (time / 1000) % 1000;
    long millisec = (time / 1000 / 1000) % 1000;
    long sec = (time / 1000 / 1000 / 1000) % 60;
    long min = (time / 1000 / 1000 / 1000 / 60);

    String r = lpad(Long.toString(min), 2, '0') + ":"
     + lpad(Long.toString(sec), 2, '0') + "."
     + lpad(Long.toString(millisec), 3, '0');
    if (showMicro) {
        r += "," + lpad(Long.toString(microsec), 3, '0');
    }
    if (showMicro && showNano) {
        r += "`" + lpad(Long.toString(nanosec), 3, '0');
    }
    return r;
}

Nem volt kis meló összerakni az osztásokat, maradékképzéseket... izzadtam vele egy ideig, de sikerült. :-)
Az lpad(String, int, char) függvényem annyit csinál, hogy jobbról kiegészíti a szöveget a megadott karakterrel, a megadott hosszúságra. Ezt nem illesztem be, 3 soros ujjgyakorlat.

2 megjegyzés:

rlegendi írta...

Hali!

A microbenchmarkkal vigyázzunk, főleg a Java kapcsán. Csomó probléma felmerülhet. Pl. a nanoTime() kiváló, de OS szintű hívás kell hozzá, ami meg 100 microsec alatt hajtódik végre (a currentTimeMilis() meg egy OS változót olvas ki, az gyorsabb, viszont az meg viszonylag ritkán frissül :-)

Egy jó kis leírást találsz itt a problémáról, ebben meg az úriember bemutat egy jó kis API-t ehhez.

juzraai írta...

Hali!

Hű, köszi, nagyon komoly a cikk! Ezt a Brenchmark API-t majd kipróbálom.

Amúgy én is sejtettem, hogy a nanoTime() esetében van egy kis turpisság a háttérben, de valóban, a currentTimeMillis() nem mindig elég. :-)