Table des matières
La structure interne de slice et de string
réutilisation des tranches
opération d'ajout
Maison développement back-end Golang Découvrez la réutilisation de la tranche et de la chaîne de Golang dans un seul article

Découvrez la réutilisation de la tranche et de la chaîne de Golang dans un seul article

Jul 16, 2021 pm 03:34 PM
golang slice string 性能优化

Par rapport à c/c++, une grande amélioration de golang est l'introduction du mécanisme gc, qui n'oblige plus les utilisateurs à gérer eux-mêmes la mémoire, réduisant considérablement les bugs introduits par le programme en raison de fuites de mémoire, mais en même temps, gc entraîne également une surcharge de performances supplémentaire, et parfois même une utilisation inappropriée fait de gc un goulot d'étranglement en termes de performances. Par conséquent, lors de la conception de programmes Golang, une attention particulière doit être accordée à la réutilisation des objets pour réduire la pression sur. gc. Slice et string sont les types de base du golang. Comprendre les mécanismes internes de ces types de base nous aidera à mieux réutiliser ces objets

La structure interne de slice et de string

La structure interne de slice et de string peut être trouvée dans$GOROOT/src/reflect/value.go

type StringHeader struct {
    Data uintptr
    Len  int
}

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}
Copier après la connexion
.

Vous pouvez voir qu'une chaîne contient un pointeur de données et une longueur. La longueur est immuable.

Slice contient un pointeur de données, une longueur et une capacité. Lorsque la capacité n'est pas suffisante, une nouvelle mémoire sera réappliquée. le pointeur Data pointera vers la nouvelle adresse, l'espace d'adressage d'origine sera libéré

Il ressort de ces structures que l'affectation de la chaîne et de la tranche, y compris sa transmission en tant que paramètre, n'est qu'une copie superficielle du Pointeur de données comme la structure personnalisée

réutilisation des tranches

opération d'ajout

si1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
si2 := si1
si2 = append(si2, 0)
Convey("重新分配内存", func() {
    header1 := (*reflect.SliceHeader)(unsafe.Pointer(&si1))
    header2 := (*reflect.SliceHeader)(unsafe.Pointer(&si2))
    fmt.Println(header1.Data)
    fmt.Println(header2.Data)
    So(header1.Data, ShouldNotEqual, header2.Data)
})
Copier après la connexion

si1 et si2 pointent tous deux vers le même tableau au début. Lorsque l'opération d'ajout est effectuée sur si2, car la valeur Cap d'origine n'est pas suffisante, un nouvel espace est nécessaire. à réappliquer, donc la valeur des données change, dans ce $GOROOT/src/reflect/value.go Le fichier contient également des stratégies pour les nouvelles valeurs de plafond. Dans cette fonction, lorsque le plafond est inférieur à 1024, il augmentera de façon exponentielle. Lorsqu'il dépasse, il augmentera de 25 %. à chaque fois. Cette croissance de la mémoire n'est pas seulement une copie de données. (La copie de l'ancienne adresse vers la nouvelle adresse) nécessite des performances supplémentaires, et la libération de l'ancienne mémoire d'adresse entraînera également une charge supplémentaire sur gc, donc si vous pouvez connaître la longueur. des données, essayez d'utiliser grow mémoire pré-allouée, non Lorsque vous connaissez la longueur, vous pouvez envisager la méthode de réutilisation de la mémoire suivantemake([]int, len, cap)

Réutilisation de la mémoire

si1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
si2 := si1[:7]
Convey("不重新分配内存", func() {
    header1 := (*reflect.SliceHeader)(unsafe.Pointer(&si1))
    header2 := (*reflect.SliceHeader)(unsafe.Pointer(&si2))
    fmt.Println(header1.Data)
    fmt.Println(header2.Data)
    So(header1.Data, ShouldEqual, header2.Data)
})

Convey("往切片里面 append 一个值", func() {
    si2 = append(si2, 10)
    Convey("改变了原 slice 的值", func() {
        header1 := (*reflect.SliceHeader)(unsafe.Pointer(&si1))
        header2 := (*reflect.SliceHeader)(unsafe.Pointer(&si2))
        fmt.Println(header1.Data)
        fmt.Println(header2.Data)
        So(header1.Data, ShouldEqual, header2.Data)
        So(si1[7], ShouldEqual, 10)
    })
})
Copier après la connexion

si2 est une tranche de si1 Dès le premier morceau de code, vous. Nous pouvons voir que la tranche ne réalloue pas de mémoire. Les pointeurs Data de si2 et si1 pointent vers la même adresse, et comme le montre le deuxième morceau de code, lorsque nous ajoutons une nouvelle valeur à si2, nous constatons qu'il y en a toujours. pas d'allocation de mémoire, et cette opération entraîne également un changement de la valeur de si1, car les deux pointent à l'origine vers la même zone de données. En utilisant cette fonctionnalité, il suffit de laisser

effacer continuellement le contenu de si1 pour réaliser la réutilisation de la mémoiresi1 = si1[:0]

.

PS : Vous pouvez utiliser pour implémenter une copie approfondiecopy(si2, si1)

string

Convey("字符串常量", func() {
    str1 := "hello world"
    str2 := "hello world"
    Convey("地址相同", func() {
        header1 := (*reflect.StringHeader)(unsafe.Pointer(&str1))
        header2 := (*reflect.StringHeader)(unsafe.Pointer(&str2))
        fmt.Println(header1.Data)
        fmt.Println(header2.Data)
        So(header1.Data, ShouldEqual, header2.Data)
    })
})
Copier après la connexion

This L'exemple est relativement simple. Les constantes de chaîne utilisent la même zone d'adresse

Convey("相同字符串的不同子串", func() {
    str1 := "hello world"[:6]
    str2 := "hello world"[:5]
    Convey("地址相同", func() {
        header1 := (*reflect.StringHeader)(unsafe.Pointer(&str1))
        header2 := (*reflect.StringHeader)(unsafe.Pointer(&str2))
        fmt.Println(header1.Data, str1)
        fmt.Println(header2.Data, str2)
        So(str1, ShouldNotEqual, str2)
        So(header1.Data, ShouldEqual, header2.Data)
    })
})
Copier après la connexion
différentes sous-chaînes de la même chaîne. Aucune nouvelle mémoire supplémentaire ne sera demandée. . Cependant, il convient de noter que la même chaîne fait ici référence à

, et Nonstr1.Data == str2.Data && str1.Len == str2.Len, l'exemple suivant peut illustrerstr1 == str2 mais ses données ne sont pas les mêmesstr1 == str2

Convey("不同字符串的相同子串", func() {
    str1 := "hello world"[:5]
    str2 := "hello golang"[:5]
    Convey("地址不同", func() {
        header1 := (*reflect.StringHeader)(unsafe.Pointer(&str1))
        header2 := (*reflect.StringHeader)(unsafe.Pointer(&str2))
        fmt.Println(header1.Data, str1)
        fmt.Println(header2.Data, str2)
        So(str1, ShouldEqual, str2)
        So(header1.Data, ShouldNotEqual, header2.Data)
    })
})
Copier après la connexion
En fait, pour les chaînes, vous n'avez qu'à retenir une chose, les chaînes sont immuables et aucune opération sur les chaînes ne s'appliquera à la mémoire supplémentaire (pour les pointeurs de données internes uniquement). J'ai déjà intelligemment conçu un cache pour stocker les chaînes afin de réduire l'espace occupé par les chaînes répétées. En fait, à moins que la chaîne elle-même ne soit créée par.

, sinon, cette chaîne elle-même est une sous-chaîne d'une autre chaîne (telle que la chaîne obtenue via []byte). Cela ne s'appliquera pas à l'espace supplémentaire. Cela est tout simplement inutile. strings.Split

Pour plus d'articles techniques liés au golang, veuillez visiter la colonne didacticiel

golang !

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

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

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 lire et écrire des fichiers en toute sécurité avec Golang ? Comment lire et écrire des fichiers en toute sécurité avec Golang ? Jun 06, 2024 pm 05:14 PM

Lire et écrire des fichiers en toute sécurité dans Go est crucial. Les directives incluent : Vérification des autorisations de fichiers Fermeture de fichiers à l'aide de reports Validation des chemins de fichiers Utilisation de délais d'attente contextuels Le respect de ces directives garantit la sécurité de vos données et la robustesse de vos applications.

Comment configurer le pool de connexions pour la connexion à la base de données Golang ? Comment configurer le pool de connexions pour la connexion à la base de données Golang ? Jun 06, 2024 am 11:21 AM

Comment configurer le pool de connexions pour les connexions à la base de données Go ? Utilisez le type DB dans le package base de données/sql pour créer une connexion à la base de données ; définissez MaxOpenConns pour contrôler le nombre maximum de connexions simultanées ; définissez MaxIdleConns pour définir le nombre maximum de connexions inactives ; définissez ConnMaxLifetime pour contrôler le cycle de vie maximum de la connexion ;

Ticage de performances Nginx: Optimisation de la vitesse et de la faible latence Ticage de performances Nginx: Optimisation de la vitesse et de la faible latence Apr 05, 2025 am 12:08 AM

Le réglage des performances de Nginx peut être obtenu en ajustant le nombre de processus de travail, la taille du pool de connexion, l'activation des protocoles de compression GZIP et HTTP / 2 et en utilisant l'équilibrage du cache et de la charge. 1. Ajustez le nombre de processus de travail et la taille du pool de connexion: Worker_ProcessesAuto; Événements {Worker_Connections1024;}. 2. Activer la compression GZIP et le protocole http / 2: http {gzipon; serveur {écouter443sslhttp2;}}. 3. Utilisez l'optimisation du cache: http {proxy_cache_path / path / to / cachelevels = 1: 2k

Golang Framework vs Go Framework : comparaison de l'architecture interne et des fonctionnalités externes Golang Framework vs Go Framework : comparaison de l'architecture interne et des fonctionnalités externes Jun 06, 2024 pm 12:37 PM

La différence entre le framework GoLang et le framework Go se reflète dans l'architecture interne et les fonctionnalités externes. Le framework GoLang est basé sur la bibliothèque standard Go et étend ses fonctionnalités, tandis que le framework Go se compose de bibliothèques indépendantes pour atteindre des objectifs spécifiques. Le framework GoLang est plus flexible et le framework Go est plus facile à utiliser. Le framework GoLang présente un léger avantage en termes de performances et le framework Go est plus évolutif. Cas : gin-gonic (framework Go) est utilisé pour créer l'API REST, tandis qu'Echo (framework GoLang) est utilisé pour créer des applications Web.

Comment enregistrer les données JSON dans la base de données dans Golang ? Comment enregistrer les données JSON dans la base de données dans Golang ? Jun 06, 2024 am 11:24 AM

Les données JSON peuvent être enregistrées dans une base de données MySQL à l'aide de la bibliothèque gjson ou de la fonction json.Unmarshal. La bibliothèque gjson fournit des méthodes pratiques pour analyser les champs JSON, et la fonction json.Unmarshal nécessite un pointeur de type cible pour désorganiser les données JSON. Les deux méthodes nécessitent la préparation d'instructions SQL et l'exécution d'opérations d'insertion pour conserver les données dans la base de données.

Comment trouver la première sous-chaîne correspondant à une expression régulière Golang ? Comment trouver la première sous-chaîne correspondant à une expression régulière Golang ? Jun 06, 2024 am 10:51 AM

La fonction FindStringSubmatch recherche la première sous-chaîne correspondant à une expression régulière : la fonction renvoie une tranche contenant la sous-chaîne correspondante, le premier élément étant la chaîne entière correspondante et les éléments suivants étant des sous-chaînes individuelles. Exemple de code : regexp.FindStringSubmatch(text,pattern) renvoie une tranche de sous-chaînes correspondantes. Cas pratique : Il peut être utilisé pour faire correspondre le nom de domaine dans l'adresse email, par exemple : email:="user@example.com", pattern:=@([^\s]+)$ pour obtenir la correspondance du nom de domaine [1].

Transformant du développement frontal au développement back-end, est-il plus prometteur d'apprendre Java ou Golang? Transformant du développement frontal au développement back-end, est-il plus prometteur d'apprendre Java ou Golang? Apr 02, 2025 am 09:12 AM

Chemin d'apprentissage du backend: le parcours d'exploration du front-end à l'arrière-end en tant que débutant back-end qui se transforme du développement frontal, vous avez déjà la base de Nodejs, ...

Comment utiliser un fuseau horaire prédéfini avec Golang ? Comment utiliser un fuseau horaire prédéfini avec Golang ? Jun 06, 2024 pm 01:02 PM

L'utilisation de fuseaux horaires prédéfinis dans Go comprend les étapes suivantes : Importez le package « time ». Chargez un fuseau horaire spécifique via la fonction LoadLocation. Utilisez le fuseau horaire chargé dans des opérations telles que la création d'objets Time, l'analyse de chaînes horaires et l'exécution de conversions de date et d'heure. Comparez les dates en utilisant différents fuseaux horaires pour illustrer l'application de la fonctionnalité de fuseau horaire prédéfini.

See all articles