Table des matières
Ne pas optimiser prématurément" >Ne pas optimiser prématurément
Suggestions d'optimisation" >Suggestions d'optimisation
1. Tableaux et tranches
Allouez de la mémoire pour les tranches à l'avance
Ne laissez pas une partie inutilisée de la tranche
2. Épissage correct des chaînes
转换优化
字符串驻留
避免分配
3. Structure
Évitez de copier de grandes structures
Évitez d'accéder aux champs de structure via des pointeurs
Manipulation des petites structures
Utilisez l'alignement pour réduire la taille de la structure
4. Fonctions
Utilisez des fonctions en ligne ou inlinez-les vous-même
raisonnable Choisissez judicieusement les paramètres de fonction
Valeurs de retour nommées
Enregistrez les résultats intermédiaires
Utilisez defer avec précaution
Aide au chemin chaud
5. Map
Allocation de mémoire à l'avance
Utiliser des structures vides comme valeurs
Effacer la carte
Essayez de ne pas utiliser de pointeurs dans les clés et les valeurs
Réduire le nombre de modifications
6. Interface
Calculer l'allocation de mémoire
Choisir le type optimal
Évitez l'allocation de mémoire
À utiliser uniquement en cas de besoin
7. Pointeurs, canaux, vérifications de limites
Évitez les déréférencements inutiles
L'utilisation des canaux est inefficace
Évitez les contrôles de limites inutiles
Résumé " > Résumé
Maison développement back-end Golang Aller : notes d'optimisation simples

Aller : notes d'optimisation simples

Jul 21, 2023 pm 01:04 PM
go

À l'ère du cloud computing, nous créons souvent des applications sans serveur (un modèle de développement cloud natif qui permet aux développeurs de créer et d'exécuter des applications sans gérer de serveurs). Lorsque nos projets adopteront ce modèle, le budget d’entretien des infrastructures sera en tête de liste. Si la charge sur notre service est faible, c'est pratiquement gratuit. Mais si quelque chose ne va pas, vous le paierez cher ! Lorsqu’il s’agit d’argent, vous êtes forcément amené à réagir d’une manière ou d’une autre.

Lorsque votre VPS exécute plusieurs applications de service, mais que l'une d'elles occupe parfois toutes les ressources, ce qui rend impossible l'accès au serveur via ssh. Vous passez à l’utilisation d’un cluster Kubernetes et définissez des limites pour toutes les applications. Nous avons ensuite vu certaines applications redémarrer alors que le OOM-killer résolvait le problème de « fuite » de mémoire.

Bien sûr, le MOO n'est pas toujours un problème de fuite, cela peut aussi être un dépassement de ressources. Les problèmes de fuite sont très probablement causés par des erreurs de programme. Le sujet dont nous parlons aujourd'hui est de savoir comment éviter cette situation.

Une consommation excessive de ressources nuit au portefeuille, ce qui signifie que nous devons prendre des mesures immédiates.

Ne pas optimiser prématurément

Parlons maintenant de l'optimisation. J'espère que vous comprendrez pourquoi nous ne devrions pas optimiser prématurément !

  • Premièrement, l'optimisation peut être un travail inutile. Parce que nous devrions d’abord étudier l’ensemble de l’application, et votre code ne sera probablement pas le goulot d’étranglement. Ce dont nous avons besoin, ce sont des résultats rapides, MVP (Minimum Viable Product, minimum viable product), et ensuite nous examinerons ses problèmes.
  • Deuxièmement, l'optimisation doit être basée sur une base. C’est-à-dire que chaque optimisation doit être basée sur un benchmark, et nous devons prouver quel profit elle nous apporte.
  • Troisièmement, l'optimisation peut apporter de la complexité. Ce que vous devez savoir, c'est que la plupart des optimisations rendent votre code moins lisible. Vous devez trouver cet équilibre.

Suggestions d'optimisation

Nous donnons maintenant quelques suggestions pratiques selon la classification standard des entités dans Go.

1. Tableaux et tranches

Allouez de la mémoire pour les tranches à l'avance

Essayez d'utiliser le troisième paramètre : <code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">make([]T, 0, len)</span>make([]T, 0, len)

Si le nombre exact d'éléments n'est pas connu et la tranche est de courte durée Oui, vous pouvez allouer une taille plus grande pour garantir que la tranche ne s'agrandit pas pendant l'exécution.

N'oubliez pas d'utiliser copy

Essayez de ne pas utiliser append lors de la copie, par exemple lors de la fusion de deux tranches ou plus.

