Newsgroup: it.comp.java
Titolo: Integrare codice C in java o no?

Salve a tutti, per la tesi di laurea (non in informatica) devo sviluppare un 
modello matematico.
Il C e' piu' performante di Java per calcoli matematici, vero?
Io di C conosco veramente pochissimo e volevo sapere:
posso integrare del codice in c in un programma java (cioe', java si occupa 
della connessione a db, e visualizzazione gui, i calcoli li fa il C )
In questo caso, ovviamente si perde in termini di prestazioni che scrivendo 
in puro C (credo)....ma tanto da vanificare il fatto che l'algoritmo sia 
scritto in C?
Grazie mille per i consigli!!!!


Mmhh, io per l'universita' avevo fatto uno studio sugli algortimi di
sort, in java e in C. Java perdeva, a dipendenza dell'algoritmo, dallo
0 al 5 % di prestazioni risp allo stesso algoritmo scritto in C. Che
per un algortimo che dura 30 secondi non ti accorgi neanche, ma se
dura 2-3 giorni...beh, le cose cambiano...
Java ha quasi le stesse prestazioni di C e C++ se lo usi in modalita'
autistica, cioe' senza interazioni con l'esterno, cioe' niente GUI, I/
O su periferiche (disco, stampante, HID, ecc.)
Cmq se vuoi interfacciare roba scritta in C con Java non ci sono
problemi, usa JNI (Java Native Interface), ti rimando al sito della
Sun 
java.sun.com
 per tutorial, spiegazioni, esempi, ecc.


Ah, io mi aspettavo0 crolli prestazionali del 20-30 % da quanto avevo 
leggiucchiato da internet...perfetto, allora credo che faro' tutto in 
java... 

 O su periferiche (disco, stampante, HID, ecc.)...
approfitto per fare una domanda visto che l'argomento interessa anche a me: 
se devo processare un array (o buffer), in sequenza, in C incremento il 
puntatore con "ptr++", e poi accedo agli elementi con "*ptr". In Java sono 
costretto ad indicizzare ogni elemento "ptr[indice]", ed incrementare l'indice.
Esiste qualcosa di piu' efficiente in Java?

 dura 2-3 giorni...beh, le cose cambiano...
Tempo addietro girava un articolo a riguarda (il titolo era qualcosa 
tipo "Java and C++ comparision"). Non è che hai capito a quale articolo 
mi riferisca? L'ho cercato in rete ma non ho trovato nulla e mi farebbe 
piacere dargli uno sguardo...
Ciao,
Giulio
--

 writes:
