Newsgroup: it.comp.java
Titolo: Per chi ciancia...

...che il Java è incredibilmente più lento del C++...
In questo periodo ho fatto un'applicazione che richiede molto tempo per
eseguire. Giusto per curiosità ho fatto un piccolo benchmark che ha più
o meno gli stessi cicli, allocazioni di memoria, calcoli in virgola
mobile,  estrazione di numeri casuali, letture/scritture del cuore
dell'algoritmo. Ho fatto una versione del benchmark in C++ ed una in
Java.
Sorpresa! il java è circa il 10% più veloce del C++. Non ci credete?
Riporto sotto i listati, provateci anche voi. La versione C++ l'ho
compilata col gcc 2.95 con ottimizzazioni a manetta (-O6 -march=i686
-mcpu=i686). Se qualcuno vuole provare col Visual C dica cosa viene
fuori...
Quando lo lanciate specificate un numero alla command line. Io ho un
athlon 1800+ e:
con 100 mi viene 26 sec. con java, 28 con il C++
con 150 	89 sec. con java, 96 con C++
Dimenticavo, quando parte specificate abbastanza memoria alla VM:
java -Xms100000000 -Xmx200000000 Benchmark ...
Buone prove... ;-)
**************************************************************************
//Benchmark.H
#define END_BUF -1
class Benchmark
{
 public:
  Benchmark(unsigned int);
  void run();
  unsigned int nearest(double, double);
  unsigned int* nextLinks();
  void modify();
  ~Benchmark();
 private:
  unsigned int modules;
  unsigned int  depth;
  void* allocatedMemory;
  double* positions;
};
**************************************************************************
//Benchmark.C
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Benchmark.H"
#include "time.h"
Benchmark::Benchmark(unsigned int mdl)
{
  printf("Allocating...%d\n", mdl);
  modules = mdl;
  depth = (int) sqrt(2 * mdl);
  allocatedMemory = malloc(100000000);
  if (allocatedMemory == NULL)
      printf("Error!");
  positions = new double[modules * 2];
}
void Benchmark::run()
{
  unsigned int iterations = 100 * modules, ui1, ui2, near;
  double d1, d2;
  clock_t clk1 = clock();
  printf("Start\n");
  for (ui1 = 0 ; ui1 < iterations ; ++ui1)
    for (ui2 = 0 ; ui2 < modules ; ++ui2)
      {
	d1 = rand();
	d2 = rand();
	near = nearest(d1, d2);
      }
  clock_t clk2 = clock();
  printf("Completed in %d seconds.\n", (clk2 - clk1) / CLOCKS_PER_SEC);
}
unsigned int Benchmark::nearest(double d1, double d2)
{
  unsigned int ui1, ord;
  double d3, d4, d5, min;
  for (ui1 = 0 ; ui1 < modules ; ++ui1)
    {
      d3 = *(positions + ui1 * 2);
      d4 = *(positions + ui1 * 2 + 1);
      d5 = sqrt(pow((d3 - d1), 2) + pow((d4, d2), 2));
      if (d5 < min)
	{
	  min = d5;
	  ord = ui1;
	}
    }
  return ord;
}
void Benchmark::modify()
{
  unsigned int ui1, ui2, tot;
  unsigned int* buf;
  for (ui1 = 0 ; ui1 < depth ; ++ui1)
    {
      buf = nextLinks();
      for (ui2 = 0 ; *(buf + END_BUF) != -1 ; ++ui2)
	tot += *(buf + ui2);
      delete(buf);
    }
}
unsigned int* Benchmark::nextLinks()
{
  unsigned int mods = (unsigned int) (modules * rand()) + 1, ui1;
  unsigned int* buf = new unsigned int[mods + 1];
  for (ui1 = 0 ; ui1 < mods ; ++ui1)
    *(buf + ui1) = 123;
  *(buf + mods) = END_BUF;
  return buf;
}
Benchmark::~Benchmark()
{
  printf("Deallocating...");
  free(allocatedMemory);
  delete(positions);
}
int main(int argc, char* argv[])
{
  Benchmark* bm = new Benchmark(atoi(argv[1]));
  bm->run();
  delete(bm);
}
**************************************************************************
// Benchmark.java
import java.util.*;
import java.lang.*;
public class Benchmark
{
    private int modules;
    private double depth;
    private byte[] allocatedMemory;
    private double[] positions;
    public Benchmark(int mdl)
    {
	System.out.println("Allocating...");
	modules = mdl;
	depth = (int) Math.sqrt(2 * mdl);
	allocatedMemory = new byte[100000000];
	positions = new double[modules * 2];
    }
    private void run()
    {
	int iterations = 100 * modules, ui1, ui2, near;
	double d1, d2;
	System.out.println("Start");
	long l1 = System.currentTimeMillis();
	for (ui1 = 0 ; ui1 < iterations ; ++ui1)
	    for (ui2 = 0 ; ui2 < modules ; ++ui2)
		{
		    d1 = Math.random();
		    d2 = Math.random();
		    near = nearest(d1, d2);
		}
	long l2 = System.currentTimeMillis();
	System.out.println("Completed in " + (l2 - l1) + " milliseconds");
    }
    private int nearest(double d1, double d2)
    {
	int ui1, ord = 442;
	double d3, d4, d5, min = 123123;
	for (ui1 = 0 ; ui1 < modules ; ++ui1)
	    {
		d3 = positions[ui1 * 2];
		d4 = positions[ui1 * 2 + 1];
		d5 = Math.sqrt(Math.pow((d3 - d1), 2) + Math.pow((d4 - d2), 2));
		if (d5 < min)
		    {
			min = d5;
			ord = ui1;
		    }
	    }
	return ord;
    }
    private void modify()
    {
	int ui1, ui2, tot = 123123124;
	int[] buf;
	for (ui1 = 0 ; ui1 < depth ; ++ui1)
	    {
		buf = nextLinks();
		for (ui2 = 0 ; ui2 < buf.length; ++ui2)
		    tot += buf[ ui2];
	    }
    }
    private int[] nextLinks()
    {
	int mods = (int) (modules * Math.random()) + 1, ui1;
	int[] buf = new int[mods];
	for (ui1 = 0 ; ui1 < mods ; ++ui1)
	    buf[ui1] = 123;
	return buf;
    }
    public static void main(String[] argv)
    {
	Benchmark bm = new Benchmark(Integer.parseInt(argv[0]));
	bm.run();
    }
}