Itération correcte

Une tranche contenant de nombreux éléments ou de gros éléments, utilisez pour pour obtenir un seul élément. De cette façon, les duplications inutiles seront évitées.

Multiplexage de tranches

Si une opération est effectuée sur la tranche entrante et renvoie un résultat modifié, nous pouvons le renvoyer. Cela évite une nouvelle allocation de mémoire.

🎜
Ne laissez pas une partie inutilisée de la tranche

Si vous devez couper un petit morceau de la tranche et l'utiliser uniquement, la partie principale de la tranche sera également conservée. L'approche correcte consiste à utiliser une nouvelle copie de cette petite tranche et à lancer l'ancienne tranche au GC.

2. Épissage correct des chaînes

Si l'épissage des chaînes peut être effectué en une seule instruction, utilisez <code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">+</span> 操作符。如果需要在循环中执行此操作,使用 <span style="font-size: 15px;">string.Builder</span>,并使用它的 <span style="font-size: 15px;">Grow</span> 方法预先指定 <span style="font-size: 15px;">Builder</span> 的大小,减少内存分配次数。

转换优化

string 和 []byte 在底层结构上非常相近,有时这两种类型之间可以通过强转换来避免内存分配。

字符串驻留

可以池化字符串,从而帮助编译器只存储一次相同的字符串。

避免分配

我们可以使用 map(级联)而不是复合键,我们可以使用字节切片。尽量不使用 <span style="font-size: 15px;">fmt</span>+ opérateur. Si vous devez le faire en boucle, utilisez

🎜string.Builder🎜🎜 et utilisez son 🎜🎜Grow🎜🎜 la méthode est pré-spécifiée🎜🎜Builder🎜🎜 taille pour réduire le nombre d'allocations de mémoire. 🎜🎜🎜Optimisation de la conversion🎜🎜🎜string et []byte sont très similaires dans la structure sous-jacente, et parfois une conversion forte peut être utilisée entre ces deux types pour éviter l'allocation de mémoire. 🎜🎜🎜String résident🎜🎜🎜 peut regrouper des chaînes, aidant ainsi le compilateur à stocker la même chaîne une seule fois. 🎜🎜🎜Éviter l'allocation🎜🎜🎜Nous pouvons utiliser map(cascade) au lieu de clés composites, nous pouvons utiliser des tranches d'octets. Essayez de ne pas utiliser 🎜🎜 fmt 🎜🎜 package, car toutes ses méthodes utilisent la réflexion. 🎜🎜

3. Structure

Évitez de copier de grandes structures

Nous comprenons que les petites structures ne comportent pas plus de 4 champs et pas plus d'une taille de mot machine.

Quelques scénarios de copie typiques

  • Projeté sur l'interface
  • Réception et envoi de canaux
  • Remplacement d'éléments dans la carte
  • Ajouter des éléments aux tranches
  • Itération (plage)
Évitez d'accéder aux champs de structure via des pointeurs

Le déréférencement coûte cher et nous devrions le faire le moins possible, surtout dans les boucles. Il perd également la possibilité d'utiliser des registres rapides.

Manipulation des petites structures

Ce travail est optimisé par l'éditeur, ce qui veut dire qu'il est bon marché.

Utilisez l'alignement pour réduire la taille de la structure

Nous pouvons réduire la taille de la structure elle-même en alignant la structure (en les disposant dans le bon ordre en fonction de la taille des champs).

4. Fonctions

Utilisez des fonctions en ligne ou inlinez-les vous-même

Essayez d'écrire de petites fonctions qui peuvent être intégrées par le compilateur, ce sera plus rapide, encore plus rapide que d'intégrer vous-même le code dans la fonction. Cela est particulièrement vrai pour les chemins chauds.

Lesquels ne seront pas en ligne

  • récupération
  • bloc de sélection
  • déclaration de type
  • defer
  • goroutine
  • pour-gamme
raisonnable Choisissez judicieusement les paramètres de fonction

Essayez d'utiliser de petits paramètres car leur réplication sera optimisée. Essayez de maintenir la réplication et la croissance de la pile équilibrées sur la charge du GC. Évitez un grand nombre de paramètres et laissez votre programme utiliser des registres rapides (leur nombre est limité).

Valeurs de retour nommées

Cela semble être plus efficace que de déclarer ces variables dans le corps de la fonction.

Enregistrez les résultats intermédiaires

