Blog

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Fejlesztői beszélgetéseken sokszor előkerül, hogy időmérésre a Calendar használata kerülendő, mivel túl sok erőforrást igényel a példányosítás, illetve a használata. A fejlesztők ebből az okból jobban szeretik a System osztály currentTimeMillis metódusát használni, amely egyszerű UNIX időbélyeget ad vissza. A tesztelés egyszerű, mérjünk meg, hogy az egyes módszerek mennyi időt vesznek el a program életéből. A mérési keretrendszer egyszerű, ciklusban lekérdezzük egy tömbbe az időbélyegeket:

Code Block
languagejava
linenumberstrue
long[] result = new long[10000000];
for (int count = 0; count < 10000000; count++)
{
  Calendar cal = Calendar.getInstance();
  result[count] = cal.getTimeInMillis();
}
System.out.println("" + (result[9999999] - result[0]) + " ms");

A másik módszer egyszerűbbnek néz ki, de a végeredmény azonos lesz:

Code Block
languagejava
linenumberstrue
long[] result = new long[10000000];
for (int count = 0; count < 10000000; count++)
{
  result[count] = System.currentTimeMillis();
}
System.out.println("" + (result[9999999] - result[0]) + " ms");

Hívjuk meg többször egymás után a fenti programrészleteket, hogy a JVM is fel tudjon pörögni, és nézzük meg az utolsó pár hívás átlagát:

  • Ötször mért 10 millió System.currentTimeMillis() hívás átlaga 12000 ms, egy hívás 1200 ns
  • Ötször mért 10 millió Calendar.getInstance() hívás átlaga 21000 ms, egy hívás 2100 ns

A mérés szerint a Calendar használata 75 százalékkal lassabb, mint a System hívás, ám ez a különbség érthető a példányosítás okán, hiszen a Calendar (vagyis egy GregorianCalendar) példány is egy System.currentTimeMillis() hívás alapján állítja be a belső változóit. Java 5.0 óta elérhető egy új metódus is a System osztályban, amely egymilliószor pontosabb mérést tesz lehetővé: a nanoTime. Igazából csak a lehetősége van meg, hogy nano másodperc felbontással mérjünk eltelt időt, jelenleg nincs olyan architektúra, amely támogatná egy ilyen felbontású idő mérését, bár a processzorok órajele már meghaladta a szükséges 1GHz értéket.

Nos, mérjünk újra és számoljuk ki ismét az utolsó pár mérési eredmény átlagát:

Code Block
languagejava
linenumberstrue
    long[] result = new long[10000000];
    for (int count = 0; count < 10000000; count++)
    {
      result[count] = System.nanoTime();
    }
    System.out.println("" + (result[9999999] / 1000000 - result[0] / 1000000) + " ms");

Az eredmény:

  • Ötször mért 10 millió System.currentTimeMillis() hívás átlaga 12000 ms, egy hívás 1200 ns
  • Ötször mért 10 millió Calendar.getInstance() hívás átlaga 21000 ms, egy hívás 2100 ns
  • Ötször mért 10 millió System.nanoTime() hívás átlaga 14000 ms, egy hívás 1400 ns

A nanoTime metódus mintegy 15-20 százalékkal lassabb, mint a currentTimeMillis metódus, ám a felbontása még átlagos gépen is használhatóbb eredményt ad. Ezt alátámasztandó, nézzük meg a letárolt értékek első tíz elemét System.currentTimeMillis() hívás esetén:

1247913669850
1247913669850
1247913669850
1247913669850
1247913669850
1247913669850
1247913669850
1247913669850
1247913669850
1247913669850

Ugyanez System.nanoTime() hívás esetén:

74858347480430
74858347481896
74858347483363
74858347484830
74858347486296
74858347487763
74858347489230
74858347490627
74858347492093
74858347493490

Láthatjuk, hogy az utóbbi esetben szépen tükröződik a 1400 ns ideig tartó hívás, míg az előbbi esetben azt láthatjuk, hogy az amúgy 1200 ns ideig tartó hívásból kell 800 darab, míg más értéket ad vissza a metódus.