Gibt es eine Möglichkeit, ostringstream malloc / free zu reduzieren?

8

Ich schreibe eine eingebettete App. An einigen Stellen verwende ich std :: ostringstream sehr, da es für meine Zwecke sehr praktisch ist. Ich habe jedoch gerade festgestellt, dass der Leistungseinbruch extrem ist, da das Hinzufügen von Daten zum Stream zu vielen Aufrufen von malloc und free führt. Gibt es eine Möglichkeit, es zu vermeiden?

Mein erster Gedanke war, den ostringstream statisch zu machen und ihn mit ostringstream :: set ("") zurückzusetzen. Dies kann jedoch nicht durchgeführt werden, da ich die Funktionen als reentrant verwenden muss.

    
Johan Kotlinski 01.03.2010, 18:27
quelle

4 Antworten

2

Nun, Booger wäre die Lösung, zu sprintf() zu wechseln. Es ist unsicher und fehleranfällig, aber es ist oft schneller.

Nicht immer obwohl. Wir können es nicht (oder ostringstream) für meinen Echtzeitjob nach der Initialisierung verwenden, da beide Speicherzuordnungen und -zuordnungen durchführen.

Wir umgehen das Problem, indem wir durch viele Ringe springen, um sicherzustellen, dass wir beim Start alle String-Konvertierungen durchführen (wenn wir noch nicht in Echtzeit sein müssen). Ich glaube, es gab eine Situation, in der wir unseren eigenen Konverter in ein Stack-Allocated-Array fester Größe geschrieben haben. Wir haben einige Einschränkungen für die Größe, auf die wir uns bei den spezifischen Conversions verlassen können.

Für eine allgemeinere Lösung können Sie Ihre eigene Version von ostringstream schreiben, die einen Puffer fester Größe verwendet (mit Fehlerprüfung an den Grenzen natürlich). Es wäre ein bisschen Arbeit, aber wenn Sie viel von diesen Stream-Operationen haben, könnte es sich lohnen.

    
T.E.D. 01.03.2010, 19:00
quelle
2

Wenn Sie wissen, wie groß die Daten sind, bevor Sie den Stream erstellen, können Sie osstrstream verwenden, dessen Konstruktor einen Puffer als Parameter verwenden kann. Somit wird es keine Speicherverwaltung der Daten geben.

    
Mark 01.03.2010 18:47
quelle
2

Wahrscheinlich wäre die genehmigte Vorgehensweise, um Ihr eigenes basic_stringbuf -Objekt für Ihre ostringstream zu erstellen. Dafür haben Sie ein paar Möglichkeiten. Eine wäre die Verwendung eines Puffers fester Größe, und overflow schlägt einfach fehl, wenn Sie versuchen, eine zu lange Ausgabe zu erstellen. Eine andere Möglichkeit wäre, einen Vektor als Puffer zu verwenden. Im Gegensatz zu std :: string garantiert der Vektor, dass die anhängigen Daten eine konstante Komplexität amortisieren. Es gibt auch niemals Daten aus dem Puffer frei, es sei denn, Sie zwingen es dazu, so dass es normalerweise zu der maximalen Größe wächst, mit der Sie es zu tun haben. Von diesem Zeitpunkt an sollte es keinen Speicher zuweisen oder freigeben, es sei denn, Sie erstellen eine Zeichenfolge, die länger als die verfügbare Länge ist.

    
Jerry Coffin 01.03.2010 18:54
quelle
1

std::ostringsteam ist eine Komfortschnittstelle. Es verbindet ein std::string mit einem std::ostream , indem es ein benutzerdefiniertes std::streambuf bereitstellt. Sie können Ihren eigenen std :: streambuf implementieren. Damit können Sie die gesamte Speicherverwaltung durchführen. Sie erhalten immer noch die schöne Formatierung von std::ostream , aber Sie haben die volle Kontrolle über die Speicherverwaltung. Das hat natürlich zur Konsequenz, dass Sie Ihre formatierte Ausgabe in char[] erhalten - aber das ist wahrscheinlich kein großes Problem, wenn Sie ein eingebetteter Entwickler sind.

    
MSalters 02.03.2010 09:11
quelle