J> Mmhh, io per l'universita' avevo fatto uno studio sugli algortimi
J> di sort, in java e in C. Java perdeva, a dipendenza dell'algoritmo,
J> dallo 0 al 5 % di prestazioni risp allo stesso algoritmo scritto in
J> C. Che per un algortimo che dura 30 secondi non ti accorgi neanche,
J> ma se dura 2-3 giorni...beh, le cose cambiano...
Curiosità Jack, come hai fatto le misure ?
J> Java ha quasi le stesse prestazioni di C e C++ se lo usi in
J> modalita' autistica, cioe' senza interazioni con l'esterno, cioe'
J> niente GUI, I/ O su periferiche (disco, stampante, HID, ecc.)
t> Ah, io mi aspettavo0 crolli prestazionali del 20-30 % da quanto
t> avevo leggiucchiato da internet...perfetto, allora credo che faro'
t> tutto in java...
Se Java non  mette in campo il JIT compiler, se  lasci statici tutti i
metodi...   I  tipi  nativi  arrivano  al  processore,  quelli  FP  al
coprocessore matematico. Il compilatore  C potrebbe avere il vantaggio
di riuscire a rischedulare meglio le istruzioni per il coprocessore.
Una cosa molto  importante è il tempo di  accesso alla memoria. Meglio
riesci  ad utilizzare  le cache  e  meglio è,  quindi, potendo,  tieni
ravvicinati gli accessi alla memoria.
Per i  dati, utilizzando  tipi numerici ed  array, i due  linguaggi si
equivalgono.
Un  loop di calcolo  in C  ben scritto  potrebbe riuscire  a contenere
tutto il  testo del loop nella  cache più preziosa  del processore per
lungo tempo (teoricamente,  se non ci fossero cambi  di contesto, fino
alla fine  dell'esecuzione), mentre del  codice byte compiled  in Java
potrebbe avere  qualche problema  in più a  fare lo stesso,  in quanto
abbiamo il bytecode (cache dati) ed il codice che lo interpreta (cache
istruzioni).
Io farei così:
codifico quello che dovrebbe essere il  loop più eseguito sia in C che
in Java, e  valuterei le prestazioni con un  input corposo, facendo un
certo numero  di prove. A tal  scopo si può utilizzare  un profiler, o
volendo "perdere tempo", farsi un wrapper JNI per la getrusage().
Se si usano  solo tipi nativi, va  a finire che con un  po' di #define
riesci ad usare lo stesso codice in C o in Java...
Sulla base dei risultati completerei il loop di calcolo.
-- 
 /\           ___
/___/\_|_|\_|__|___Gian Uberto Lauri_____
  //--\| | \|  |   Integralista GNUslamico
\/                 e coltivatore diretto di Software

 Curiosità Jack, come hai fatto le misure ?
Allora:
algoritmi di sort (bubble, heap e quicksort) su array di int,
implementati allo stesso modo.
Creo l'array, lo popolo con numeri random, lo copio (cosi che tutti
gli algoritmi hanno lo stesso array di partenza) e poi faccio partire
l'algoritmo.
Per le misure niente di eclatante ho preso il tempo subito prima
dell'inizio dell'algoritmo e subito dopo (con le fz apposite).
Ho fatto diverse prove, mi pare 10 per ogni algoritmo e per ogni
lunghezza dell'array (in realta' dovevo fare una comparazione
sull'efficienza degli algoritmi di sort, io gia' che c'ero ho fatto
anche una comparazione tra Java e C). L'array da ordinare era lungo
1000, 5000, 10k, 50k, 100k, 500k, 1M, 5M e 10M (ok, ho avuto un po' di
problemi con l'ultimo, mi andava in outofmemory :P )
Ovviamente usando sempre la stessa macchina senza processi in
background che rompessero le balle (oltre a win :( )
Per Java avevo usato la 1.4.2 (non ricordo che build) e per C avevo
usato DevC++ (v. 4.9.9.2 se non erro) sotto win.
Cmq l'aveva fatta anche un mio amico la stessa cosa (con gli algoritmi
implementati da lui) e avevamo trovato risultati analoghi.
Ciao Jack

 wrote:

Si' puo fare , java ha una tecnica standard per parlare con funzioni C
(JNI)
Ma non dovresti farlo, che senso ha usare mezzo Java e mezzo C?
Questa tecnologia e' stata pensata piu' che altro per permettere a
codice
Java di usare codice C GIA" esistente.
Se parti da zero, fai tutto in Java o tutto in C. A meno che non
tratti
di megaipersimulazioni non credo che avrai grossi probs di
performance.
Piu' che altro se usi un linguaggio chietiti perche' proprio quello.


In C per il compilatore usare i puntatori per un array o usare la
notazione array[indice] e' uguale, quando trasforma in assembler
scrive la stessa cosa.
In Java usare array[indice] e' AFAIK il metodo piu' efficiente.
Ciao Jack

 writes:
P> C incremento il puntatore con "ptr++", e poi accedo agli elementi
P> con "*ptr". In Java sono costretto ad indicizzare ogni elemento
P> "ptr[indice]", ed incrementare l'indice.  Esiste qualcosa di piu'
P> efficiente in Java?
No, non essendoci l'aritmetica sui puntatori. E comunque non peggiori 
tanto le cose.


 scrive la stessa cosa.
No, come può essere!
Capisco che un array in C è un puntatore, ma in C, scrivere "array[indice]" 
implica comunque la somma dell'indice sul puntatore dell'array.
Mentre io intendevo l'incremento di un puntatore.

 No, come può essere!
puo' essere perche' il compilatore e' intelligente.

> Curiosità Jack, come hai fatto le misure ?
J> dell'inizio dell'algoritmo e subito dopo (con le fz apposite).
Erano queste che mi interessavano... :)


 Erano queste che mi interessavano... :)
lo devo interpretare che ho fatto una cagata o meno?
Ciao Jack

 writes:
J> In C per il compilatore usare i puntatori per un array o usare la
J> notazione array[indice] e' uguale, quando trasforma in assembler
J> scrive la stessa cosa.
Sicuro  ? Sei  proprio certo  che *var  non venga  tradotto  usando un
indirizzamento "secco" e var[i] un indirizzamento con displacement ?
Poi a runtime dovrebbero essercis pochi problemi di prestazioni...
J> In Java usare array[indice] e' AFAIK il metodo piu' efficiente.
AFAIK l'unico.
-- 
                                                    Gian
                                           Friends will be friends
                                              right to the end!

> Erano queste che mi interessavano... :)
J> lo devo interpretare che ho fatto una cagata o meno?
No, non hai fatto una cagata, il metodo che hai seguito mi pare valido.
// Lo aveva scelto un mio amico che ha successivamente vinto un premio
// per la migliore routine di calcolo numerico del biennio...
Visto che lo avevi fatto, mi interessava sapere come avevi misurato il
tempo.


 puo' essere perche' il compilatore e' intelligente.
sarà pure, ma come fa prima della compilazione a sapere che l'indice è 
sequenziale?
Non è una questione di intelligenza, non lo può sapere.

> puo' essere perche' il compilatore e' intelligente.
P> sarà pure, ma come fa prima della compilazione a sapere che
P> l'indice è sequenziale?  Non è una questione di intelligenza, non
P> lo può sapere.
In realtà usa due indirizzamenti diversi se la CPU li supporta, e quindi
il peso in cicli macchina non cambia.
Credo che solo sui macchine che non supportano una forma di indirizzamnto
[indirizzo base + displacement] occorra una operazione in più.


 indirizzamento "secco" e var[i] un indirizzamento con displacement ?
mmhh no sicuro sicuro non lo sono. Sinceramente sono convinto dipenda
dal compilatore e da cosa c'e' intorno alla chiamata.
Per dire e' diverso se accedo ad un array cosi a[5] oppure se ci
accedo cosi a[indice]   all'interno di un loop (penso).
In linea di principio se il compilatore e' "smart" abbastanza riesce a
ottimizzare il codice e quindi le due cose sono equivalenti, altrimeni
usare i puntatori e' piu' efficiente (il compilatore non deve far
nulla)
Ad esempio se si fa un loop (in C) cosi:
for(i=0;i<12;i++)
{
   a[i] = b[i] + c[i];
}
i compilatore moderni (tipo GCC), se hanno attivato le ottimizzazioni
vettoriali (ad esempio il GCC per MacOSX, se si compila per processori
G4,G5 o Intel) questa cosa la fa diventare:
for(i=0;i<12;)
{
   a[i] = b[i] + c[i];
   a[i+1] = b[i+1] + c[i+1];
   a[i+2] = b[i+2] + c[i+2];
   i += 3;   //e' un esempio, non e' che lo divide in 3
}
e il codice passa all'unita' vettoriale che processa ogni ciclo del
loop in una botta sola, e quindi farla con o senza i puntatori cambia
poco o niente.
OK, mi sa che sono andato un po' OT, cmq tutto questo per dire che con
i compilatori un po' evoluti uno puo' scrivere un po' quello che vuole
(con certi limiti eh :) ) ma poi il compilatore fa un po' quello che
vuole.
Tutto questo e' IMHO e AFAIK, se ho detto fregnacce spero che qualcuno
me lo dica.
E se qualcuno ha articoli, paper, ecc. su questo argomento saro ben
felice di leggerli :P.
(sto pensando di comprare il dragonbook)
Ciao Jack

 poco o niente.
Giusto una domanda, ovviamente quelle opzioni di ottimizzazioni sono 
attive anche per il GCC sotto Linux...
Ora perchè mi veniva il dubbio, l'altra volta che ho ricompilato tutta 
una Gentoo ci ha messo una vita, ovviamente con molte ottimizzazioni 
attive e codice poco pulito il compilatore spende molto tempo 
nell'ottimizzazione...e poco nella compilazione...
Chissà cosa fa GCJ a livello di ottimizzazioni! :P
Ciao,
jRed

 writes:
j> Chissà cosa fa GCJ a livello di ottimizzazioni! :P
Potresti rimanerne deluso... L'architettura della JVM è molto diversa
da quella dei processori "tradizionali"...



Le conclusioni sono in linea, ma in linea.
Nella maggior parte degli algortimi Java perde meno del 2% (e d'altra
parte siccome stiamo usando un JIT la cosa mi torna).
Semmai il discorso è che spesso e volentieri si hanno consumi di memoria
dalle 20 alle (nel caso estremo) 200 volte superiori. Per cui a seconda
dei calcoli, bisogna vedere.
Per esempio se si manipolano molte matrici grosse, il problema
computazionale sarebbe che viene usata *troppa* RAM, eventualmente
portando a paginazione e altri problemi prestazionali indiretti.
-- 
blog:  
http://www.akropolix.net/rik0/blogs
 | Uccidete i filosofi,
site:  
http://www.akropolix.net/rik0/
      | tenetevi riso e
forum: 
http://www.akropolix.net/forum/
     | bacchette per voi.

 Non è una questione di intelligenza, non lo può sapere.
Potrebbe. Dipende dal codice. Il mestiere dell'ottimizzatore di un
compilatore è proprio quello di fare il pelo al problema della
terminazione, cercando di scoprire quante più possibile informazioni e
usandole per ottimizzare.


 da quella dei processori "tradizionali"...
In particolare è pur sempre una macchina a stack.
Ad ogni modo il discorso cambia poco. IMHO la JVM ottimizza
relativamente poco *prima* per dare più possibilità di spremere cicli al
JIT *dopo*.
Poi resta il fatto che gcj può compilare in codice nativo. In qualche
punto gli alberi astratti dei programmi nei vari linguaggi sono buttati
fuori in qualche linguaggio intermedio comune, quello è ottimizzato e
poi tramutato in asm.
Non so se si fa ancora, ma direi che potrebbe essere a livello del
three-address code.


 indirizzamento "secco" e var[i] un indirizzamento con displacement ?
Agli occhi del compilatore una scrittura del tipo
*(p + i) e p[i]
sono del tutto equivalenti (addirittura si mantiene la commutatività e
puoi scrivere i[p]). Questo è da standard.
6.5.2.1 Array subscripting 
Constraints 
1 One of the expressions shall have type ''pointer to object type'', the
other expression shall have integer type, and the result has type
''type''. 
Semantics
A postfix expression followed by an expression in square brackets[]is a
subscripted designation of an element of an array object. The definition
of the subscript operator[] is that E1[E2]is identical to(*((E1)+(E2))).
Because of the conversion rules that apply to the binary+operator, if
E1 is an array object (equivalently, a pointer to the initial element of
an array object) and E2 is an integer, E1[E2]designates the E2-th
element of E1(counting from zero).
Poi chiaramente se i è una costante (eventualmente 0) ci possono essere
ottimizzazioni aggiuntive, ma è un altro discorso (e le ottimizzazioni
non riguardano lo standard).


 Piu' che altro se usi un linguaggio chietiti perche' proprio quello.
