• [^] # Re: Ça passe très bien :)

    Posté par . En réponse à la dépêche Jython supporte maintenant Python 2.5. Évalué à 8.

    Ici tu as des mecs qui ont codé un peu plus que des TP d'IUT; qui sont certainement capable d'écrire du C bien mieux que toi et qui en plus sont compétents en Java. Tu penses pas que tu devrais réfléchir un peu ? De plus tu découvriras aussi le compromis plus tard. Si je peux faire 30% plus rapide mais que ca demande 50% de budget en plus est ce que j'y gagne ? La rapidité n'est qu'un critère il y en a de nombreux autres, techniques ou pas.

    Revenons à nos moutons, tu ne comprends pas que le code que tu as pondu (et qu'on a toujours pas vu) doit cumuler les cas pathologiques qui ne se retrouvent pas dans une vraie appli ? Tu ne comprends pas pourquoi ton test est mauvais ? Il n'y a que des imbéciles qui disent que Java est facile. Il faut apprendre comment ca marche. Certains concepts sont propres à l'OOP, d'autres à a spécification de la JVM, du langage Java ou à une implémentation particulière. Il faut les maitriser, et c'est parreil avec toutes les technos. Par contre java n'est pas piégieur (l'API de la libc est ultra casse gueule par exemple).


    Tu parles tu temps d'appel d'une fonction ok, mais c'est quoi un appel de fonction ? Quelle est la sémantique en C et en Java ? A ton avis tout les appels de méthodes suivants sont ils équivalents ?


    private void a() {}
    public void b() {}
    public final void c() {}
    public static void d() {}


    La réponse est bien évidement non. X.b() est un appel de méthode virtuel alors que tout les autres seront des appels finaux. Dans le cas d'un appel virtuel tu as des opérations supplémentaires pour déterminer le type réel de l'objet et appeler la bonne méthode:


    010 B2: # B6 B3 <- B1 Freq: 0.999999
    010 movq R11, precise klass Virt: 0x0000000000d5b7d8:Constant:exact * # ptr
    01a cmpq R10, R11 # ptr
    01d je,us B6 P=0.500000 C=-1.000000
    01d
    01f B3: # B11 B4 <- B2 Freq: 0.499999
    01f movq R11, precise klass Virt2: 0x0000000000d5b9e8:Constant:exact * # ptr
    029 cmpq R10, R11 # ptr
    02c jne,us B11 P=0.000001 C=-1.000000
    02c
    02e B4: # B12 B5 <- B3 Freq: 0.499999
    02e movq RBP, RSI # spill
    031 # checkcastPP of RBP
    031 movq RSI, RBP # spill
    034 nop # 3 bytes pad for loops and calls
    037 call,static Virt2::b
    # Main::doit @ bci:1 L[0]=RBP
    # OopMap{rbp=Oop off=60}
    03c
    03c B5: # B8 <- B4 Freq: 0.499989
    # Block is sole successor of call
    03c movq RSI, RBP # spill
    03f jmp,s B8
    03f
    041 B6: # B13 B7 <- B2 Freq: 0.499999
    041 movq RBP, RSI # spill
    044 # checkcastPP of RBP
    044 movq RSI, RBP # spill
    047 call,static Virt::b
    # Main::doit @ bci:1 L[0]=RBP
    # OopMap{rbp=Oop off=76}
    04c


    Ce n'est pas si couteux que ca mais sur un microbench tu peux le sentir. Contrairement au C++, en Java les méthodes sont virtuelles sauf si private/static/final. La JVM est tout de même assez intelligente, ici elle se passe d'un call,dynamic et préfere deux call,static conditionnels. De plus si une classe n'est pas sous classée ca devient un appel non virtuel:


    014 B2: # B7 B3 <- B1 Freq: 0.999999
    014 nop # 3 bytes pad for loops and calls
    017 call,static Virt::b
    # Main::doit @ bci:1 L[0]=RBP
    # OopMap{rbp=Oop off=28}


    Et comme Java supporte le dynamic code loading ça peut changer au cours de l'exécution, une autre beauté d'Hotspot...

    Ce n'est qu'un exemple de pourquoi ce genre de microbench peut être très trompeur si tu ne maitrise pas parfaitement ton sujet tu peux mesurer deux choses très différentes sans t'en rendre compte.


    Maintenant qu'on a vu l'"appel de méthode". Passons à ton bench. Supposons que tu a écris une fonction tail recursive, comme factoriel. Compilé par gcc ça donne ça (-O2):


    0000000000400480 <fact>:
    400480: 85 ff test %edi,%edi
    400482: b8 01 00 00 00 mov 0ドルx1,%eax
    400487: 74 0f je 400498 <fact+0x18>
    400489: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
    400490: 0f af c7 imul %edi,%eax
    400493: 83 ef 01 sub 0ドルx1,%edi
    400496: 75 f8 jne 400490 <fact+0x10>
    400498: f3 c3 repz retq
    40049a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)


    C'est dommage tu voulais bencher les appels de méthode mais y'en a pas ! L'opti qui est possible en C n'est pas possible en Java. Donc ton bench il sert à quoi ? Tu enfonces une porte ouverte, un jump est plus rapide qu'un callq et toutes les opérations associées. Écrire un tel code en Java c'est une faute, il faut utiliser la version impérative tu auras exactement les mêmes perfs qu'en C ou assembleur.

    Je passe sur le fait que ton bench a peu de chances d'être compilé par le JIT étant donné la structure de ton test.

    Mais au final tout ca on s'en fou. Hormis si tu bosses dans quelques secteurs bien précis, du code CPU bound t'en écriras pas des masses... Et c'est pas ca qui est important ou qui fera ramer un projet, ça serait trop simple.