Tout en faisant quelques benchmarking pour répondre à this question sur le moyen le plus rapide de concaténer les tableaux, j'ai été surpris que lorsque j'ai fait les mêmes tests avec jRuby les tests étaient beaucoup plus lent. Est-ce que cela signifie que le vieil adagio à propos de jRuby étant plus rapide que MRI Ruby est parti? Ou s'agit-il de la façon dont les tableaux sont traités dans jRuby?Différence de performance entre MRI Ruby et jRuby
Voici le cas-test et les résultats en MRI Ruby 2.3.0 et jRuby 9.1.2.0 Les deux fonctionnent sur un boîtier Windows 7 64 bits, les 4 processeurs occupés pour 50-60%, la mémoire utilisée ± 5,5 Go. Le jRuby a dû être démarré avec le paramètre -J-Xmx1500M
pour fournir suffisamment d'espace de tas. J'ai dû supprimer le test avec push à cause du niveau de la pile trop profond et j'ai également retiré les méthodes les plus lentes pour ne pas faire les tests trop longtemps. runtime occasion Jave: 1.7.0_21
require 'Benchmark'
N = 100
class Array
def concat_all
self.reduce([], :+)
end
end
# small arrays
a = (1..10).to_a
b = (11..20).to_a
c = (21..30).to_a
Benchmark.bm do |r|
r.report('plus ') { N.times { a + b + c }}
r.report('concat ') { N.times { [].concat(a).concat(b).concat(c) }}
r.report('splash ') { N.times {[*a, *b, *c]} }
r.report('concat_all ') { N.times { [a, b, c].concat_all }}
r.report('flat_map ') { N.times {[a, b, c].flat_map(&:itself)} }
end
#large arrays
a = (1..10_000_000).to_a
b = (10_000_001..20_000_000).to_a
c = (20_000_001..30_000_000).to_a
Benchmark.bm do |r|
r.report('plus ') { N.times { a + b + c }}
r.report('concat ') { N.times { [].concat(a).concat(b).concat(c) }}
r.report('splash ') { N.times {[*a, *b, *c]} }
r.report('concat_all ') { N.times { [a, b, c].concat_all }}
r.report('flat_map ') { N.times {[a, b, c].flat_map(&:itself)} }
end
Cette question ne concerne pas les différentes méthodes utilisées, voir la question initiale pour cela. Dans les deux cas, l'IRM est 7 fois plus rapide! Quelqu'un peut-il m'expliquer pourquoi? Je suis aussi curieux de la façon dont d'autres implémentations faire, comme RBX (Rubinius)
C:\Users\...>d:\jruby\bin\jruby -J-Xmx1500M concat3.rb
user system total real
plus 0.000000 0.000000 0.000000 ( 0.000946)
concat 0.000000 0.000000 0.000000 ( 0.001436)
splash 0.000000 0.000000 0.000000 ( 0.001456)
concat_all 0.000000 0.000000 0.000000 ( 0.002177)
flat_map 0.010000 0.000000 0.010000 ( 0.003179)
user system total real
plus 140.166000 0.000000 140.166000 (140.158687)
concat 143.475000 0.000000 143.475000 (143.473786)
splash 139.408000 0.000000 139.408000 (139.406671)
concat_all 144.475000 0.000000 144.475000 (144.474436)
flat_map143.519000 0.000000 143.519000 (143.517636)
C:\Users\...>ruby concat3.rb
user system total real
plus 0.000000 0.000000 0.000000 ( 0.000074)
concat 0.000000 0.000000 0.000000 ( 0.000065)
splash 0.000000 0.000000 0.000000 ( 0.000098)
concat_all 0.000000 0.000000 0.000000 ( 0.000141)
flat_map 0.000000 0.000000 0.000000 ( 0.000122)
user system total real
plus 15.226000 6.723000 21.949000 (21.958854)
concat 11.700000 9.142000 20.842000 (20.928087)
splash 21.247000 12.589000 33.836000 (33.933170)
concat_all 14.508000 8.315000 22.823000 (22.871641)
flat_map 11.170000 8.923000 20.093000 (20.170945)
sur mon système (OS X, JRuby 9.1.6.0, 2.3.1 IRM), les tableaux « petits » tableaux sont plus rapides sur l'IRM alors que les « grands » sont 2 -4x plus rapide dans JRuby. Cela est dû à l'utilisation du processeur: l'IRM n'utilise qu'un seul cœur et JRuby fait tourner mon ventilateur. Je ne sais pas pourquoi les résultats sont si différents. – Stefan
J'ai trouvé le coupable: '-J-Xmx1500M'. Je n'ai pas utilisé cette option au début, donc la taille de tas maximum par défaut de Java a été utilisée ('4096M' sur mon système) et cela a très bien fonctionné. Si je fournis cette option, abaissant ainsi la valeur à «1500M», j'obtiens des résultats douloureusement lents. – Stefan
Comme avec presque toutes les questions de benchmarking «Pourquoi Java est lent», je soupçonne que vous ne faites pas correctement l'analyse comparative. Par exemple, JRuby compile seulement le code Ruby au bytecode JVM après qu'une méthode ait été exécutée 20 fois (je pense). Et HotSpot ne compile que le bytecode JVM au code machine natif après qu'une méthode ait été exécutée plusieurs * fois * (IIRC, le seuil par défaut pour le compilateur C1 est 20000). Aucune de vos méthodes n'est exécutée même à distance assez souvent pour être compilé, elles seront toujours interprétées. Par exemple, 'concat_all' est seulement exécuté' N' fois, donc 'N' devrait être ... –