Dopo alcune correzioni al tuo listato C (inizzializzazione delle varibili),
ecco i risultati dei test:
VC++6: 53 e 177 secondi con 100 e 150.
Jikes 1.15: 58 e 196 sec.
Javac 1.4: 60 e 201
su un P3 800MHz con 256MB RAM.
Però tutti sanno che la funzione pow non è il massimo, se usi double*double
ecco i risultati:
VC++6: 9 e 27 secondi con 100 e 150
se vuoi ti mando il listato C++ modificato. (basta che cambi il pow).
Ciao,
Gio.

 VC++6: 9 e 27 secondi con 100 e 150
dimenticavo:
Javac 1.4: 19 e 62 con 100 e 150 (idem jikes)
cmq che java non fosse troppo indietro nelle prestazioni me ne ero accorto
di già (implementando un qsort), però il C/C++ è più scalabile. (e poi non
mi piace che se non imposti la dimensione di memoria da linea di comando và
in "out of memory")

 VC++6: 9 e 27 secondi con 100 e 150
Sì, si potrebbe fare lo stesso anche in java...
Grazie per il disturbo.
Saluti dalla Maison Ikkoku.

 Per chi ciancia che il Java è incredibilmente più lento del C++...
digli che è un coglione pressapochista...
quanto "più"? quanto in rapporto all'interattività?
una query complessa tramite jdbc NON è mooooolto più lenta di una fatta con 
qualsiasi altra cosa in QUALSIASI caso...
eh eh ognuno si fa i suoi test, con i suoi dati... e guarda caso ogni volta 
gli danno ragione!!
Io ho fatto un test:
"E' piu veloce la 500 o una Ferrari?"
il risultato è stato: la 500 era il 1000% piu veloce...
se guardi in fondo in fondo...
....
....
.....
.....
scopri che il test era fatto facendo partire le due auto sulla stessa 
strada a distanza di 3 minuti, la 500 partiva per prima ed è arrivata al 
traguardo in 5 minuti, la Ferrari è arrivata in 50 minuti perchè era 
crollato il ponte sul quale dovevano passare e aveva fatto il giro piu 
largo.......
meditate, meditate
-- 
Antonello Pasella

 Grazie per il disturbo.
Prego, io mi diverto con i benchmark. (altrimenti non avrei fatto la doppia
compilazione javac/jikes!)
Ciao,
Gio.

 compilazione javac/jikes!)
Hai provato il codice con IBM Java 1.3.0 e 1.3.1 invece di Java 1.4?
ciao
uL

 compilazione javac/jikes!)
Ora ci riprovo...
Saluti dalla Maison Ikkoku.