Bonne question, je me la suis posée récemment. Pour vous donner des chiffres précis, les benchmarks ci-dessous (en Scala, compilés vers pratiquement les mêmes bytecodes que le code Java équivalent) :
var cnt: String = ""
val tlocal = new java.lang.ThreadLocal[String] {
override def initialValue = ""
}
def loop_heap_write = {
var i = 0
val until = totalwork / threadnum
while (i < until) {
if (cnt ne "") cnt = "!"
i += 1
}
cnt
}
def threadlocal = {
var i = 0
val until = totalwork / threadnum
while (i < until) {
if (tlocal.get eq null) i = until + i + 1
i += 1
}
if (i > until) println("thread local value was null " + i)
}
disponible sur aquí ont été réalisées sur un AMD 4x 2,8 GHz dual-cores et un i7 quad-core avec hyperthreading (2,67 GHz).
Voici les chiffres :
i7
Des lunettes : Intel i7 2x quad-core @ 2.67 GHz Test : scala.threads.ParallelTests
Nom du test : loop_heap_read
Nombre de fils : 1 Total des tests : 200
Temps d'exécution : (affichant les 5 derniers) 9.0069 9.0036 9.0017 9.0084 9.0074 (moyenne = 9.1034 min = 8.9986 max = 21.0306 )
Nombre de fils : 2 Total des tests : 200
Temps d'exécution : (montrant les 5 derniers) 4.5563 4.7128 4.5663 4.5617 4.5724 (moyenne = 4.6337 min = 4.5509 max = 13.9476 )
Nombre de fils : 4 Total des tests : 200
Temps d'exécution : (montrant les 5 derniers) 2.3946 2.3979 2.3934 2.3937 2.3964 (moyenne = 2.5113 min = 2.3884 max = 13.5496 )
Nombre de fils : 8 Total des tests : 200
Temps d'exécution : (affichant les 5 derniers) 2.4479 2.4362 2.4323 2.4472 2.4383 (moyenne = 2.5562 min = 2.4166 max = 10.3726 )
Nom du test : threadlocal
Nombre de fils : 1 Total des tests : 200
Temps d'exécution : (affichant les 5 derniers) 91.1741 90.8978 90.6181 90.6200 90.6113 (moyenne = 91.0291 min = 90.6000 max = 129.7501 )
Nombre de fils : 2 Total des tests : 200
Temps d'exécution : (affichant les 5 derniers) 45.3838 45.3858 45.6676 45.3772 45.3839 (moyenne = 46.0555 min = 45.3726 max = 90.7108 )
Nombre de fils : 4 Total des tests : 200
Temps d'exécution : (affichant les 5 derniers) 22.8118 22.8135 59.1753 22.8229 22.8172 (moyenne = 23.9752 min = 22.7951 max = 59.1753 )
Nombre de fils : 8 Total des tests : 200
Temps d'exécution : (affichant les 5 derniers) 22.2965 22.2415 22.3438 22.3109 22.4460 (moyenne = 23.2676 min = 22.2346 max = 50.3583 )
AMD
Specs : AMD 8220 4x dual-core @ 2.8 GHz Test : scala.threads.ParallelTests
Nom du test : loop_heap_read
Travail total : 20000000 Nombre de fils : 1 Total des tests : 200
Temps d'exécution : (montrant les 5 derniers) 12.625 12.631 12.634 12.632 12.628 (moyenne = 12.7333 min = 12.619 max = 26.698 )
Nom du test : loop_heap_read Travail total : 20000000
Temps d'exécution : (montrant les 5 derniers) 6.412 6.424 6.408 6.397 6.43 (moyenne = 6.5367 min = 6.393 max = 19.716 )
Nombre de fils : 4 Total des tests : 200
Temps d'exécution : (montrant les 5 derniers) 3.385 4.298 9.7 6.535 3.385 (moyenne = 5.6079 min = 3.354 max = 21.603 )
Nombre de fils : 8 Total des tests : 200
Temps d'exécution : (montrant les 5 derniers) 5.389 5.795 10.818 3.823 3.824 (moyenne = 5.5810 min = 2.405 max = 19.755 )
Nom du test : threadlocal
Nombre de fils : 1 Total des tests : 200
Temps d'exécution : (affichant les 5 derniers) 200.217 207.335 200.241 207.342 200.23 (moyenne = 202.2424 min = 200.184 max = 245.369 )
Nombre de fils : 2 Total des tests : 200
Temps d'exécution : (affichant les 5 derniers) 100.208 100.199 100.211 103.781 100.215 (moyenne = 102.2238 min = 100.192 max = 129.505 )
Nombre de fils : 4 Total des tests : 200
Temps d'exécution : (montrant les 5 derniers) 62.101 67.629 62.087 52.021 55.766 (moyenne = 65.6361 min = 50.282 max = 167.433 )
Nombre de fils : 8 Total des tests : 200
Temps d'exécution : (montrant les 5 derniers) 40.672 74.301 34.434 41.549 28.119 (moyenne = 54.7701 min = 28.119 max = 94.424 )
Résumé
Un thread local est environ 10-20x celui de la lecture du tas. Il semble également bien s'adapter à cette implémentation JVM et à ces architectures avec le nombre de processeurs.
2 votes
Un thread local est fondamentalement un champ contenant un hashmap et un lookup où la clé est l'objet thread actuel. Il est donc beaucoup plus lent mais toujours rapide :)
1 votes
@eckes : il se comporte certainement comme ça, mais il n'est généralement pas implémenté de cette façon. Au lieu de cela,
Thread
contiennent une table de hachage (non synchronisée) dont la clé est l'adresse courante de l'utilisateur.ThreadLocal
objet