+1
"Perchè conosco quello" in generale non è una buona risposta.


> diversa da quella dei processori "tradizionali"...
E'OF> In particolare è pur sempre una macchina a stack. 
Ed i processori normali NON lo sono, fa eccezione lo stack floating point
delle architetture Intel...
Inoltre  non conosco  molte macchine  che hanno  l'istruzione macchina
"invoca metodo virtuale" :)


> ?
E'OF> Agli occhi del compilatore una scrittura del tipo
E'OF> *(p + i) e p[i]
Questa, Enrico, e` la situazione  banale, deve fare tutte due le volte
la stessa cosa.
Io pensavo  alla situazione  in cui  si usa un  puntatore k  che punta
all'i-esimo valore in p[]
Qui al massimo cambia il tipo di indirizzamnto.


 delle architetture Intel...
Dopo tutto il principale vantaggio di un set di istruzioni a stack è che
i binari sono più piccoli. Ma perdi in performance (e riesci ad emulare
abbastanza facilmente una macchina a stack con una a registri).
Per la parte floating point delle architetture Intel non me ne parlare.
Riesco a pensare a poche cose più dementi di avere registri da 80bit
quando in memoria i double sono a 64 bit, con il risultato che in
pratica il risultato di una sequenza di operazioni è in buona sostanza
dipendente da quello che sta succedendo sulla macchina (e che la stessa
'funzione' eseguita due volte può dare risultati diversi).


 all'i-esimo valore in p[]
Credo che stiamo dicendo due cose diverse. Mi faresti un esempio?
Dici 
char *k = p + i;
Ma non capisco a che livello stiamo parlando: se è a livello di quello
che fa il compilatore sotto il cappuccio o a livello di linguaggio.


 writes:
E'OF> Dopo tutto il principale vantaggio di un set di istruzioni a
E'OF> stack č che i binari sono piů piccoli.
Credo sia uno dei motivi per cui la hanno scelta come architettura...
E'OF> Per la parte floating point delle architetture Intel non me ne
E'OF> parlare.  Riesco a pensare a poche cose piů dementi di avere
E'OF> registri da 80bit quando in memoria i double sono a 64 bit
Scusa, ma i registri MMX dove č che stanno adesso ? Una volta c'era una
istuzione da 100 cicli relativa all'attivazione di quei registri...


> all'i-esimo valore in p[]
E'OF> Credo che stiamo dicendo due cose diverse. Mi faresti un
E'OF> esempio?  Dici
E'OF> char *k = p + i;
int i;
int p[100];
int *k;
/* ... */
k=p;
for(i=0;i<100;i++) {
   foo(p[i]);
   bar(k++);
}
Se non erro dovrebbe risolvere  ambedue gli accessi al vettore con una
istruzione sola, ma  usando due tipi di indirizzamento  diversi (se la
cpu li supporta)
E'OF> Uccidete i tenetevi riso e bacchette per voi.
Splendida soluzione per il problema!


 istuzione da 100 cicli relativa all'attivazione di quei registri...
Uh, non seguo le n-mila estensioni ASM ad x86 :P
Scherzi a parte, non parlo dei registri MMX. Quelli sono 64bit precisi
(anche se IIRC mi pare che almeno una volta fossero solo un modo diverso
di accedere allo stack FPU).
Inoltre i registri MMX hanno un interfaccia per calcoli *vettoriali
interi*, non floating point (con la genialata allegata che se devi
mischiare le istruzioni SIMD *e* istruzioni floating point devi romperti
le palle non da poco, per cui... si aggiungono SSE).
Se uno invece guarda il semplice e potentissimo progetto di AltiVec, gli
viene una lacrimuccia. E pensa, io sono un softwarista puro. Non oso
pensare cosa capiti ad un esteta dell'hardware o a un vero asm-hacker.


 Splendida soluzione per il problema!
Lo penso anche io. E non ha nemmeno l'ombra di un deadlock. 


 
su questo č ok, ma io intendevo (e ho scritto) diversamente, cioč:
*(p++)
e
p[i++]
..non credo vengano compilati nello stesso modo.

 ..non credo vengano compilati nello stesso modo.
Scusa, hai ragione. No, non possono essere compilati allo stesso modo,
visto che sono semanticamente diversi.
Tipicamente fra i due il valore di p cambia.


 
...e la cosa mi fa inca..are tantissimo in Java ma in genere nei linguaggi 
cosiddetti "moderni", dove l'aritmetica dei puntatori č vista come un 
attentato alla sicurezza dello Stato :-(

 attentato alla sicurezza dello Stato :-(
Non ci vedo nulla di male, personalmente. Ci sono indubbi casi in cui i
puntatori e la gestione esplicita della memoria sono fondamentali (tipo
a breve dovrei scrivere il gestore della memoria per un interprete).
Ma nella maggior parte dei casi, sono dettagli che non servono al
programmatore (a patto di avere un linguaggio ricco a sufficienza). 
Chiediamoci in una tipica applicazione quando useremmo l'aritmetica dei
puntatori. Quando veramente serve, e quando invece bastano le reference.
Non a caso anche linguaggi 'semimoderni' (secondo la tua definizione)
come potrebbero essere il C++ usano con accortezza i puntatori,
preferendo quando possibile i reference (che non hanno aritmetica). Ma
non solo: ci sono fiori di classi (auto_ptr nella libreria standard e
qualcosa ancora di meglio in boost, pare si chiami checked_ptr IIRC) che
cercano di arginare i problemi della gestione esplicita della memoria.
L'altra cosa che stiamo scrivendo č per l'appunto un sistema che
staticamente va a beccare gli accessi out of bound sulle stringhe (fra
le varie cose). Perchč? Perchč č un errore tipico.
Il punto č che quando ci si rende conto che una feature di un linguaggio
di 35 anni fa, pensato per l'efficienza e pensato per essere quanto piů
vicino alla macchina senza scegliere in dettagli, causa la maggior parte
dei bachi, viene da chiedersi se il gioco valga la candela.
Oggi l'efficienza non č cosě importante (non in tutti i casi, e spesso
basta ottimizzare le parti critiche). I programmi sono ancora piů
complessi e tutto... bene, č il tempo di usare qualcosa di piů vicino al
programmatore.
Pensa che per me Java č fin  troppo di basso livello per molte cose. Ma
non disdegno mica il C (tempo fa avevo fatto una libreria per la
manipolazione di polinomi su anelli modulo n che doveva essere parecchio
efficiente, visto che seriviva per problemi di teoria dei numeri). Ecco.
Li C, C e ancora C. La memoria la devo gestire io, e devo gestirla nel
modo piů efficiente possibile: devo essere ragionevolmente certo che
dentro un loop veloce non mi allochi e deallochi memoria. Devo accettare
ridondanza di memoria negli oggetti costruiti (poichč lavorando con
interi di dimensione arbitraria posso avere *sempre* bisogno di
ingrandirmi), e quindi diventa vitale che un oggetto appena non serve
sia distrutto.
Puntatori e sporchevolezze a gogo, roba tipo
typedef struct {
    size_t degree;
    size_t _allocated;
    mpz_t mod;
    BOOL _constructed;
    mpz_t *coefs;
} __aks_poly_struct;
typedef __aks_poly_struct ap_t[1];
(questo č codice vero dalla libreria), per evitarsi un sacco di malloc
(tipicamente in questo modo almeno la struct finisce sullo stack, ma la
si passa in giro senza copiarla)


 puoi scrivere i[p]). Questo è da standard.
figata, questo non lo sapevo. ora provo :)

 writes:
E'OF> Scherzi a parte, non parlo dei registri MMX. Quelli sono 64bit
E'OF> precisi (anche se IIRC mi pare che almeno una volta fossero solo
E'OF> un modo diverso di accedere allo stack FPU).
Almeno una volta era esattamente cosě, e 100 cicli macchina per passare
da un modo all'altro.
E'OF> Inoltre i registri MMX hanno un interfaccia per calcoli
E'OF> *vettoriali interi*
Oh,  ora  lo chiamano  vettoriale.  Olim  era  solo parallelismo  SIMD
(Single Instruction Multiple Data)
-- 
 /\           ___
/___/\_|_|\_|__|___Gian Uberto Lauri_____
  //--\| | \|  |   Integralista GNUslamico
\/                 e coltivatore diretto di Software
mov -(PC), -(PC)
                       [assembler PDP-11]

> vista come un attentato alla sicurezza dello Stato :-(
E'OF> Non ci vedo nulla di male, personalmente.
Con le opportune premesse.
E'OF> Il punto è che quando ci si rende conto che una feature di un
E'OF> linguaggio di 35 anni fa, pensato per l'efficienza e pensato per
E'OF> essere quanto più vicino alla macchina senza scegliere in
E'OF> dettagli, causa la maggior parte dei bachi, viene da chiedersi
E'OF> se il gioco valga la candela.
Non sono gli anni che fanno superato un progetto software. Anzi, tanto
di cappello a progetti che hanno 30 e più anni di vita.
Più che altro, è calata  la qualità media dei programmatori rispetto a
quando  è stato  fatto il  progetto. C  richiede  buoni programmatori,
buoni secondo gli standard di quando è stato scritto.
E'OF> Oggi l'efficienza non è così importante 
Non  totalmente  sono d'accordo.   Qualche  giorno  fa Caterpillar  ha
lanciato la campagna  "mi illumino di meno". Mi  ha fatto pensare alla
quantità di  energia che  viene usata in  software poco  efficente. Ci
sono in giro  computer che assorbono 6 kW,  e non sono particolarmente
grossi  come  server, mi  piacerebbe  vedere  se  il costo  per  ciclo
macchina è ancora irrisorio.
E'OF> e spesso basta ottimizzare le parti critiche.
Questo è invece oggettivo.
-- 
 /\           ___
/___/\_|_|\_|__|___Gian Uberto Lauri_____
  //--\| | \|  |   Integralista GNUslamico
\/                 e coltivatore diretto di Software
A Cesare avrei detto di scrivermi a 
fn...@rat.vg

> commutativitą e puoi scrivere i[p]). Questo č da standard.
J> figata, questo non lo sapevo. ora provo :)
Poi analizza questo codice e valutane l'output senza eseguirlo :)
main(){printf(&unix["\021%six\012\0"], (unix)["have"]+"fun"-0x60);}
                                       [David Korn, AT&T Bell Labs
                                        ioccc best One Liner, 1987 ]


 (Single Instruction Multiple Data)
No. Sono io che *impropriamente* lo chiamo 'vettoriale'. 


 macchina è ancora irrisorio.
Il punto è che la maggior parte dei software per gran parte del tempo,
fanno poco o nulla. Questo è quanto vale per sostanzialmente tutti i
software desktop (e quelli che hanno bisogno di alte performance *sono*
scritti almeno in parte in C/C++).
Per il software di rete spesso il tempo computazionale è piccolo
rispetto al tempo per fare query su un db (e quello si che è scritto in
C/C++, anche se mi pare che di recente sia venuto su bene hsql db, in
Java apputno) e al tempo di risposta (per cui dal punto di vista
dell'efficienza si tendono ad abbandonare i CGI -- e perfino un
merdosissimo sw in PHP ha in generale performance sotto carico di un CGI
in C).
Ci sono come vedi vaste classi di sw in cui l'efficienza *davvero* non è
importante. Perchè vuoi per colli di bottiglia, vuoi per altri motivi,
le carte in tavola non contano.
Poi possiamo ragionare anche su un paio di cose. OCaml dal punto di
vista dell'efficienza se la gioca con il C. Dal punto di vista del
programmatore è invece un linguaggio di livello piuttosto alto, con cui
è *davvero* veloce sviluppare. Eppure... quanti lo usano?


 puntatori. Quando veramente serve, e quando invece bastano le reference...
Concordo su tutto: comunque io parlo in base alla mia espierienza, lunga ma 
purtroppo non molto variata, quindi sono 10 anni che scrivo codice (image 
processing) che non fa altro che elaborare lunghe sequenze di dati, e per 
me, poter incrementare un puntatore invece di usare indici significa 
dimezzare i tempi di elaborazione.
Giustamente si puņ obiettare: usa il C (o meglio l'assembly)! Si perņ mi si 
raddoppiano i tempi di sviluppo + altri problemi, e mi concentro meno sul 
problema da risolvere.

> buoni secondo gli standard di quando è stato scritto.
E'OF> I bachi di cui stiamo parlando sono talmente diffusi che
E'OF> verrebbe da chiedersi se esistono davvero dei 'buoni
E'OF> programmatori'. IMHO più semplicemente i buoni programmatori
E'OF> fanno pure loro fior di errori, e più è complesso il progetto
E'OF> software e più è facile introdurne.
Esistono, ho avuto occasione di vederli, qualcosa di paragonabile
all'illuminazione zen :).
Conta che una  volta valeva la pena di ragionarci  su sul codice prima
di darlo in  pasto al compilatore ed al debugger, vuoi  per i tempi di
esecuzione vuoi  per l'uso delle  risorse. Quindi si andava  molto più
attenti.
E'OF> Inoltre non è la qualità media che influenza queste cose. Ci
E'OF> sono fior di ambiti dove comunque lavora solo l'elite (pensa per
E'OF> esempio ad un compilatore, librerie di sistema, di rete, ma
E'OF> anche applicazioni mission critical).
Qui  potrei  raccontarti  qualcosina  di  divertente  che  include  il
software di navigazione di un certo vettore...
E'OF> riproduzione fra i programmatori di un noto ambiente (homo
E'OF> visualbasicensis) senza skill, il loro aumento abbassa la
E'OF> qualità media, ma non va ad intaccare quella di quelli che fanno
E'OF> la roba di cui sopra.
Vero. Ma essendo molti ed economici ci saranno manager che affideranno
progetti  a  homini visualbasicensis  invece  che  a programmatori  di
adatta capacità (ma maggiore costo).
E'OF> La qualità media è forse anche scesa, ma questo non è certo il
E'OF> problema che fa si che ci siano fior di bachi in tutti i tipi di
E'OF> software.
Ni. 
E'OF> Scrivere in C è più costoso. Ci va più tempo per debuggare, più
E'OF> tempo per progettare le cose per bene. Anche i costi di
E'OF> deployment per molte categorie software sono più costosi.
Per le  categorie mi  servirebbe un esempio  per capire meglio  il tuo
discorso.
Per lo scrivere... Si e no. Penso dipenda dall'esperienza.
Certo, il C  va bene con organizzazioni del lavoro  tipo quelle ne "il
mitico  mese uomo" (team  di 10  persone in  cui c'è  un programmatore
senior, uno junior, un code lawyer e il resto supporto).
E'OF> Il punto è che la maggior parte dei software per gran parte del
E'OF> tempo, fanno poco o nulla.
Vero, ma per fare il resto mangiano un barcone di CPU :).
Io stavo  pensando principalmente a  codice che gira su  server, anche
grossetti. Con quella mentalità venne sviluppata una applicazione che,
fintanto che stava nel laboratorio, andava benissimo. Salvo mettere in
crisi il server  con qualche decina di migliaia  di page fault/secondo
quando arrivava  il picco d'utenza... Energia sprecata  sia sul server
che sulle macchine client.
E'OF> Per il software di rete spesso il tempo computazionale è piccolo
E'OF> rispetto al tempo per fare query su un db
Anche la query va scritta con efficienza.
E'OF> Ci sono come vedi vaste classi di sw in cui l'efficienza
E'OF> *davvero* non è importante. Perchè vuoi per colli di bottiglia,
E'OF> vuoi per altri motivi, le carte in tavola non contano.
Non mi  convinci del  tutto. Il  discorso a naso  torna perché  non si
stanno considerando alcune variabili.
E'OF> con cui è *davvero* veloce
E'OF> sviluppare. Eppure... quanti lo usano?
Mi puoi indicare qualcosa di veramente notevole fatto in Ocaml?
Non è per  sminuire quel linguaggio. La fortuna di  un linguaggio è un
discorso complesso, usualmente il linguaggio più noti hanno avuto o un
grosso impulso da parte del  marketing o sono stati usati per scrivere
qualcosa di notevole (i.e. un kernel). Il Pascal non rientra in queste
categorie  ma  a  naso  era  l'unico  linguaggio  didattico(*)  valido
disponibile.
(*) Anche nei costi di compilazione/esecuzione.


 problema da risolvere.
E qui quoto.


 disponibile.
Infatti.


> stanno considerando alcune variabili.
E'OF> IMHO scegliere un linguaggio di basso livello per un progetto
E'OF> software 'di alto livello' (ovvero di livello applicativo)
E'OF> rientra nel caso della 'premature optimization', se è fatto a
E'OF> scopo prestazionale.
Il discorso di tutte le variabili  è ampio, e rientra nella classe dei
discorsi  su quanto viene  fatto in  una maniera  piuttosto che  in un
altra perché non si mettono a bilancio, ad esempio, costi sostenuti da
terzi non implicati.
Non lo so, nessuno lo ha mai fatto, ma se si mettessero in conto tutti
i consumi  energetici dovuti  ad inefficenze del  software, mi  sa che
altro che standby dei televisori...


 problema da risolvere.
Una soluzione che potrebbe salvare capra e cavoli e` l'uso di linguaggi
piu` moderni o piu` semplici rispetto al C, ma che permettono comunque
un approccio piu` a basso livello rispetto ai linguaggi interpretati. In
questo campo, penso che gli unici linguaggi disponibili siano il Pascal
e il D
Enrico

 e il D
Io adoro D. Ma D è più vicino a Java come idea. Mi spiego meglio.
Java ha diverse caratteristiche peculiari. Nasce come linguaggio di
livello sostanzialmente medio (più alto del C, comparabile o più alto di
C++, ma comunque non alto come Python o Ruby) che però sia *più*
semplice del C++ sotto diversi aspetti.
In questo senso D risponde alla stessa domanda. Rispetto a Java è
compilato in codice nativo (mantenendo comunque una buona facilità di
installazione).
D'altra parte è comunque un linguaggio di livello parecchio più basso di
Python, Ruby o Perl. E' un linguaggio che si presta molto bene a carichi
computazionali, roba algortmica di basso livello etc etc etc. Ma per
scrivere software applicativo complesso non è *così* più semplice
rispetto a Java o addirittura C++.
Riguardo Pascal non mi esprimo. Conosco (poco ormai) il vecchio Pascal.
Il 'nuovo' Pascal (ma chiamiamolo anche Delphi, visto che di base
parliamo di quello) non lo ho mai usato. Mi dicono dalla regia che hanno
fixato alcune cose demenziali del vecchio pascal...
considera il codice Java
Person singer = SingerFactory.singerByName("Jagger")
ConcreteObject aDoor = singer.firstSeenObject()
if (aDoor != null && aDoor.isRed()){
   aDoor.paintItBlack()
}
[ che ok, io ci userei un NullObjectPattern... ma d'accordo ]
Ecco... questo in Pascal una volta lo facevi con due if annidati. Ora
dicono che non sia più vero.


 Mi puoi indicare qualcosa di veramente notevole fatto in Ocaml?
MLDonkey
Enrico

 Chissà cosa fa GCJ a livello di ottimizzazioni! :P
Da quel poco che ho visto, piu` che di una compilazione a codice nativo,
il GCJ non fa altro che eseguire un wrapper dell'applicativo tale da
renderlo eseguibile senza alcuna VM[1]
Enrico
[1] non proprio vero, in quanto lega all'eseguibile una libreria che fa
le veci della VM

 MLDonkey
Omminghia. Non lo sapevo. Un RiK0 che mo 'si fa pirata' solo per usare
qualcosa in OCaml! :P


 Enrico
D non l'ho mai sentito, mi informerň grazie. Pascal a me sembra un po' piu' 
vecchio del C.

> Enrico
P> D non l'ho mai sentito, mi informerò grazie. Pascal a me sembra un
P> po' piu' vecchio del C.
Pascal  pare  anche  a me  più  anziano,  se  non altro  perché  nelle
primissime pagine del K&R si citano le macro per il begin e l'end - le
graffe potevano essere  un problema di leggibilità per  chi veniva dal
pascal e aveva delle stampanti un po' stanchine.
Basso livello il Pascal non direi, è un linguaggio didattico, nato per
essere compilato  ed eseguito  con poca spesa  (il tempo  macchina del
CDC6600 costava...).
Se poi  uno con Pascal intende  i prodotti Borland,  questo è un'altro
discorso, il Turbo Pascal di  Borland ha riportato quasi tutto ciò che
c'era in C ma con sintassi Pascal.


 parte siccome stiamo usando un JIT la cosa mi torna).
Guarda che i numeri riportati in quel benchmark non sono percentuali.
I risultati non sono tanto buoni per Java:
in 14 test su 19 Java impiega oltre il 50% del tempo in piu' rispetto
al C.
Per quanto riguarda la memoria sono d'accordo con te, ma c'e' da
considerare che con il GC di mezzo e' difficile dire quale sia la
quantita' di memoria effettiva utilizzata in piu' dal programma Java.
Saluti,
The Librarian

 c'era in C ma con sintassi Pascal.