Aidez le compilateur à optimiser votre code, enregistrez les résultats intermédiaires, et il y aura ensuite plus d'options pour optimiser votre code.

Utilisez defer avec précaution

Essayez de ne pas utiliser defer, ou du moins ne l'utilisez pas en boucle.

Aide au chemin chaud

Évitez d'allouer de la mémoire dans le chemin chaud, en particulier les objets de courte durée. Créez les branches les plus courantes (si, switch)

5. Map

Allocation de mémoire à l'avance

Identique à la tranche, lors de l'initialisation de la carte, spécifiez sa taille.

Utiliser des structures vides comme valeurs

struct{} n'est rien (ne prend pas de mémoire), il est donc très avantageux de l'utiliser lors du passage de signaux par exemple.

Effacer la carte

la carte ne peut que croître, pas rétrécir. Lorsque nous devons réinitialiser la carte, supprimer tous ses éléments ne nous aidera pas.

Essayez de ne pas utiliser de pointeurs dans les clés et les valeurs

Si la carte ne contient pas de pointeurs, alors le GC ne perdra pas de temps précieux dessus. Les chaînes utilisent également des pointeurs, vous devez donc utiliser des tableaux d'octets au lieu de chaînes comme clés.

Réduire le nombre de modifications

De même, nous ne voulons pas utiliser de pointeurs, mais nous pouvons utiliser une combinaison de carte et de tranche, en stockant les clés dans la carte et les valeurs dans la tranche. De cette façon, nous pouvons modifier la valeur sans restrictions.

6. Interface

Calculer l'allocation de mémoire

N'oubliez pas que lorsque vous souhaitez attribuer une valeur à une interface, vous devez d'abord la copier quelque part, puis y coller le pointeur. La clé est de copier. Il s'avère que le coût du boxing et du déballage de l'interface sera à peu près le même que celui de l'allocation de la taille de la structure.

Choisir le type optimal

Dans certains cas, il n'y a pas d'allocation lors du boxing et du unboxing des interfaces. Par exemple, des valeurs petites ou booléennes pour les variables et les constantes, des structures avec un champ simple, des pointeurs (y compris carte, canal, fonction)

Évitez l'allocation de mémoire

Comme ailleurs, essayez d'éviter les allocations inutiles. Par exemple attribuer une interface à une autre au lieu de boxer deux fois.

À utiliser uniquement en cas de besoin

Évitez d'utiliser des interfaces dans les paramètres de fonction fréquemment appelés et renvoyez les résultats. Nous n'avons pas besoin d'opérations de déballage supplémentaires. Réduisez la fréquence d’utilisation des appels de méthode d’interface car cela empêche l’inline.

7. Pointeurs, canaux, vérifications de limites

Évitez les déréférencements inutiles

Surtout dans les boucles car cela s'avère trop coûteux. Le déréférencement est quelque chose que nous ne voulons pas faire à nos propres frais.

L'utilisation des canaux est inefficace

La synchronisation des canaux est plus lente que les autres méthodes primitives de synchronisation. De plus, plus il y a de cas sélectionnés, plus notre programme sera lent. Cependant, select, case et default ont été optimisés.

Évitez les contrôles de limites inutiles

Cela coûte également cher et nous devrions l'éviter. Par exemple, vérifiez (obtenez) l’index de tranche maximum une seule fois, et non plusieurs fois. Il est préférable d'essayer d'opter pour l'option extrême maintenant.

Résumé

Tout au long de cet article, nous avons vu certaines des mêmes règles d'optimisation.

Aidez le compilateur à prendre la bonne décision et il vous remerciera. Allouez de la mémoire au moment de la compilation, utilisez des résultats intermédiaires et essayez de garder votre code lisible.

Je réitère que pour une optimisation implicite, les benchmarks sont obligatoires. Si quelque chose qui a fonctionné hier ne fonctionnera pas demain car le compilateur change trop rapidement entre les versions, et vice versa.

N'oubliez pas d'utiliser les outils d'analyse et de suivi intégrés de Go.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Où trouver la courte de la grue à atomide atomique
1 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment envoyer des messages Go WebSocket ? Comment envoyer des messages Go WebSocket ? Jun 03, 2024 pm 04:53 PM

Dans Go, les messages WebSocket peuvent être envoyés à l'aide du package gorilla/websocket. Étapes spécifiques : Établissez une connexion WebSocket. Envoyer un message texte : appelez WriteMessage(websocket.TextMessage,[]byte("message")). Envoyez un message binaire : appelez WriteMessage(websocket.BinaryMessage,[]byte{1,2,3}).

