Java: WallClock versus System.currentTimeMillis

Como de costoso es llamar a System.currentTimeMillis()?

Si tenemos una función dependiente del tiempo y a esa funcion la llamamos, digamos… 500.000.000 veces y tarda 9911ms; hay alguna manera de hacer que sea más rápido? Bueno, si eludimos la llamada al reloj del sistema mediante un pequeño cache puede que ganemos unos segundos…

Esto sería el esqueleto del sistema, un thread que actualiza el reloj a intervalos regulares y una funcion q devuelve el último valor conocido:

public class WallClock implements Runnable {
  private static final int clockLatency = 1;  // WallClock time refresh (millis)
  private static WallClock self = null;       // Singleton
  private volatile long lastTimeMillis = 0L;  // Last time cached from SystemClock
  private volatile Thread clocker = null;     // WallClock Thread

  public static synchronized WallClock getInstance() {
    if (self == null) {
      self = new WallClock();
      self.init();
    }
    return self;
  }

  public long currentTimeMillis() {
    return lastTimeMillis;
  }

  private void init() {
    if (clocker == null) {
      clocker = new Thread(this);
      clocker.setDaemon(true);
      clocker.start();
    }
  }
  public void destroy() {
    clocker.interrupt();
  }

  /**
   * Run, baby, run
   */
  public void run() {
    try {
      while (!Thread.currentThread().isInterrupted()) {
        lastTimeMillis = System.currentTimeMillis();
        Thread.sleep(clockLatency);
      }
    } catch (InterruptedException ie) {
      /* Allow thread to exit */
    } finally {
      clocker = null;
    }
  }
}

Y cuanto tiempo ganamos con esta aproximación?

  public static void main(final String[] args) throws Throwable {
    final int TOTAL = 500000000;
    long ax = 0, ts = 0;
    //
    ts = System.currentTimeMillis();
    for (int i = 0; i < TOTAL; i++) {
      ax += (System.currentTimeMillis() & 0xF);
    }
    System.out.println("SystemClock: " + (System.currentTimeMillis() - ts) + "ms");
    //
    final WallClock wc = WallClock.getInstance();
    ts = System.currentTimeMillis();
    for (int i = 0; i < TOTAL; i++) {
      ax += (wc.currentTimeMillis() & 0xF);
    }
    System.out.println("WallClock: " + (System.currentTimeMillis() - ts) + "ms");
    if ((ax > 0) || (ts > 0)) // Dummy (always true)
      wc.destroy();
  }
SystemClock: 9911ms
WallClock..: 1820ms

El resultado es un aumento de la velocidad x5, el precio q se paga es tener un thread en background y algo de perdida de precision en los valores del reloj, pero es lo que tienen los caches.

Source code: WallClock.java

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: