Author: thimel Date: 2006-08-28 17:13:03 +0000 (Mon, 28 Aug 2006) New Revision: 2 Added: doc/ doc/etude.rst doc/img/ doc/img/testB-results.png doc/installation.rst doc/resultats.ods doc/results-mesuresSimple.ods src/test/org/codelutin/j2r/JPurTest.java src/test/org/codelutin/j2r/LutinTimer.java src/test/org/codelutin/j2r/TestConstants.java Modified: pom.xml src/java/org/codelutin/j2r/REngine.java src/java/org/codelutin/j2r/RException.java src/java/org/codelutin/j2r/RProxy.java src/java/org/codelutin/j2r/jni/RJniEngine.java src/java/org/codelutin/j2r/net/RNetEngine.java src/test/org/codelutin/j2r/JNITest.java src/test/org/codelutin/j2r/NetTest.java Log: Suite des devs Ajout des tests Added: doc/etude.rst =================================================================== --- doc/etude.rst 2006-08-23 16:14:42 UTC (rev 1) +++ doc/etude.rst 2006-08-28 17:13:03 UTC (rev 2) @@ -0,0 +1,193 @@ +Introduction +============ + +Ce document a pour but de comparer les diff�rentes solutions envisageables pour l'utilisation de R en Java. + +R est un outil libre de calculs et cr�ation de graphiques li�s aux statistiques. Il pr�sente l'avantage non n�gligeable d'�tre optimis� pour bon nombre de calculs. Cependant, R n'est pas �crit en Java et ne permet donc pas d'�tre directement utilis� dans une application Java. + +Heureusement, R est un projet tr�s modulaire et permet par le biais d'extensions d'ouvrir son moteur � d'autres appplications. En Java, deux possibilit�s s'offrent � nous : + - Acc�s par le r�seau : L'application envoie des requ�tes par le r�seau � une extension de R faisant office de serveur, laquelle renvoie par la suite les r�sultats obtenus. + - Acc�s par une librairie JNI : Il s'agit d'�crire du code en un langage autre que Java qui sera compil� et exc�cut� par la machine plut�t qu'interpr�t�. Gr�ce � JNI, il est ensuite possible d'appeler ce code depuis une application Java. + +Le pr�sent document va donc comparer ces deux solutions afin de d�terminer laquelle est la plus adapt�e. Afin d'effectuer une comparaison plus pertinente, ces solutions seront compar�es, lorsque c'est possible, � l'utilisation de R seul (sans Java) et Java seul (sans R). + + +R�sultats attendus +================== + +Chacune des solutions a ses avantages et ses inconv�nients qui entreront dans la d�cision finale. Avant m�me de commencer, la nature m�me des solutions sugg�re certains r�sultats qu'il faudra v�rifier : + + - Les temps de r�ponse obtenus en R pur seront inf�rieurs aux solutions r�seau et JNI. Le contraire serait �tonnant dans la mesure o� l'utilisation de R pur est la seule solution n'impliquant pas de technologie tierce. + - Les appels JNI devraient prendre moins de temps que les appels r�seau. L'utilisation des interfaces r�seau est reconnue est informatique pour �tre un point qui ralenti souvent les applications. + - Certaines calculs simples effectu�s en Java pur pourraient parfois s'av�rer plus rapide. Cependant, des calculs plus complexes comme des calculs matriciels devraient faire ressortir l'avantage de R. + + +Consid�rations techniques +========================= + +R�seau +------ + +Par d�faut, R n'int�gre aucune interface r�seau, et ne peut donc �tre utilis� � distance. Il existe une extension du nom de 'Rserve' permettant d'ajouter � R la possibilit� de recevoir et traiter des requ�tes TCP/IP, le rendant ainsi accessible � tous types de langages. + +Avantages : R non n�cessaire sur la machine cliente, d�l�gation des calculs � une machine tierce, appli 100% portable +Inconv�nients : Rserve a installer sur le serveur + +JNI +--- + +L'utilisation de JNI implique la cr�ation d'une librarie d�pendante du syst�me. On perd donc un peu de la portabilit� du Java. + +Avantages : Installation basique de R +Inconv�nients : M�me machine, n�cessite des param�tres de d�marrage de l'application Java, l'application Java n'est plus 100% portable car cr�ation/compilation d'une librairie n�cessaire. + + +D�roulement (protocole) des tests +================================= + +Le but des tests est de faire ressortir le co�t de chacune des solutions de mani�re � d�terminer laquelle pourrait �tre la meilleure, mais surtout les conditions, s'il y en a, dans lesquelles telle ou telle solution est meilleure. + +Deux types de tests ont �t� effectu�s. + - Le permier consiste � envoyer de tr�s petits calculs � R et ce beaucoup de fois de suite. On obtient donc une moyenne pour chacune des solutions ce qui permettra d'�valuer le co�t de chaque m�thode. + - Le second se base sur la quantit� de donn�es � v�hiculer. Il s'agit donc l� de calculs plus long mais surtout g�n�rant un plus gros volume de donn�es. Plusieurs mesures seront effectu�es avec des tailles croissantes afin d'�valuer l'impact de l'augmentation volum�trique. + - Le dernier test est surtout informatif et ne fera ressortir que le temps n�cessaires � initialiser chacune des solutions �tudi�es. + +A noter que : + De fa�on � ne pas trop laisser libre cours aux optimisations des diff�rentes plateformes, les calculs r�p�t�s sont volotairement changeants au sein d'un m�me test (il restent n�anmoins identiques entre les tests). + + +R�sultats des tests +=================== + +Tous les temps sont mesur�s en milli-secondes : + +Test A - Calculs rapides +------------------------ + ++------------+--------+--------+--------+--------+ +| | Java | Net | JNI | R | ++============+========+========+========+========+ +| Moyenne | | 241,06 | 233,56 | 230,83 | ++------------+--------+--------+--------+--------+ +| Ecart-type | | 18,65 | 11,99 | | ++------------+--------+--------+--------+--------+ + + +Test B - Volumes importants +--------------------------- + ++------------+--------+--------+--------+--------+ +| | Java | Net | JNI | R | ++============+========+========+========+========+ +| 50 | 0,00 | 1,00 | 1,33 | | ++------------+--------+--------+--------+--------+ +| 500 | 0,00 | 3,00 | 1,33 | | ++------------+--------+--------+--------+--------+ +| 5000 | 1,00 | 13,00 | 3,33 | | ++------------+--------+--------+--------+--------+ +| 50000 | 24,20 | 33,50 | 8,00 | | ++------------+--------+--------+--------+--------+ +| 100000 | 60,20 | 118,00 | 79,00 | | ++------------+--------+--------+--------+--------+ +| 200000 | 66,60 | 142,00 | 116,00 | | ++------------+--------+--------+--------+--------+ +| 500000 | 89,00 | 330,00 | 189,00 | | ++------------+--------+--------+--------+--------+ +| 1000000 | 94,00 | 620,00 | 282,00 | | ++------------+--------+--------+--------+--------+ + + +Test C - Temps d'initialisation +------------------------------- + ++------------+--------+--------+--------+--------+ +| | Java | Net | JNI | R | ++============+========+========+========+========+ +| Init. | | 22,10 | 571,10 | | ++------------+--------+--------+--------+--------+ + + +Exploitation des r�sultats +========================== + +Les tests �tant effectu�s, il faut maintenant les interpr�ter et en tirer des conclusions. + +Test A - Calculs rapides +------------------------ + +Le premier test avait pour but d'isoler le co�t de chaque appel � R. +La comparason avec du Java pur n'avait ici aucun int�ret dans la mesure ou le but est de calculer le temps d'appel � R. + +Premi�rement, l'op�ration est r�alis�e en R pur afin d'avoir un temps de base : 229.83ms. +A partir de l�, on peut estimer que le temps n�cessaire � chaque technologie. +Ainsi, un appel JNI est en moyenne d'un peu moins de 3ms (2.73ms), alors que par le r�seau, il faut plus de 10ms (10,23ms), soit un ecart d'environ 7ms en faveur de JNI. + +La diff�rence est relativement faible, elle ne repr�sente ici que 3%, mais r�p�t� � grande �chelle elle peut �tre p�nalisante. Si par exemple 100.000 appels cons�cutifs sont n�cessaires, la diff�rence se monte � 700 secondes soit 11 minutes et 40 secondes ce qui peut �tre �norme pour des simulateurs par exemple. + +Pour ce test, l'�cart-type �tait mesur� afin d'estimer la r�partition des valeurs. +L'�cart-type nous permet ici de constater que la r�partition des valeurs avec JNI est plus proche de la moyenne que par le r�seau. La solution r�seau est donc plus sensible aux variations de temps. + + +Test B - Volumes importants +--------------------------- + +La deuxi�me s�rie de tests veut mettre en valeur l'�volution des temps n�cessaires avec l'augmentation du volume de donn�es. +Inversement au pr�c�dent test, c'est la solution R pur qui n'a ici pas de sens puisqu'on cherche � �valuer l'impact d'un passqge de Java � R. + +L'op�ration r�alis�e pour ce test est un simple produit scalaire entre deux vecteurs dont la taille va augmenter progressivement. Le graphique ci-dessous permet de voir instantann�ment la mani�re dont �voluent ces technologies : + +.. image:: img/testB-results.png + :alt: Evolution des temps de r�ponse + +L'�tude de l'�volution des temps de r�ponse s'av�re r�v�latrice. + +A faibles volumes de donn�es, les r�sultats des 3 solutions sont comparables. + +Cependant, la solution r�seau montre vite ses faiblesses. D�s l'utilisation de vecteurs d'une taille de 5.000 chiffres la comparaison devient ridicule tant les temps n�cessaires pour transf�rer les vecteurs prend le pas sur le calcul. Pour le reste de ce test, le r�seau restera toujours la solution la moins adapt�e. + +Du c�t� de JNI, la solution s'av�re beaucoup plus pertinente. R sur JNI s'offre m�me le luxe de battre Java sur certaines tailles ce qui est tr�s flatteur si on tient compte du fait que les r�sultats doivent �tre convertis de R � Java afin d'�tre exploitables. La solution se montre donc viable mais uniquement jusqu'� ce que la taille des vecteurs depasse les 100.000 chiffres. Les optimisations de Java prennent alors le dessus et affichent des temps bien inf�rieurs. + +Enfin le dernier test sur des vecteurs d'une taille de 1.000.000 de chiffres indique des temps qui, m�me s'ils ne sont plus comparables � Java (94ms), restent honorables. La solution JNI n�cessite 282ms pour effectuer le calcul et le renvoyer � Java, ce qui signifie qu'il est toujours possible d'effectuer 3 produits scalaires sur des vecteurs d'un million d'entr�es en moins d'une seconde. Le temps n�cessaire � la solution r�seau (620ms) n'est pas non plus ridicule compte tenu de la taille des donn�es � traiter. La solution r�seau souffre simplement de temps de transfert trop longs qui sont le reflet habituel de l'utilisation des r�seaux. + +Test C - Temps d'initialisation +------------------------------- + +Le temps d'initialisation repr�sente le temps n�cessaire � la premi�re utilisation de l'application avant de pouvoir acc�der � R. Il peut parraitre annodin, mais en r�alit� il peut s'av�rer primordial dans le choix de la solution � utiliser. + +Si les tests pr�c�dents n'ont pas �t� en faveur de la solution r�seau, ce test l� montre que l'initialisation de JNI prend en moyenne 550ms de plus que l'initialisation du r�seau. Cette diff�rence peut s'av�rer cruciale si les calculs � effectuer sont petits et peu r�p�t�s. + +Notes +----- + +Certains faits n'apparaissent pas dans les chiffres pr�c�demment cit�s mais peuvent �galement pencher dans la balance. + +Par exemple, les diff�rents tests ont fait ressortir que la solution r�seau n�cessite un "temps de chauffe". Un simple test r�p�t� 10 fois de suite peut le mettre en �vidence. Chaque ligne suivante repr�sente l'�volution d'un m�me test : + ++-----------------+ +| duration: 801ms | ++-----------------+ +| duration: 700ms | ++-----------------+ +| duration: 638ms | ++-----------------+ +| duration: 584ms | ++-----------------+ +| duration: 642ms | ++-----------------+ +| duration: 581ms | ++-----------------+ +| duration: 415ms | ++-----------------+ +| duration: 323ms | ++-----------------+ +| duration: 321ms | ++-----------------+ +| duration: 326ms | ++-----------------+ + +La diff�rence entre le premier et le dernier test atteint quasiment la demi seconde soit plus de 150% du temps n�cessaire au final pour l'op�ration. + +R�capitulatif +------------- + + Added: doc/img/testB-results.png =================================================================== (Binary files differ) Property changes on: doc/img/testB-results.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: doc/installation.rst =================================================================== Added: doc/resultats.ods =================================================================== (Binary files differ) Property changes on: doc/resultats.ods ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: doc/results-mesuresSimple.ods =================================================================== (Binary files differ) Property changes on: doc/results-mesuresSimple.ods ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: pom.xml =================================================================== --- pom.xml 2006-08-23 16:14:42 UTC (rev 1) +++ pom.xml 2006-08-28 17:13:03 UTC (rev 2) @@ -24,8 +24,7 @@ <!--Description--> <description> - Librairie permettant d'utiliser R en Java, que ce soit par -le Network ou en JNI. + Librairie permettant d'utiliser R en Java, que ce soit par le Network ou en JNI. </description> <inceptionYear>2006</inceptionYear> @@ -45,13 +44,13 @@ <dependency> <groupId>externallib</groupId> <artifactId>JRclient</artifactId> - <version>RE817</version> + <version>RF503</version> <scope>compile</scope> </dependency> <dependency> <groupId>externallib</groupId> <artifactId>JRI</artifactId> - <version>0.2-4</version> + <version>0.2-4-cl</version> <scope>compile</scope> </dependency> </dependencies> Modified: src/java/org/codelutin/j2r/REngine.java =================================================================== --- src/java/org/codelutin/j2r/REngine.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/java/org/codelutin/j2r/REngine.java 2006-08-28 17:13:03 UTC (rev 2) @@ -33,7 +33,8 @@ package org.codelutin.j2r; /** - * + * Cette interface est le point commun entre les differentes technologies + * utilisees pour l'acces a R */ public interface REngine { @@ -46,6 +47,8 @@ */ public Object eval(String expr) throws RException; + public void voidEval(String expr) throws RException; + public void terminate() throws RException; } //RJniEngine Modified: src/java/org/codelutin/j2r/RException.java =================================================================== --- src/java/org/codelutin/j2r/RException.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/java/org/codelutin/j2r/RException.java 2006-08-28 17:13:03 UTC (rev 2) @@ -21,7 +21,7 @@ /* * * RException.java * -* Created: 22 ao�t 06 +* Created: 22 aout 06 * * @author Arnaud Thimel <thimel@codelutin.com> * @version $Revision: $ Modified: src/java/org/codelutin/j2r/RProxy.java =================================================================== --- src/java/org/codelutin/j2r/RProxy.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/java/org/codelutin/j2r/RProxy.java 2006-08-28 17:13:03 UTC (rev 2) @@ -135,4 +135,13 @@ } } + public void voidEval(String expr) throws RException { + if (engine == null) { + log.fatal("The R Proxy is not initialized. An error probably " + + "occured during the initialization."); + return; + } + engine.voidEval(expr); + } + } //RProxy Modified: src/java/org/codelutin/j2r/jni/RJniEngine.java =================================================================== --- src/java/org/codelutin/j2r/jni/RJniEngine.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/java/org/codelutin/j2r/jni/RJniEngine.java 2006-08-28 17:13:03 UTC (rev 2) @@ -52,12 +52,17 @@ * @see org.codelutin.j2r.REngine#init() */ public boolean init() { - String[] args = { "--no-save" }; - engine = new Rengine(args, false, null); - if (!engine.waitForR()) { - if (log.isErrorEnabled()) { - log.error("Cannot load the R engine"); + try { + String[] args = { "--no-save" }; + engine = new Rengine(args, false, null); + if (!engine.waitForR()) { + if (log.isErrorEnabled()) { + log.error("Cannot load the R engine"); + } + return false; } + } catch (Throwable twable) { + log.error("An error occured during R/JNI initialization.", twable); return false; } return true; @@ -80,6 +85,10 @@ } private Object convertResult(REXP rexp) { + if (rexp == null) { + log.debug("Null returned"); + return null; + } if (log.isDebugEnabled()) { log.debug("Converting : " + rexp.toString()); } @@ -119,4 +128,16 @@ } } + /* (non-Javadoc) + * @see org.codelutin.j2r.REngine#voidEval(java.lang.String) + */ + public void voidEval(String expr) throws RException { + //voidEval is not really supproted by JRI, we just discard the result conversion + try { + engine.eval(expr); + }catch (Exception eee) { + throw new RException("An error occured while voidEval on JNI", eee); + } + } + } // RJniEngine Modified: src/java/org/codelutin/j2r/net/RNetEngine.java =================================================================== --- src/java/org/codelutin/j2r/net/RNetEngine.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/java/org/codelutin/j2r/net/RNetEngine.java 2006-08-28 17:13:03 UTC (rev 2) @@ -21,7 +21,7 @@ /* * * RNetEngine.java * -* Created: 22 ao�t 06 +* Created: 22 aout 06 * * @author Arnaud Thimel <thimel@codelutin.com> * @version $Revision: $ @@ -61,7 +61,10 @@ try { conn = new Rconnection(host, port); } catch (RSrvException e) { - e.printStackTrace(); + log.error("Unable to establish a connection to the R server. " + + "Maybe you forgot to start it. " + + "Try using the command \"R CMD Rserve\"."); + return false; } return true; } @@ -80,6 +83,10 @@ } private Object convertResult(REXP rexp) { + if (rexp == null) { + log.debug("Null returned"); + return null; + } if (log.isDebugEnabled()) { log.debug("Converting : " + rexp.toString()); } @@ -128,4 +135,15 @@ } } + /* (non-Javadoc) + * @see org.codelutin.j2r.REngine#voidEval(java.lang.String) + */ + public void voidEval(String expr) throws RException { + try { + conn.voidEval(expr); + } catch (RSrvException rse) { + throw new RException("An error occured while voidEval on net", rse); + } + } + } //RNetEngine Modified: src/test/org/codelutin/j2r/JNITest.java =================================================================== --- src/test/org/codelutin/j2r/JNITest.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/test/org/codelutin/j2r/JNITest.java 2006-08-28 17:13:03 UTC (rev 2) @@ -32,37 +32,81 @@ package org.codelutin.j2r; + +import static org.codelutin.j2r.TestConstants.*; + import junit.framework.TestCase; public class JNITest extends TestCase { - private REngine engine; + private REngine engine; @Override protected void setUp() throws Exception { + LutinTimer init = new LutinTimer(); + init.startTiming(); System.setProperty("R.type", "jni"); if (engine == null) { engine = new RProxy(); } + System.err.println("jni init: " + init.endTiming() + "ms"); } @Override protected void tearDown() throws Exception { engine.terminate(); } +// +// public void testDouble() throws Exception { +// assertEquals(5.0, engine.eval("5.0")); +// } +// +// public void testIntArray() throws Exception { +// Object result = engine.eval("5:10"); +// assertEquals(int[].class, result.getClass()); +// int[] intArray = (int[])result; +// assertEquals(6, intArray.length); +// for (int i=5; i<11; i++) { +// assertEquals(i, intArray[i-5]); +// } +// } - public void testDouble() throws Exception { - assertEquals(5.0, engine.eval("5.0")); - } + public void testSimpleOp() throws Exception { + LutinTimer t = new LutinTimer(); + for (int loop=0; loop<S_NB_LOOPS; loop++) { + engine.voidEval("t<-0"); + t.startTiming(); + engine.voidEval(S_OP); + t.endTiming(); + System.err.println((Double)engine.eval("t")); + } + double[] results = t.computeResults(); + System.err.println("min: " + results[0]); + System.err.println("avg: " + results[1]); + System.err.println("max: " + results[2]); + System.err.println("etype: " + results[3]); + } - public void testIntArray() throws Exception { - Object result = engine.eval("5:10"); - assertEquals(int[].class, result.getClass()); - int[] intArray = (int[])result; - assertEquals(6, intArray.length); - for (int i=5; i<11; i++) { - assertEquals(i, intArray[i-5]); - } - } + public void testVector() throws Exception { + System.err.println(V_OP_R); + for (int loop=0; loop<V_NB_LOOPS; loop++) { + LutinTimer t = new LutinTimer(); + t.startTiming(); + engine.voidEval(V_OP_A); + engine.voidEval(V_OP_B); + double[] r = (double[])engine.eval(V_OP_AB); + long end = t.endTiming(); + System.err.println("duration: " + end); + double sum = 0.0; + for (int i=0; i<r.length; i++) { + // if (i%10000==0) { + // System.err.println(r[i]); + // } + sum += r[i]; + } +// System.err.println("sum: " + sum); +// System.err.println(r.length); + } + } } //NetTest Added: src/test/org/codelutin/j2r/JPurTest.java =================================================================== --- src/test/org/codelutin/j2r/JPurTest.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/test/org/codelutin/j2r/JPurTest.java 2006-08-28 17:13:03 UTC (rev 2) @@ -0,0 +1,89 @@ +/* *##% +* Copyright (C) 2002, 2003, 2004, 2005, 2006 Code Lutin, +* Cedric Pineau, Benjamin Poussin, Arnaud Thimel +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*##%*/ + +/* * +* JPurTest.java +* +* Created: 25 ao�t 06 +* +* @author Arnaud Thimel <thimel@codelutin.com> +* @version $Revision: $ +* +* Mise a jour: $Date: $ +* par : $Author: $ +*/ + +package org.codelutin.j2r; + +import static org.codelutin.j2r.TestConstants.*; +import junit.framework.TestCase; + + +public class JPurTest extends TestCase { + + public void testSimpleOp() throws Exception { + LutinTimer lt = new LutinTimer(); + for (int loop=0; loop<S_NB_LOOPS; loop++) { + int t=0; + lt.startTiming(); + while (t<S_T_MAX) { + t += 2; + t *= 2; + t /= 2; + } + lt.endTiming(); + } + double[] results = lt.computeResults(); + System.err.println("min: " + results[0]); + System.err.println("avg: " + results[1]); + System.err.println("max: " + results[2]); + System.err.println("etype: " + results[3]); + } + + public void testVector() throws Exception { + for (int loop=0; loop<V_NB_LOOPS; loop++) { + LutinTimer lt = new LutinTimer(); + lt.startTiming(); + double[] a = new double[V_MAX]; + double[] b = new double[V_MAX]; + for (int i=0; i<a.length; i++) { + a[i] = (i + 0.5); + b[i] = ((V_MAX-0.5)-i); + } + + double[] r = new double[V_MAX]; + for (int i=0; i<a.length; i++) { + r[i] = a[i] * b[i]; + } + long end = lt.endTiming(); + System.err.println("duration: " + end); + double sum = 0.0; + for (int i=0; i<r.length; i++) { + // if (i%10000==0) { + // System.err.println(r[i]); + // } + sum += r[i]; + } +// System.err.println("sum: " + sum); +// System.err.println(r.length); + } + } + +} Added: src/test/org/codelutin/j2r/LutinTimer.java =================================================================== --- src/test/org/codelutin/j2r/LutinTimer.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/test/org/codelutin/j2r/LutinTimer.java 2006-08-28 17:13:03 UTC (rev 2) @@ -0,0 +1,112 @@ +/* *##% +* Copyright (C) 2002, 2003, 2004, 2005 Code Lutin, +* C�dric Pineau, Benjamin Poussin, +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*##%*/ + +/* * +* Timer.java +* +* Created: 18 ao�t 2006 +* +* @author Arnaud Thimel <thimel@codelutin.com> +* @version $Revision: $ +* +* Mise a jour: $Date: $ +* par : $Author: $ +*/ + +package org.codelutin.j2r; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class LutinTimer { + + private static Log log = LogFactory.getLog(LutinTimer.class); + + private List<Long> times = new ArrayList<Long>(); + private long currentStart = -1; + + public void startTiming() { + currentStart = System.currentTimeMillis(); + } + + public long endTiming() { + if (currentStart == -1) { + System.err.println("Timer didn't start..."); + return -1; + } + long end = System.currentTimeMillis(); + long duration = end - currentStart; + currentStart = -1; + times.add(duration); + return duration; + } + + public void markTiming() { + if (currentStart == -1) { + startTiming(); + return; + } + long end = System.currentTimeMillis(); + long duration = end - currentStart; + currentStart = end; + times.add(duration); + } + + public void reset() { + currentStart = -1; + times.clear(); + } + + public double[] computeResults() { + if (times.size() == 0) { + System.err.println("To time saved"); + return null; + } + long min = Long.MAX_VALUE; + long max = Long.MIN_VALUE; + long total = 0; + for (long time : times ){ + if (time > max) { + max = time; + } + if (time < min) { + min = time; + } + total += time; + } + double avg = (((double)total) / times.size()); + double etype = 0; + for (long time : times) { + etype += Math.pow(((double)time) - avg, 2); + } + etype /= times.size(); + etype = Math.sqrt(etype); + double[] results = new double[4]; + results[0] = min; + results[1] = avg; + results[2] = max; + results[3] = etype; + return results; + } + +} //Timer Modified: src/test/org/codelutin/j2r/NetTest.java =================================================================== --- src/test/org/codelutin/j2r/NetTest.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/test/org/codelutin/j2r/NetTest.java 2006-08-28 17:13:03 UTC (rev 2) @@ -32,6 +32,8 @@ package org.codelutin.j2r; +import static org.codelutin.j2r.TestConstants.*; + import junit.framework.TestCase; public class NetTest extends TestCase { @@ -40,24 +42,65 @@ @Override protected void setUp() throws Exception { + LutinTimer init = new LutinTimer(); + init.startTiming(); System.setProperty("R.type", "net"); if (engine == null) { engine = new RProxy(); } + System.err.println("net init: " + init.endTiming() + "ms"); } +// +// public void testDouble() throws Exception { +// assertEquals(5.0, engine.eval("5.0")); +// } +// +// public void testIntArray() throws Exception { +// Object result = engine.eval("5:10"); +// assertNotNull(result); +// assertEquals(int[].class, result.getClass()); +// int[] intArray = (int[])result; +// assertEquals(6, intArray.length); +// for (int i=5; i<11; i++) { +// assertEquals(i, intArray[i-5]); +// } +// } - public void testDouble() throws Exception { - assertEquals(5.0, engine.eval("5.0")); - } + public void testSimpleOp() throws Exception { + LutinTimer t = new LutinTimer(); + for (int loop=0; loop<S_NB_LOOPS; loop++) { + engine.voidEval("t<-0"); + t.startTiming(); + engine.voidEval(S_OP); + t.endTiming(); + System.err.println((Double)engine.eval("t")); + } + double[] results = t.computeResults(); + System.err.println("min: " + results[0]); + System.err.println("avg: " + results[1]); + System.err.println("max: " + results[2]); + System.err.println("etype: " + results[3]); + } - public void testIntArray() throws Exception { - Object result = engine.eval("5:10"); - assertEquals(int[].class, result.getClass()); - int[] intArray = (int[])result; - assertEquals(6, intArray.length); - for (int i=5; i<11; i++) { - assertEquals(i, intArray[i-5]); - } - } + public void testVector() throws Exception { + for (int loop=0; loop<V_NB_LOOPS; loop++) { + LutinTimer t = new LutinTimer(); + t.startTiming(); + engine.voidEval(V_OP_A); + engine.voidEval(V_OP_B); + double[] r = (double[])engine.eval(V_OP_AB); + long end = t.endTiming(); + System.err.println("duration: " + end); + double sum = 0.0; + for (int i=0; i<r.length; i++) { + // if (i%10000==0) { + // System.err.println(r[i]); + // } + sum += r[i]; + } +// System.err.println("sum: " + sum); +// System.err.println(r.length); + } + } } //NetTest Added: src/test/org/codelutin/j2r/TestConstants.java =================================================================== --- src/test/org/codelutin/j2r/TestConstants.java 2006-08-23 16:14:42 UTC (rev 1) +++ src/test/org/codelutin/j2r/TestConstants.java 2006-08-28 17:13:03 UTC (rev 2) @@ -0,0 +1,58 @@ +/* *##% +* Copyright (C) 2002, 2003, 2004, 2005, 2006 Code Lutin, +* Cedric Pineau, Benjamin Poussin, Arnaud Thimel +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*##%*/ + +/* * +* TestConstants.java +* +* Created: 25 ao�t 06 +* +* @author Arnaud Thimel <thimel@codelutin.com> +* @version $Revision: $ +* +* Mise a jour: $Date: $ +* par : $Author: $ +*/ + +package org.codelutin.j2r; + +public class TestConstants { + + /* + * Constants for simple operations + */ + public static final int S_T_MAX = 100000; + + public static final String S_OP = "while (t<" + S_T_MAX + ") {t<-t+2; t<-t*2; t<-t/2;}"; + + public static final int S_NB_LOOPS = 5; + + /* + * Constants for volumetric operations + */ + public static final int V_MAX = 50000; + + public static final String V_OP_A = "a<-0.5:"+(V_MAX-0.5); + public static final String V_OP_B = "b<-"+(V_MAX-0.5)+":0.5"; + public static final String V_OP_AB = "r<-a*b"; + public static final String V_OP_R = V_OP_A + "; " + V_OP_B + "; " + V_OP_AB; + + public static final int V_NB_LOOPS = 10; + +} //TestConstants