
Dans bon nombre de mes projets frontaux, à un moment donné, j'ai dû faire face à une baisse de la productivité - cela se produit généralement lorsque la complexité de l'application augmente, ce qui est normal. Néanmoins, les développeurs sont toujours responsables des performances, donc dans mon article, je donnerai cinq conseils pour optimiser les applications que j'applique moi-même: certains peuvent sembler évidents, certains affectent les principes de base de la programmation - mais, je pense, rafraîchir la mémoire n'est pas superflu sera. Chaque conseil est accompagné de tests: vous pouvez les exécuter vous-même et tester les performances.
Traduit en AlconostPréface
N'oubliez pas: si le code n'a pas besoin d'être optimisé, n'entrez pas dedans. Bien sûr, le code que vous écrivez devrait fonctionner rapidement, et vous pouvez toujours trouver un algorithme plus rapide - mais celui écrit doit rester clair pour les autres développeurs. Dans la conférence «La programmation en tant qu'art», Donald Knuth a exprimé une idée très importante sur l'optimisation du code:
Le vrai problème était que les programmeurs passaient trop de temps à se soucier de l'efficacité dans des endroits et des moments inappropriés. L'optimisation prématurée est à l'origine de toutes les erreurs de programmation (ou du moins la plupart).
1. Recherche: au lieu des tableaux ordinaires - objets et tableaux associatifs
Lorsque vous travaillez avec des données, des situations surviennent souvent lorsque, par exemple, vous devez trouver un objet, en faire quelque chose, puis trouver un autre objet, etc. La structure de données la plus courante dans JS est un tableau, donc le stockage de données en eux est une pratique normale. Cependant, chaque fois que vous avez besoin de trouver quelque chose dans le tableau, vous devez utiliser des méthodes telles que "find", "indexOf", "filter" ou itérer avec des boucles - c'est-à-dire que vous devez parcourir les éléments du début à la fin. Ainsi, nous effectuons une recherche linéaire, dont la complexité est 0 (n) (dans le pire des cas, nous devrons effectuer autant de comparaisons qu'il y a d'éléments dans le tableau). Si vous effectuez cette opération plusieurs fois sur de petites baies, l'impact sur les performances sera faible. Cependant, si nous avons beaucoup d'éléments et que l'opération est effectuée plusieurs fois, les performances échoueront certainement.
Dans ce cas, ce sera une bonne solution pour convertir un tableau régulier en objet ou en tableau associatif et effectuer une recherche de clé: dans ces structures, les éléments sont accessibles avec la complexité O (1) - nous aurons un appel mémoire, quelle que soit la taille. L'amélioration de la vitesse de travail est obtenue grâce à l'utilisation d'une structure de données appelée
table de hachage .
Vous pouvez tester les performances ici:
https://jsperf.com/finding-element-object-vs-map-vs-array/1 . Voici mes résultats:

La différence est très importante: pour un tableau associatif et un objet, j'ai des millions d'opérations par seconde, alors que pour un tableau, le meilleur résultat est un peu plus d'une centaine d'opérations. Bien sûr, la conversion des données n'est pas prise en compte ici, mais même en tenant compte de son fonctionnement sera beaucoup plus rapide.
2. Au lieu d'exceptions - l'opérateur conditionnel "si"
Parfois, il semble plus facile d'ignorer la vérification nulle et de simplement attraper les exceptions correspondantes. Bien sûr, c'est une mauvaise habitude - vous n'avez pas besoin de le faire, et si vous en avez un dans votre code, il suffit de réécrire les sections correspondantes. Mais pour vous convaincre complètement, je soutiendrai cette recommandation par des tests. J'ai décidé de tester trois façons de faire des vérifications: l'expression «try-catch», la condition «if» et le calcul de «court-circuit».
Test:
https://jsperf.com/try-catch-vs-conditions/1 . Voici mes résultats:

Je pense qu'il est évident à partir d'ici qu'un contrôle de «null» est nécessaire. De plus, comme vous pouvez le voir, il n'y a presque aucune différence entre la condition "si" et le calcul du "court-circuit" - alors appliquez-vous à ce que ment l'âme.
3. Moins il y a de cycles, mieux c'est
Une autre considération évidente, mais peut-être controversée. Il existe de nombreuses fonctions pratiques pour les tableaux: «carte», «filtre», «réduire», de sorte que leur utilisation semble attrayante, et le code avec eux semble plus propre et plus facile à lire. Mais lorsque la question se pose d'améliorer la productivité, vous pouvez essayer de réduire le nombre de fonctions appelées. J'ai décidé d'analyser deux cas: 1) «filtrer», puis «carte», et 2) «filtrer», puis «réduire» - et les comparer avec la chaîne fonctionnelle, «forEach» et la boucle traditionnelle «for». Pourquoi exactement ces deux cas? Les tests montrent que les avantages obtenus peuvent ne pas être très importants. De plus, dans le deuxième cas, j'ai également essayé d'utiliser "filtre" lors de l'appel de "réduire".
Test de performance pour "filtre" et "carte":
https://jsperf.com/array-function-chains-vs-single-loop-filter-map/1 . Mes résultats:

