Archivos por Etiqueta: benchmark

Network: Latency benchmark

Las pruebas han sido muy basicas (pero dan una idea/orden de magnitud), las maquinas dst tienen un Servidor ECHO-TCP y las maquinas src tiene un Cliente ECHO-TCP. El cliente se conecta al servidor, envia un byte, lee el byte de vuelta, asi una y otra vez en un bucle de 10mil iteraciones, calcula la latencia minima, maxima y la media de las 10mil iteraciones.

Los resultados:

+--------+--------+------------+-------------+------------+----------+
| src    | dst    |    min     |     max     |    avg     | medium   |
+--------+--------+------------+-------------+------------+----------+
| linux1 | win7   | 2137.421µs | 24779.393µs | 3471.736µs | plc      |
| linux2 | win7   | 2035.887µs | 36111.414µs | 3040.004µs | plc      |
| linux3 | win7   | 1889.267µs | 10737.868µs | 2689.145µs | plc      |
| linux1 | win7   | 1031.974µs |  6943.338µs | 1371.043µs | wifi-11n |
| linux2 | win7   |  786.553µs |  4445.808µs | 1153.319µs | wifi-11n |
| linux3 | win7   |  621.457µs | 40078.223µs |  964.037µs | wifi-11n |
| linux1 | win7   |  380.495µs | 69546.800µs |  732.009µs | gbe      |
| linux1 | linux3 |  101.130µs | 10486.523µs |  314.863µs | vm       |
| linux2 | linux1 |  159.140µs |  9334.732µs |  308.808µs | vm       |
| linux2 | win7   |  165.534µs | 11921.050µs |  307.096µs | gbe      |
| linux3 | win7   |   79.133µs |  2289.499µs |  150.973µs | gbe      |
| linux2 | linux3 |   54.764µs |  5447.378µs |   86.460µs | vm       |
| linux1 | linux1 |   54.197µs |   299.199µs |   85.713µs | loopback |
| linux2 | linux2 |   41.505µs |   372.127µs |   72.765µs | loopback |
| linux3 | linux3 |   15.805µs |   500.069µs |   48.219µs | loopback |
| win7   | win7   |   17.675µs |    76.399µs |   22.927µs | loopback |
+--------+--------+------------+-------------+------------+----------+

Las maquinas son:

  • linux1: Ubuntu 14.04 32bits (virtual)
  • linux2: Ubuntu 14.04 64bits (virtual)
  • linux3: Ubuntu 12.04 64bits (fisica)
  • win7: Windows 7 Pro 64bits (fisica)

Los medios de transmision son:

  • plc: enlace PLC HomePlug-AV (aunque el PLC se conecta a la red por Ethernet a 100Mb)
  • wifi: enlace wifi 802.11n (aunque el AP-Wifi se conecta a la red por Ethernet a 100Mb)
  • vm: comunicacion entre dos maquinas dentro de un mismo hypervisor/host (linux3)
  • gbe: enlace Ethernet a 1Gb
  • loopback: comunicacion dentro de la misma maquina (127.0.0.1)

Sourcecode on GitHub:
EchoServer.java
EchoClient.java

Anuncios

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

Java: Async vs Sync Servlet and BIO / NIO Tomcat Connector

Un pequeño micro benchmark para comparar un Servlet Sincrono “clasico” versus su version Asincrona (de la nueva especificacion de Servlet 3.0) y la diferencia de rendimiento del conector BIO vs NIO.

## Connector BIO: org.apache.coyote.http11.Http11Protocol ##
SyncServlet  time=52837ms threads=100 req/thread=2000 request=200000 req/ms=3 
AsyncServlet time=55006ms threads=100 req/thread=2000 request=200000 req/ms=3 
SyncServlet  time=50124ms threads=100 req/thread=2000 request=200000 req/ms=3 
AsyncServlet time=54444ms threads=100 req/thread=2000 request=200000 req/ms=3 
SyncServlet  time=49937ms threads=100 req/thread=2000 request=200000 req/ms=4 
AsyncServlet time=54180ms threads=100 req/thread=2000 request=200000 req/ms=3 

## Connector NIO: org.apache.coyote.http11.Http11NioProtocol ##
SyncServlet  time=64741ms threads=100 req/thread=2000 request=200000 req/ms=3 
AsyncServlet time=72572ms threads=100 req/thread=2000 request=200000 req/ms=2 
SyncServlet  time=64163ms threads=100 req/thread=2000 request=200000 req/ms=3 
AsyncServlet time=72353ms threads=100 req/thread=2000 request=200000 req/ms=2 
SyncServlet  time=66192ms threads=100 req/thread=2000 request=200000 req/ms=3 
AsyncServlet time=71574ms threads=100 req/thread=2000 request=200000 req/ms=2 

* Menor tiempo mejor

Leer más de esta entrada

Java: Benchmark MessageDigest Algorithms

Otro sencillo benchmark para tener un orden de magnitud de que es más rápido:

MD5       281ms
SHA-1     687ms
SHA-256  1154ms
SHA-384  2232ms
SHA-512  2232ms

El codigo de prueba:

import java.security.MessageDigest;
import java.util.Random;

public class BenchMarkMessageDigest {
	static final String[] TEST_ALGORITHMS = { 
		"MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512"
	};
	static final int LOOPS = 5;

