Dans une question C ++ sur l'optimisation et le style de code , plusieurs réponses faisaient référence à "SSO" dans le contexte de l'optimisation des copies de std::string
. Que signifie SSO dans ce contexte?
Clairement pas "single sign on". "Optimisation des chaînes partagées", peut-être?
c++
string
optimization
Raedwald
la source
la source
std::string
implémentée", et une autre demande "qu'est-ce que SSO signifie", vous devez être absolument insensé pour les considérer comme la même questionRéponses:
Contexte / Aperçu
Les opérations sur les variables automatiques ("à partir de la pile", qui sont des variables que vous créez sans appeler
malloc
/new
) sont généralement beaucoup plus rapides que celles impliquant le magasin libre ("le tas", qui sont des variables créées à l'aide denew
). Cependant, la taille des tableaux automatiques est fixée au moment de la compilation, mais la taille des tableaux du magasin gratuit ne l'est pas. De plus, la taille de la pile est limitée (généralement quelques Mio), alors que le stockage gratuit n'est limité que par la mémoire de votre système.SSO est l'optimisation des chaînes courtes / petites. A
std::string
stocke généralement la chaîne en tant que pointeur vers le magasin gratuit ("le tas"), qui donne des caractéristiques de performances similaires à celles que vous appelieznew char [size]
. Cela évite un débordement de pile pour les très grandes chaînes, mais cela peut être plus lent, en particulier avec les opérations de copie. En tant qu'optimisation, de nombreuses implémentationsstd::string
créent un petit tableau automatique, quelque chose commechar [20]
. Si vous avez une chaîne de 20 caractères ou moins (dans cet exemple, la taille réelle varie), elle la stocke directement dans ce tableau. Cela évite du tout le besoin d'appelernew
, ce qui accélère un peu les choses.ÉDITER:
Je ne m'attendais pas à ce que cette réponse soit aussi populaire, mais puisque c'est le cas, permettez-moi de donner une implémentation plus réaliste, avec la mise en garde que je n'ai jamais lu une implémentation de SSO "dans la nature".
Détails d'implémentation
Au minimum, a
std::string
doit stocker les informations suivantes:La taille peut être stockée comme un
std::string::size_type
ou comme un pointeur vers la fin. La seule différence est de savoir si vous souhaitez avoir à soustraire deux pointeurs lorsque l'utilisateur appellesize
ou ajouter unsize_type
à un pointeur lorsque l'utilisateur appelleend
. La capacité peut également être stockée dans les deux sens.Vous ne payez pas ce que vous n'utilisez pas.
Tout d'abord, considérez l'implémentation naïve basée sur ce que j'ai décrit ci-dessus:
Pour un système 64 bits, cela signifie généralement qu'il
std::string
a 24 octets de «surcharge» par chaîne, plus 16 autres pour le tampon SSO (16 choisis ici au lieu de 20 en raison des exigences de remplissage). Cela n'aurait pas vraiment de sens de stocker ces trois membres de données plus un tableau local de caractères, comme dans mon exemple simplifié. Sim_size <= 16
, alors je vais mettre toutes les donnéesm_sso
, donc je connais déjà la capacité et je n'ai pas besoin du pointeur vers les données. Sim_size > 16
, alors je n'ai pas besoinm_sso
. Il n'y a absolument aucun chevauchement là où j'ai besoin de tous. Une solution plus intelligente qui ne gaspille aucun espace ressemblerait un peu plus à ceci (non testé, à titre d'exemple uniquement):Je suppose que la plupart des implémentations ressemblent davantage à ceci.
la source
std::string const &
, obtenir les données est une indirection de mémoire unique, car les données sont stockées à l'emplacement de la référence. S'il n'y avait pas d'optimisation de petite chaîne, l'accès aux données nécessiterait deux indirections mémoire (d'abord pour charger la référence à la chaîne et lire son contenu, puis la seconde pour lire le contenu du pointeur de données dans la chaîne).SSO est l'abréviation de «Small String Optimization», une technique où de petites chaînes sont incorporées dans le corps de la classe de chaînes plutôt que d'utiliser un tampon alloué séparément.
la source
Comme déjà expliqué par les autres réponses, SSO signifie Optimisation des petites / courtes chaînes . La motivation derrière cette optimisation est la preuve indéniable que les applications en général traitent des chaînes beaucoup plus courtes que des chaînes plus longues.
Comme expliqué par David Stone dans sa réponse ci - dessus , la
std::string
classe utilise un tampon interne pour stocker le contenu jusqu'à une longueur donnée, ce qui élimine le besoin d'allouer dynamiquement de la mémoire. Cela rend le code plus efficace et plus rapide .Cette autre réponse connexe montre clairement que la taille du tampon interne dépend de l'
std::string
implémentation, qui varie d'une plateforme à l'autre (voir les résultats de référence ci-dessous).Benchmarks
Voici un petit programme qui compare l'opération de copie de beaucoup de chaînes de même longueur. Il commence à imprimer le temps de copie de 10 millions de chaînes avec une longueur = 1. Puis il se répète avec des chaînes de longueur = 2. Il continue jusqu'à ce que la longueur soit de 50.
Si vous voulez exécuter ce programme, vous devez le faire comme
./a.out > /dev/null
pour que le temps d'impression des chaînes ne soit pas compté. Les nombres importants sont imprimésstderr
, ils apparaîtront donc dans la console.J'ai créé des graphiques avec la sortie de mes machines MacBook et Ubuntu. Notez qu'il y a un énorme saut dans le temps pour copier les chaînes lorsque la longueur atteint un point donné. C'est le moment où les chaînes ne rentrent plus dans le tampon interne et l'allocation de mémoire doit être utilisée.
Notez également que sur la machine Linux, le saut se produit lorsque la longueur de la chaîne atteint 16. Sur le macbook, le saut se produit lorsque la longueur atteint 23. Cela confirme que SSO dépend de l'implémentation de la plateforme.
Ubuntu
Macbook Pro
la source