On peut voir qu'un cycle est plus rapide, mais la différence est faible. La raison d'un si petit écart est l'opération de «poussée», qui n'est pas nécessaire lors de l'utilisation de la «carte». Par conséquent, dans ce cas, vous pouvez vous demander s'il est vraiment nécessaire de procéder à un cycle.
Maintenant, vérifions "filtrer" + "réduire":
https://jsperf.com/array-function-chains-vs-single-loop-filter-reduce/1 . Mes résultats:

Ici, la différence est déjà plus grande: la combinaison de deux fonctions en une a accéléré l'exécution de près de la moitié. Néanmoins, le passage au cycle traditionnel "for" donne une augmentation de vitesse beaucoup plus importante.
4. Utilisez des boucles régulières
Ces conseils peuvent également sembler controversés, car les développeurs adorent les cycles fonctionnels: ils sont bien lus et peuvent simplifier le travail. Cependant, ils sont moins efficaces que les cycles traditionnels. Je pense que vous remarquerez peut-être déjà la différence dans l'utilisation des boucles for, mais jetons un coup d'œil dans un test séparé:
https://jsperf.com/for-loops-in-few-different-ways/ . Comme vous pouvez le voir, en plus des mécanismes intégrés, j'ai également vérifié "forEach" dans la bibliothèque "Lodash" et "each" dans "jQuery". Résultats:

Et encore une fois, nous voyons que la boucle "for" la plus simple est beaucoup plus rapide que les autres. Certes, ces boucles ne sont valables que pour les tableaux - dans le cas d'autres objets itérables, vous devez utiliser "forEach", "for ... of" ou l'itérateur lui-même. Mais «for ... in» ne devrait être appliqué que s'il n'y a pas d'autre méthode du tout. N'oubliez pas non plus que «for ... in» accepte toutes les propriétés de l'objet (et dans le tableau les propriétés sont des index), ce qui peut conduire à des résultats imprévisibles. Étonnamment, les méthodes de Lodash et jQuery n'étaient pas si mauvaises en termes de performances, donc dans certains cas, vous pouvez les utiliser en toute sécurité au lieu du «forEach» intégré (il est intéressant de noter que dans le test, la boucle de Lodash a fonctionné plus rapidement que le intégré).
5. Utilisez les fonctions intégrées pour travailler avec le DOM
Parfois, vous regardez le code de quelqu'un d'autre et voyez que le développeur a importé jQuery uniquement pour manipuler le DOM - je suis sûr que vous l'avez vu aussi, car c'est l'une des bibliothèques JavaScript les plus populaires. Il est clair qu'il n'y a rien de mal à utiliser des bibliothèques pour contrôler le DOM: nous utilisons aujourd'hui React et Angular, et ils font de même. Cependant, il semble parfois que jQuery devrait être utilisé même pour des opérations simples pour extraire un élément du DOM et y apporter des modifications mineures.
Voici une comparaison des fonctions intégrées pour le DOM et des opérations JQuery similaires dans trois cas différents:
https://jsperf.com/native-dom-functions-vs-jquery/1 . Mes résultats:

Et encore une fois, les fonctions les plus élémentaires - «getElementById» et «getElementsByClassName» - se sont avérées être les plus rapides lors de la visualisation du DOM. Dans le cas des identifiants et des sélecteurs avancés, querySelector est également plus rapide que jQuery. Et dans un seul cas, «querySelectorAll» est plus lent que jQuery (obtention des éléments par nom de classe). Pour plus d'informations sur comment et comment remplacer jQuery, voir ici:
http://youmightnotneedjquery.com .
Il est clair que si vous utilisez déjà la bibliothèque pour gérer le DOM, il est fortement recommandé de vous y tenir - cependant, pour les cas simples, les outils intégrés suffisent.
Matériel supplémentaire
Ces cinq conseils vous aideront à écrire un code JavaScript plus rapide. Mais si vous souhaitez en savoir plus sur l'optimisation des performances, voici quelques recommandations:
1. Optimisation des bundles JavaScript à l'aide de Webpack: c'est un sujet très complet, mais si tout est fait correctement, le chargement des applications peut être considérablement accéléré.
2. Structures de données, algorithmes de base et leur complexité: beaucoup pensent que ce n'est «qu'une théorie», mais dans le premier paragraphe, nous avons vu comment cette théorie fonctionne dans la pratique.
3. Tests sur la page
jsPerf : ici, vous pouvez vous familiariser avec une comparaison de différentes façons d'accomplir la même tâche en JavaScript et en même temps voir un indicateur important dans la pratique - la différence de vitesse.
À propos du traducteurL'article a été traduit par Alconost.
Alconost
localise des jeux , des
applications et des sites dans 70 langues. Traducteurs en langue maternelle, tests linguistiques, plateforme cloud avec API, localisation continue, chefs de projet 24/7, tout format de ressources de chaîne.
Nous réalisons également
des vidéos de publicité et de formation - pour les sites qui vendent, présentent des images, de la publicité, des formations, des teasers, des explicateurs, des bandes-annonces pour Google Play et l'App Store.
→
En savoir plus