5 votes

Appel d'une méthode Java surchargée depuis Jython

Je constate un comportement étrange que je ne comprends pas lorsque j'appelle une méthode Java surchargée à partir d'un script Jython.

Voici ma classe Java :

public class TestClass {
  public static float[][][] overloaded(float[][][] x) {
    return x;
  }
  public static float[][][][] overloaded(float[][][][] x) {
    return x;
  }
  public static float[][][] zeros(int n1, int n2, int n3) {
    return new float[n3][n2][n1];
  }
}

et voici mon script Jython :

import time,TestClass
n1,n2,n3 = 250,250,250
z = TestClass.zeros(n1,n2,n3)
start = time.time()
TestClass.overloaded([z,z,z])
print 'time =',(time.time()-start)

Ce script Jython prend environ 1 minute pour s'exécuter, mais si je commente la première méthode dans TestClass, le script ne prend presque pas de temps du tout. Je ne comprends pas pourquoi cela prend autant de temps lorsque la méthode est surchargée. Est-ce que quelque chose m'échappe ?

3voto

Favonius Points 9008

Votre code ! !

import time,TestClass
n1,n2,n3 = 250,250,250
z = TestClass.zeros(n1,n2,n3)
start = time.time()
TestClass.overloaded([z,z,z])
print 'time =',(time.time()-start)

Les faits ! !

  1. Jython est basé sur Java (nous le savons déjà ! !).
  2. Quand vous le faites n1,n2,n3 = 250,250,250 et dire z = TestClass.zeros(n1,n2,n3) alors vous allouez essentiellement 250x250x250x32 bytes qui est autour de 500000000 bytes o 477 megabytes . 32 est la taille d'un flottant en Java.
  3. Quand vous dites TestClass.overloaded([z,z,z]) alors vous allez toujours appeler la méthode surchargée en 4 dimensions ! !! Essayez-le si vous ne me croyez pas ! !

Mon code fonctionne bien !

Je viens de changer le TestClass.overloaded([z,z,z]) a x = TestClass.overloaded([z,z,z]) . Et l'exécution a été très rapide. Mais à l'impression 'x' it still fails!! Pourquoi ? !

La partie "pourquoi" !

Il échoue parce que lorsque vous faites TestClass.overloaded([z,z,z]) ou lorsque j'imprime 'x' parce que python ou plutôt jython doit convertir l'objet en représentation de chaîne de caractères et c'est là que le problème se situe. Voir le stacktrace ci-dessous :

java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOfRange(Arrays.java:3209)
        at java.lang.String.<init>(String.java:215)
        at java.lang.StringBuilder.toString(StringBuilder.java:430)
        at org.python.core.PyList.list_toString(PyList.java:472)
        at org.python.core.PyList.toString(PyList.java:450)
        at org.python.core.PyArray.toString(PyArray.java:395)
        at org.python.core.PyObject.__repr__(PyObject.java:174)
        at org.python.core.PyList.list_toString(PyList.java:464)
        at org.python.core.PyList.toString(PyList.java:450)
        at org.python.core.PyArray.toString(PyArray.java:395)
        at org.python.core.PyObject.__repr__(PyObject.java:174)

Voyez ... La JVM est bombardée ! !!! Il n'y a plus d'espace dans le tas... Même si vous changez l'argument de la JVM pour la mémoire et bénissez ce programme avec plus, même alors vous parlez de 478 MB !! (Eh bien, ce n'est pas seulement 478 MB car vous passez un tableau de 'z' et chacun d'entre eux est 478 MB ! !!) et c'est juste ce que vous avez alloué, en plus du fait que la JVM aura besoin de mémoire pour les StringBuilder pour sauvegarder la représentation de la chaîne de caractères et quelques autres choses !

Et croyez-moi, cela prendra du temps et une bonne quantité de temps.

Juste pour vous donner une idée !

>>> n1,n2,n3 = 2,2,2
>>> z = TestClass.zeros(n1,n2,n3)
>>> x = TestClass.overloaded([z,z,z])
>>> x

Output:

array([[[F, [array([[F, [array([F, [array('f', [0.0, 0.0]), array('f', [0.0, 0.0
])]), array([F, [array('f', [0.0, 0.0]), array('f', [0.0, 0.0])])]), array([[F,
[array([F, [array('f', [0.0, 0.0]), array('f', [0.0, 0.0])]), array([F, [array('
f', [0.0, 0.0]), array('f', [0.0, 0.0])])]), array([[F, [array([F, [array('f', [
0.0, 0.0]), array('f', [0.0, 0.0])]), array([F, [array('f', [0.0, 0.0]), array('
f', [0.0, 0.0])])])])

Voir la taille de la chaîne de caractères et c'est juste pour 2x2x2x32 bytes du tableau ! ! Prenez le code que j'ai utilisé et changez tous les éléments du tableau. 2's con 20's .

Mais pourquoi cela prend du temps alors que vous ne décommentez pas la première méthode ! !!

Rappelez-vous que, pour résoudre la fonction surchargée correcte, jython doit évaluer la fonction [z,z,z] ce qui est une bonne quantité de mémoire. Et c'est là que vous voyez ce retard. Lorsque vous commentez la première méthode, il n'y a pas de confusion sur l'appel et donc le retour est instantané. Si j'utilise votre code, alors il premièrement prend pour résoudre l'expression susmentionnée et puis calcule la représentation en chaîne de l'objet. Combiné, il mettra longtemps à redevenir réactif. Mais, si j'utilise la version modifiée de votre code, à savoir x = TestClass.overloaded([z,z,z]) alors cela devient un peu plus rapide mais cela prendra toujours du temps à l'impression. 'x' ou peut entraîner Heap Exception ! !

Amusez-vous bien ! !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X