Lorsque j'ai regardé les solutions dans les autres réponses, j'ai vu certaines choses qui, je le sais, sont mauvaises pour les performances. J'allais les mettre dans un commentaire, mais j'ai pensé qu'il était préférable de les évaluer et de partager les résultats. Vous pouvez testez-le vous-même . Voici mes résultats (ymmv) normalisés après l'opération la plus rapide dans chaque navigateur.
Voici les résultats du 2021-MAY-05
Test
Chrome
Firefox
Opéra
Bordure
Courageux
Nœud
1.0 temps
15 ms
14 ms
17 ms
17 ms
16 ms
14 ms
si-immédiat
1.00
1.00
1.00
1.00
1.00
1.00
si-indirect
2.20
1.21
2.06
2.18
2.19
1.93
switch-immediate
2.07
1.43
1.71
1.71
2.19
1.93
gamme de commutateurs
3.60
2.00
2.47
2.65
2.88
2.86
switch-range2
2.07
1.36
1.82
1.71
1.94
1.79
commutateur-indirect-array
2.93
1.57
2.53
2.47
2.75
2.50
commutateur linéaire de réseau
2.73
3.29
2.12
2.12
2.38
2.50
commutateur binaire de réseau
5.80
6.07
5.24
5.24
5.44
5.37
Les tests de 2021 ont été effectués sur Windows 10 64bit avec les versions suivantes : Chrome 90.0.4430.212 , Firefox 89.0b13 , Opera 76.0.4017.123 , Edge 90.0.818.62 , Brave 1.24.85 y Node 16.1.0 (était géré sous WSL)
Apple ne met pas à jour Safari pour Windows Il s'agit donc toujours de la version 5.1.7. Je l'ai changé en Brave dans ce test.
Voici les résultats de 2012-septembre-04, pour une comparaison historique :
Test
Chrome
Firefox
Opéra
MSIE
Safari
Nœud
1.0 temps
37 ms
73 ms
68 ms
184 ms
73 ms
21 ms
si-immédiat
1.0
1.0
1.0
2.6
1.0
1.0
si-indirect
1.2
1.8
3.3
3.8
2.6
1.0
switch-immediate
2.0
1.1
2.0
1.0
2.8
1.3
gamme de commutateurs
38.1
10.6
2.6
7.3
20.9
10.4
switch-range2
31.9
8.3
2.0
4.5
9.5
6.9
commutateur-indirect-array
35.2
9.6
4.2
5.5
10.7
8.6
commutateur linéaire de réseau
3.6
4.1
4.5
10.0
4.7
2.7
commutateur binaire de réseau
7.8
6.7
9.5
16.0
15.0
4.9
Les tests en 2012 ont été effectués sur Windows 7 32bit avec les versions suivantes : Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 . Nœud a été exécuté sur une boîte Linux 64bit parce que la résolution du timer sur Node pour Windows était 10ms au lieu de 1ms.
si-immédiat
Cette méthode est la plus rapide dans tous les environnements testés, sauf dans ... roulement de tambour MSIE ! (surprise, surprise).
C'est la manière recommandée de le mettre en œuvre.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
si-indirect
Il s'agit d'une variante de switch-indirect-array
mais avec if
-et est plus rapide dans tous les moteurs testés.
En 2021, il était 20 à 120 % (2012 : 0 à 280 %) plus lent que le test le plus rapide. Chrome prend plus de temps en 2021 (2,20) qu'en 2012 (1,2).
values=[
1000, 2000, ... 30000
];
if (val < values[0]) { /* do something */ } else
if (val < values[1]) { /* do something */ } else
...
if (val < values[29]) { /* do something */ } else
switch-immediate
Cela fonctionne lorsque vous pouvez effectuer un calcul pour obtenir un indice.
En 2021, il était de 40 à 120 % (2012 : 0 à 180 %) plus lent que le taux d'inflation. if-immediate
sauf dans MSIE où il est le plus rapide.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
gamme de commutateurs
Il est lent car le moteur doit comparer la valeur deux fois pour chaque cas.
En 2021, il était 1-2,6 fois (2012 : 1,6-38) plus lent que le test le plus rapide. Chrome a fait la plus grande amélioration, passant de 38 à 3,6, mais reste le moteur testé le plus lent.
switch (true) {
case (0 <= val && val < 1000): /* do something */ break;
case (1000 <= val && val < 2000): /* do something */ break;
...
case (29000 <= val && val < 30000): /* do something */ break;
}
switch-range2
Il s'agit d'une variante de switch-range
mais avec une seule comparaison par cas et donc plus rapide. L'ordre de la déclaration de cas est important car le moteur testera chaque cas dans l'ordre du code source. ECMAScript 2020 13.12.9
En 2021, il était 36 à 107 % plus lent que le test le plus rapide, mais en 2012, il était 1 à 31 fois plus lent. C'est toujours Chrome qui a les plus mauvaises performances sur ce test, mais il s'est amélioré de 32 à 2 fois.
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
commutateur-indirect-array
Dans cette variante, les plages sont stockées dans un tableau.
En 2021, il était de 57 à 193 % (2012 : 3 à 35 fois) plus lent que le test le plus rapide. La performance s'est améliorée dans tous les moteurs testés, et si Chrome est toujours le plus lent, il est passé de 35 à 2,93.
values=[1000, 2000 ... 29000, 30000];
switch(true) {
case (val < values[0]): /* do something */ break;
case (val < values[1]): /* do something */ break;
...
case (val < values[29]): /* do something */ break;
}
recherche linéaire de tableaux
Dans cette variante, les plages sont stockées dans un tableau.
En 2021, il était de 57 à 193 % (2012 : 3 à 35 fois) plus lent que le test le plus rapide. La performance s'est améliorée dans tous les moteurs testés, et si Chrome est toujours le plus lent, il est passé de 35 à 2,93.
values=[1000, 2000 ... 29000, 30000];
for (sidx=0, slen=values.length; sidx < slen; ++sidx) {
if (val < values[sidx]) break;
}
switch (sidx) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
commutateur binaire de réseau
Il s'agit d'une variante de array-linear-switch
mais avec une recherche binaire. Malheureusement, elle est plus lente que la recherche linéaire. Je ne sais pas si cela est dû à mon implémentation ou si la recherche linéaire est plus optimisée. Il se peut aussi que l'espace des clés soit trop petit.
En 2021, ce rythme était 4 à 5 fois (2012 : 4 à 16) plus lent. Ne pas utiliser .
values=[0, 1000, 2000 ... 29000, 30000];
while(range) {
range = Math.floor( (smax - smin) / 2 );
sidx = smin + range;
if ( val < values[sidx] ) { smax = sidx; } else { smin = sidx; }
}
switch (sidx) {
case 0: /* do something */ break;
...
case 29: /* do something */ break;
}
Conclusion
Si les performances sont importantes, utilisez if
-déclarations ou switch
avec des valeurs immédiates.
5 votes
Vos pas sont-ils réguliers ? Je veux dire, si vous divisez scrollLeft par 1000, vous pouvez passer de 1, 2, 3...
0 votes
Vous pourriez peut-être créer un tableau trié qui met en correspondance une plage de conditions avec l'opération correspondante, et y appliquer une recherche binaire. Ou si vos conditions sont suffisamment régulières, vous pourriez directement appeler
your_mapper_object[scrollLeft / SOME_CONST]
en supposant queyour_mapper_object
est quelque chose comme{1: some_func, 2: another_func, ...}
. Et dans ce cas, vous pouvez également utiliser switch.