Da come lo dici sembra che sia una brutta cosa. Attualmente, tutti i
compilatori Pascal in circolazione si rifanno al dialetto di Borland,
permettendo cosi` un'alta portabilita` di codice. Per fare un esempio,
FreePascal permette di compilare il codice scritto per il compilatore
Borland senza problemi
Enrico

 quantita' di memoria effettiva utilizzata in piu' dal programma Java.
Certamente. Il fatto è che la prevedibilità del consumo è una cosa
chiave quando la quantità di RAM è critica. Tutto qui :)


> che c'era in C ma con sintassi Pascal.
E'B> Da come lo dici sembra che sia una brutta cosa.
Beh, meglio la sintassi del C, il trasporto al Pascal di queste funzioni
anche se è stato utile non lo vedo come una cosa elegante.


 altro che standby dei televisori...
Attenzione però: scegliere di usare linguaggi di basso livello non
necessariamente minimizzerebbe i consumi. Tipicamente ottimizzare
software a livello algoritmico diventa più costoso (in opposizione con
l'ottimizzazione del singolo algoritmo nel software).
Crescerebbero anche i memory leak et similia. E su un sistema odierno
memory leak significa prima o tardi paginazione più intensa. Che è pure
questo uno spreco di CPU.


> sa che altro che standby dei televisori...
E'OF> Attenzione però: scegliere di usare linguaggi di basso livello
E'OF> non necessariamente minimizzerebbe i consumi.
Infatti, vedi il gracconto di  Graham sul programma per la ricerca dei
voli  "appetibili" da  un  certo  cliente: il  programma  in LISP  con
algoritmi  intelligenti  che  batte  quelli  ottimizzatissimi  ma  con
algoritmi grulli (non condivido l'idea che ha sui software patents, il
signore dovrebbe dare un'occhiata alla normativa europea...)


 writes:
GUL> Infatti, vedi il gracconto di Graham sul programma per la ricerca
GUL> dei voli "appetibili" da un certo cliente: il programma in LISP
GUL> con algoritmi intelligenti che batte quelli ottimizzatissimi ma
GUL> con algoritmi grulli
Trovato il documento: 
http://www.paulgraham.com/carl.html
 
http://www.paulgraham.com/icad.html


 signore dovrebbe dare un'occhiata alla normativa europea...)
+1 su tutto.


                       
http://www.paulgraham.com/icad.html
TY. Me lo leggiucchio. 
Il secondo è splendido:
<<If you want to trick a pointy-haired boss into letting you write
software in Lisp, you could try telling him it's XML.>>
Mi chiedo cosa ci facciamo su un ng di Java.<g>


> lato opposto c'è Java che controlla il controllabile.
E'OF> Mai lavorato in ADA <g>?
No, non c'era ancora un compilatore disponibile.
E poi la sai quella dell'unità di misura dell'intelligenza ? Il tary.
Ci sono le  persone normali, intorno a qualche decina  di tary. I geni
che vanno su percentuali significative, o superano, il kilotary. E gli
sfortunati, che girano  sul decitary se non peggio  sul centitary o il
millitary...
E'OF> Mi chiedo cosa ci facciamo su un ng di Java.<g>
"We were after the C++ programmers. We managed to drag a lot of them
about halfway to Lisp."
- Guy Steele, co-author of the Java spec


 E'OF> Mai lavorato in ADA <g>?
evitiamo di parlare di ADA. E' un linguaggio di programmazione
paranoico.
-- 
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?

 - Guy Steele, co-author of the Java spec
Interessante. Anche se non sono sicuro che il programmatore Java tipo
sia sulla strada per Lisp. O forse questo da un interessante insight sul
perchè sempre più Javisti si stanno appassionando a Ruby.