Comment faire correspondre les horodatages à l'aide d'expressions régulières dans Go ? Comment faire correspondre les horodatages à l'aide d'expressions régulières dans Go ? Jun 02, 2024 am 09:00 AM

Dans Go, vous pouvez utiliser des expressions régulières pour faire correspondre les horodatages : compilez une chaîne d'expression régulière, telle que celle utilisée pour faire correspondre les horodatages ISO8601 : ^\d{4}-\d{2}-\d{2}T \d{ 2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ . Utilisez la fonction regexp.MatchString pour vérifier si une chaîne correspond à une expression régulière.

Compréhension approfondie du cycle de vie des fonctions Golang et de la portée variable Compréhension approfondie du cycle de vie des fonctions Golang et de la portée variable Apr 19, 2024 am 11:42 AM

Dans Go, le cycle de vie de la fonction comprend la définition, le chargement, la liaison, l'initialisation, l'appel et le retour ; la portée des variables est divisée en niveau de fonction et au niveau du bloc. Les variables d'une fonction sont visibles en interne, tandis que les variables d'un bloc ne sont visibles que dans le bloc. .

Comment éviter les fuites de mémoire dans l'optimisation des performances techniques de Golang ? Comment éviter les fuites de mémoire dans l'optimisation des performances techniques de Golang ? Jun 04, 2024 pm 12:27 PM

Les fuites de mémoire peuvent entraîner une augmentation continue de la mémoire du programme Go en : fermant les ressources qui ne sont plus utilisées, telles que les fichiers, les connexions réseau et les connexions à la base de données. Utilisez des références faibles pour éviter les fuites de mémoire et ciblez les objets pour le garbage collection lorsqu'ils ne sont plus fortement référencés. En utilisant go coroutine, la mémoire de la pile de coroutines sera automatiquement libérée à la sortie pour éviter les fuites de mémoire.

La différence entre la langue Golang et Go La différence entre la langue Golang et Go May 31, 2024 pm 08:10 PM

Go et le langage Go sont des entités différentes avec des caractéristiques différentes. Go (également connu sous le nom de Golang) est connu pour sa concurrence, sa vitesse de compilation rapide, sa gestion de la mémoire et ses avantages multiplateformes. Les inconvénients du langage Go incluent un écosystème moins riche que les autres langages, une syntaxe plus stricte et un manque de typage dynamique.

Comment afficher la documentation des fonctions Golang dans l'EDI ? Comment afficher la documentation des fonctions Golang dans l'EDI ? Apr 18, 2024 pm 03:06 PM

Consultez la documentation de la fonction Go à l'aide de l'EDI : passez le curseur sur le nom de la fonction. Appuyez sur la touche de raccourci (GoLand : Ctrl+Q ; VSCode : Après avoir installé GoExtensionPack, F1 et sélectionnez « Go:ShowDocumentation »).

Un guide pour les tests unitaires des fonctions simultanées Go Un guide pour les tests unitaires des fonctions simultanées Go May 03, 2024 am 10:54 AM

Les tests unitaires des fonctions simultanées sont essentiels car cela permet de garantir leur comportement correct dans un environnement simultané. Des principes fondamentaux tels que l'exclusion mutuelle, la synchronisation et l'isolement doivent être pris en compte lors du test de fonctions concurrentes. Les fonctions simultanées peuvent être testées unitairement en simulant, en testant les conditions de concurrence et en vérifiant les résultats.

Comment utiliser le wrapper d'erreur de Golang ? Comment utiliser le wrapper d'erreur de Golang ? Jun 03, 2024 pm 04:08 PM

Dans Golang, les wrappers d'erreurs vous permettent de créer de nouvelles erreurs en ajoutant des informations contextuelles à l'erreur d'origine. Cela peut être utilisé pour unifier les types d'erreurs générées par différentes bibliothèques ou composants, simplifiant ainsi le débogage et la gestion des erreurs. Les étapes sont les suivantes : Utilisez la fonction error.Wrap pour envelopper les erreurs d'origine dans de nouvelles erreurs. La nouvelle erreur contient des informations contextuelles de l'erreur d'origine. Utilisez fmt.Printf pour générer des erreurs encapsulées, offrant ainsi plus de contexte et de possibilités d'action. Lors de la gestion de différents types d’erreurs, utilisez la fonction erreurs.Wrap pour unifier les types d’erreurs.

See all articles