Comment beaucoup de différence de performances lors de l'utilisation chaîne vs char tableau?
J'ai le code suivant:
char fname[255] = {0}
snprintf(fname, 255, "%s_test_no.%d.txt", baseLocation, i);
vs
std::string fname = baseLocation + "_test_no." + std::to_string(i) + ".txt";
Celui qui fonctionne mieux? Le second impliquer temporaire de la création? Est-il meilleure façon de le faire?
Comment mesurez-vous la performance de quelque chose qui arrive une fois et prend le temps zéro?
Sauf si vous appelez ce code plusieurs millions de fois, vous aurez du mal à faire la différence. Mesure, oui, mais attention, pas tellement. Cela dit, il ya une bonne chance que la seconde va prendre plus de temps en raison de la création d'objets temporaires, mais un bon compilateur est susceptible d'optimiser beaucoup de cette suite.
Sauf si vous appelez ce code plusieurs millions de fois, vous aurez du mal à faire la différence. Mesure, oui, mais attention, pas tellement. Cela dit, il ya une bonne chance que la seconde va prendre plus de temps en raison de la création d'objets temporaires, mais un bon compilateur est susceptible d'optimiser beaucoup de cette suite.
OriginalL'auteur texasbruce | 2014-02-21
Vous devez vous connecter pour publier un commentaire.
Faisons tourner les chiffres:
Le code (j'ai utilisé PAPI des Chronomètres)
main.cpp
Jouer avec les commentaires d'obtenir d'une façon ou de l'autre.
10 millions d'itérations de ces deux méthodes sur ma machine avec la ligne de compilation:
À l'aide de char tableau:
L'aide de la chaîne approche:
Ainsi, au moins sur MA machine avec MON code et MON compilateur paramètres,
j'ai vu environ 50% de ralentissement lors du déplacement de chaînes de caractères.que des tableaux de caractères de subir une 34% de l'accélération sur les chaînes à l'aide de la formule suivante:Qui donne la différence de temps entre les approches en pourcentage sur le temps pour cordes seules. Mon pourcentage était correcte; j'ai utilisé le tableau de caractères approche comme un point de référence au lieu de cela, ce qui montre une 52% ralentissement lors du passage à la chaîne, mais j'ai trouvé qu'il était erroné.
Je vais prendre tout et tous les commentaires pour la façon dont je l'ai fait de mal 🙂
Edit: Compilé avec GCC 4.8.4:
chaîne
tableau de caractères
De sorte que le tableau de caractères approche reste nettement plus rapide bien que moins. Dans ces tests, il était d'environ 29% plus rapide.
Faire que baselocation 80 chaîne de caractères, déclarer char fname[255]={} aussi à l'intérieur du cycle. Puis faire un troisième essai et essayer de std::string a également déclaré à l'extérieur du cycle et de l'utiliser à l'intérieur avec de l'ajout ou de l'opérateur+= . J'ai confiance qu'on va gagner.
J'ai tenu compte de vos commentaires dans mon post. J'ai effectué les timings de la façon dont je l'ai fait à l'origine, car je l'ai senti plus purement capturé ce que l'OP a été fait. Aussi, j'ai mis à jour les horaires avec la dernière version de GCC que j'ai sur Ubuntu. (pas la dernière, dans l'ensemble, cependant. 5.2 est comme de ce moment de l'écriture)
Désolé, mais il ne ressemble pas à ce que j'ai suggéré. Ma suggestion est d'utiliser de 80 caractères chaîne de caractères comme un baselocation texte lui-même. Autre suggestion est de ne pas utiliser l'opérateur+ ou opérateur=(string&&), mais d'utiliser l'opérateur+= ou string::append à la place. Le string::reserve a seul point si vous insérez ou d'en ajouter à la chaîne. Qui peut être le cas lorsque vous construisez multimegabyte textes où cette fraction de microseconde questions. Faire des réserves avant de le déplacer à l'affectation n'a pas de sens.
Toutes mes excuses pour le retard. Merci pour la clarification. Je crois que je vois ce que vous êtes en train de suggérer. Il serait peut-être plus vite, mais je ne doute pas que la différence entre le string et char array approche va changer beaucoup de choses.
OriginalL'auteur AndyG
La
snprintf()
version sera presque certainement être un peu plus rapide. Pourquoi? Tout simplement parce qu'aucun d'allocation de mémoire. Lenew
opérateur est étonnamment cher, environ 250ns sur mon systèmesnprintf()
auront fini de tout à fait un peu de travail dans le temps.Qui ne veut pas dire que vous devriez utiliser le
snprintf()
approche: Le prix que vous payez est la sécurité. Il est tellement facile de se tromper avec le fixe taille de la mémoire tampon que vous fournissez àsnprintf()
, et vous devez absolument fournir un code pour le cas où le tampon n'est pas assez grand. Donc, ne pense plus qu'à l'aide desnprintf()
lorsque vous avez identifié cette partie de code pour être vraiment critique pour les performances.Si vous avez une POSIX-2008 système compatible, vous pouvez aussi penser à essayer
asprintf()
au lieu desnprintf()
, ilmalloc()
de la mémoire pour vous, vous donnant à peu près le même confort que C++string
s. Au moins sur mon système,malloc()
est un peu plus rapide que la builtinnew
-opérateur (ne me demandez pas pourquoi, tout de même).Edit:
Viens de voir, avez-vous utilisé des noms de fichier dans votre exemple. Si les noms de fichiers sont à votre préoccupation, oublier la performance de la chaîne de l'opération! Votre code ne passent pratiquement pas de temps. Sauf si vous avez de l'ordre de 100000 telles opérations de la chaîne par seconde, ils ne sont pas pertinents pour votre performance.
OriginalL'auteur cmaster
Si c'est VRAIMENT important, de mesurer les deux solutions. Si non, selon ce que vous pensez que plus de sens à partir de ce que les données que vous avez, de l'entreprise privée/style de codage des normes, etc. Assurez-vous d'utiliser de manière optimale construire, avec la même optimisation que vous allez utiliser dans la production réelle de construire, pas -O3 parce que c'est le plus élevé, si votre production de construire est aide -O1]
Je pense que les deux sont assez proches si vous ne faites qu'un peu. Si vous disposez de plusieurs millions, il peut y avoir une différence. Ce qui est plus rapide? Je suppose que le second [1], mais cela dépend de la personne qui a écrit la mise en œuvre de
snprintf
et qui a écrit lestd::string
mise en œuvre. Les deux ont certainement le potentiel pour prendre beaucoup plus de temps que vous attendez d'une approche naïve de la façon dont la fonction fonctionne (et peut-être courir plus vite que vous attendez)[1] Parce que j'ai travaillé avec printf, et ce n'est pas une simple fonction, il passe beaucoup de temps à bricoler avec divers groking de la chaîne de format. Ce n'est pas très efficace (et j'ai regardé ceux de la glibc et ces trop, et ils ne sont pas nettement mieux).
D'autre part
std::string
fonctions sont souvent incorporé depuis qu'ils sont modèle implémentations, ce qui améliore l'efficacité. Le joker dans le pack est de savoir si l'allocation de mémoire pourstd::string
qui est susceptible de se produire. Bien sûr, si en quelque sortebaselocation
s'avère être plutôt grand, vous ne voulez probablement pas à le stocker en tant que fixe la taille des locaux de la matrice de toute façon, ce qui égalise dans ce cas.OriginalL'auteur Mats Petersson