2010-03-01 2 views
8

J'écris une application intégrée. Dans certains endroits, j'utilise beaucoup std :: ostringstream, car c'est très pratique pour mes besoins. Cependant, je viens de découvrir que le coup de performance est extrême car l'ajout de données dans le flux entraîne de nombreux appels à malloc et gratuit. Y a-t-il un moyen de l'éviter? Ma première pensée était de rendre l'ostringstream statique et de le réinitialiser en utilisant ostringstream :: set (""). Cependant, cela ne peut pas être fait car j'ai besoin que les fonctions soient réentrantes.Existe-t-il un moyen de réduire ostringstream malloc/free?

+0

Dupe http://stackoverflow.com/questions/1941064/should-i-preallocate-stdstringstream –

+0

Hmm ... la question de dupe ne donne cependant pas une réponse valide. –

+0

En outre, le "dupe" pré-suppose une réponse. – MSalters

Répondre

2

Eh bien, Booger solution serait de passer à sprintf(). C'est dangereux et sujet aux erreurs, mais c'est souvent plus rapide.

Pas toujours bien. Nous ne pouvons pas l'utiliser (ou ostringstream) sur mon travail en temps réel après l'initialisation car les deux effectuent des allocations de mémoire et des désallocations. Notre façon de contourner le problème est de passer à travers un grand nombre de cerceaux pour nous assurer que nous effectuons toutes les conversions de chaînes au démarrage (lorsque nous ne devons pas encore être en temps réel). Je pense qu'il y a eu une situation où nous avons écrit notre propre convertisseur dans un tableau alloué par pile de taille fixe. Nous avons des contraintes de taille sur lesquelles nous pouvons compter pour les conversions spécifiques en question. Pour une solution plus générale, vous pouvez envisager d'écrire votre propre version d'ostringstream qui utilise un tampon de taille fixe (avec un contrôle d'erreur sur les limites qui restent, bien sûr). Ce serait un peu de travail, mais si vous avez un lot de ces opérations de flux, il pourrait en valoir la peine.

+0

Qu'est-ce que vous utilisez à la place? –

+0

J'ai commencé à ajouter cela, mais reculé. Je vais aller de l'avant et le mettre pour vous. –

+0

Vous pouvez au moins utiliser snprintf (avec un tampon de pile), mais je ne le préconiserais pas, à moins que le profilage ne prouve qu'il offre les avantages dont vous avez besoin et que vous décidiez que les inconvénients en valent la peine. –

2

Si vous connaissez la taille des données avant de créer le flux, vous pouvez utiliser ostrstream dont le constructeur peut prendre un buffer en paramètre. Ainsi, il n'y aura pas de gestion de la mémoire des données.

2

Probablement la manière approuvée de traiter ceci serait de créer votre propre objet basic_stringbuf à utiliser avec votre ostringstream. Pour cela, vous avez plusieurs choix. Un serait d'utiliser un tampon de taille fixe, et ont overflow échouer simplement lorsque/si vous essayez de créer une sortie qui est trop longue. Une autre possibilité serait d'utiliser un vecteur comme tampon. Contrairement à std :: string, le vecteur garantit que les données ajoutées auront une complexité constante amortie. Il ne libère jamais non plus de données à partir du tampon, sauf si vous le forcez à le faire, de sorte qu'il va normalement atteindre la taille maximale avec laquelle vous traitez. À partir de ce moment, il ne doit pas allouer ou libérer de la mémoire sauf si vous créez une chaîne dont la longueur est actuellement supérieure à la longueur disponible.

+0

J'ai vérifié la source de l'implémentation STL que j'utilise, si je la passe une chaîne au constructeur ostringstream elle fait juste une copie de cette chaîne ... –

+0

Oui, je m'y attendais. Je vous conseille de créer votre propre objet stringbuf et de lui attacher un flux. –

+0

Si vous voulez passer un tampon en cours d'utilisation ostrstream pas ostringstream – Mark

1

std::ostringsteam est une interface de commodité. Il relie un std::string à un std::ostream en fournissant un std::streambuf personnalisé. Vous pouvez implémenter votre propre std :: streambuf. Cela vous permet de faire toute la gestion de la mémoire. Vous obtenez toujours la bonne mise en forme de std::ostream, mais vous avez un contrôle total sur la gestion de la mémoire. Bien sûr, la conséquence est que vous obtenez votre sortie formatée dans un char[] - mais ce n'est probablement pas un gros problème si vous êtes un développeur intégré.

+0

Ce tutoriel a été utile pour implémenter un std personnalisé: streambuf http://www.mr-edd.co .uk/blog/beginners_guide_streambuf –

Questions connexes