	public static void main(final String[] args) throws Throwable {
		final Random r = new Random();
		// Seed random buffer
		final byte[] buf = new byte[32 * 1024 * 1024]; // 32MB
		final int BLOCK = 4096;
		for (int i = 0; i < buf.length; i += 4) {
			final int n = r.nextInt();
			buf[i + 0] = (byte) (n & 0xFF);
			buf[i + 1] = (byte) ((n >> 8) & 0xFF);
			buf[i + 2] = (byte) ((n >> 16) & 0xFF);
			buf[i + 3] = (byte) ((n >> 24) & 0xFF);
		}
		// Run Benchmarks
		MessageDigest md;
		long begin, diff;
		for (int t = 0; t < LOOPS; t++) {
			System.out.println("--- Loop: " + t);
			for (final String alg : TEST_ALGORITHMS) {
				begin = System.currentTimeMillis();
				md = MessageDigest.getInstance(alg);
				for (int i = 0; i < buf.length; i += BLOCK) {
					md.update(buf, i, BLOCK);
				}
				diff = (System.currentTimeMillis() - begin);
				System.out.println(alg + " time: " + diff + "ms");
			}
		}
	}
}

Source code: BenchMarkMessageDigest.java

Referencias:
Java Cryptography Architecture: Standard Algorithm Name Documentation
Java Cryptography Architecture: Reference Guide

Java: Atomic, volatile, synchronized?

Otro sencillo benchmark para tener un orden de magnitud de que es más rápido:

B (boolean), VB (volatile boolean), AB (AtomicBoolean), Bsync (boolean synchronized)

B	100000000	900ms	100000000req/s	111111req/ms	best (reference)
VB	100000000	2497ms	50000000req/s	40048req/ms	2nd better
AB	100000000	2513ms	50000000req/s	39793req/ms	3rd better
Bsync	100000000	5715ms	20000000req/s	17497req/ms	worse

El codigo de prueba:

import java.util.concurrent.atomic.AtomicBoolean;

public class TestBoolean {
	private static boolean b = true;
	private static volatile boolean vb = true;
	private static final AtomicBoolean ab = new AtomicBoolean(true);
	//
	private static final void setAB(final boolean pb) {
		ab.set(pb);
	}
	private static final void setVB(final boolean pb) {
		vb = pb;
	}
	private static final void setB(final boolean pb) {
		b = pb;
	}
	private static final synchronized void setBsync(final boolean pb) {
		b = pb;
	}
	//
	public static void main(String[] args) {
		final int TOTAL = (int) 1e8;
		long ts, diff;
		// Do anything
		System.out.println("B\t" + b);
		System.out.println("VB\t" + vb);
		System.out.println("AB\t" + ab.get());
		//
		// boolean
		ts = System.currentTimeMillis();
		for (int i = 0; i < TOTAL; i++) {
			setB(((i % 2) == 0) ? true : false);
		}
		diff = (System.currentTimeMillis() - ts);
		System.out.println("B\t" + TOTAL + "\t" + diff + "ms\t"
				+ (TOTAL / Math.max(diff / 1000, 1)) + "req/s\t"
				+ (TOTAL / Math.max(diff, 1)) + "req/ms");
		//
		// synchronized boolean 
		ts = System.currentTimeMillis();
		for (int i = 0; i < TOTAL; i++) {
			setBsync(((i % 2) == 0) ? true : false);
		}
		diff = (System.currentTimeMillis() - ts);
		System.out.println("Bsync\t" + TOTAL + "\t" + diff + "ms\t"
				+ (TOTAL / Math.max(diff / 1000, 1)) + "req/s\t"
				+ (TOTAL / Math.max(diff, 1)) + "req/ms");
		//
		// volatile boolean
		ts = System.currentTimeMillis();
		for (int i = 0; i < TOTAL; i++) {
			setVB(((i % 2) == 0) ? true : false);
		}
		diff = (System.currentTimeMillis() - ts);
		System.out.println("VB\t" + TOTAL + "\t" + diff + "ms\t"
				+ (TOTAL / Math.max(diff / 1000, 1)) + "req/s\t"
				+ (TOTAL / Math.max(diff, 1)) + "req/ms");
		//
		// AtomicBoolean
		ts = System.currentTimeMillis();
		for (int i = 0; i < TOTAL; i++) {
			setAB(((i % 2) == 0) ? true : false);
		}
		diff = (System.currentTimeMillis() - ts);
		System.out.println("AB\t" + TOTAL + "\t" + diff + "ms\t"
				+ (TOTAL / Math.max(diff / 1000, 1)) + "req/s\t"
				+ (TOTAL / Math.max(diff, 1)) + "req/ms");
		// Do anything
		System.out.println("B\t" + b);
		System.out.println("VB\t" + vb);
		System.out.println("AB\t" + ab.get());
	}
}

Referencias:
Patrones de uso para volatile
Managing volatility
Synchronized Methods
Atomic Variables

Java: Son rapidos los “varargs”?

Fix=llamada a metodo de argumentos fijos
Var=llamada a metodo varargs
Dummy=La llamada solo devuelve false
Null=La llamada compara los parametros con null

Resultados:

checkDummyFix:	125ms
checkDummyVar:	4422ms
checkNullFix:	1735ms
checkNullVar:	5797ms

# java -version
java version “1.6.0_33”
Java(TM) SE Runtime Environment (build 1.6.0_33-b03)
Java HotSpot(TM) Client VM (build 20.8-b03, mixed mode, sharing)

El codigo de prueba:
Leer más de esta entrada

Java: El coste de usar Reflexion (Reflect)

Cual es el coste de usar reflexion (reflect) en Java?

En cifras (tiempo de ejecucion en milisegundos, bajo=mejor) sobre 5millones de invocaciones de un metodo sencillo:

Loop iteration counter=5000000
Normal Static time=78ms
Normal Object time=78ms
Reflection Static time=796ms
Reflection Object time=796ms
Static XX=96349939634993
Object XX=96349939634993

Resumen: 796ms por reflexion (lento) vs 78ms de una invocacion normal (rapido).

El codigo fuente de las pruebas…
Leer más de esta entrada

Filesystem performance on SSD

A %d blogueros les gusta esto: