Umgang mit std :: string / std :: vector Membervariablen bei Verwendung von boost :: singleton_pool

9

Ich schreibe eine performancekritische Anwendung, in der ich eine große Anzahl von ähnlichen Objekten erzeuge, um Aufträge zu platzieren. Ich verwende boost :: singleton_pool zum Zuweisen von Speicher. Endlich sieht meine Klasse so aus.

%Vor%

Ich habe kürzlich eine Frage über die Leistung veröffentlicht Vorteil bei der Verwendung von boost :: singleton_pool. Als ich die Leistungen von boost :: singleton_pool und Standard-Allokator, ich habe keinen Leistungsvorteil erhalten. Wenn jemand darauf hinwies, dass meine Klasse Mitglieder vom Typ std :: string hatte, deren Zuweisung nicht von meinem benutzerdefinierten Zuordner gesteuert wurde, entfernte ich die Variablen std :: string und wiederholte die Tests. Diesmal bemerkte ich einen erheblichen Leistungsschub.

  1. Nun, in meiner eigentlichen Anwendung kann ich Membervariablen der Zeit std :: string und std :: vector nicht loswerden. Sollte ich boost :: pool_allocator mit meinen Variablen std :: string und std :: vector?

  2. boost :: pool_allocator reserviert Speicher von einem zugrunde liegenden std :: singleton_pool. Ist es wichtig, ob verschiedene Member-Variablen (ich habe mehr als einen std :: string / std :: vector types in meiner MyOrder-Klasse. Auch verwende ich Pools für andere Klassen als MyOrder, die std :: string / std :: vector types enthalten wie Mitglieder auch) den gleichen Speicherpool verwenden? Wenn ja, wie stelle ich sicher, dass sie das eine oder andere tun?

sank 08.05.2012, 14:27
quelle

2 Antworten

2
  
  1. Nun, in meiner eigentlichen Anwendung kann ich Membervariablen der Zeit std :: string und std :: vector nicht loswerden. Sollte ich boost :: pool_allocator mit meinen std :: string und std :: vector Membervariablen benutzen?
  2.   

Ich habe diesen Teil von Boost nie untersucht, aber wenn Sie ändern wollen, wo Strings ihren Speicher zuweisen, müssen Sie beim Kompilieren einen anderen Zuordner an std::basic_string<> übergeben. Es geht nicht anders. Sie müssen sich jedoch der Nachteile bewusst sein: Zum Beispiel können solche Strings nicht mehr zu std::string zugewiesen werden. (Obwohl die Verwendung von c_str() funktionieren würde, könnte dies eine kleine Leistungseinbuße bedeuten.)

  
  1. boost :: pool_allocator weist Speicher von einem zugrunde liegenden std :: singleton_pool zu. Ist es wichtig, ob verschiedene Member-Variablen (ich habe mehr als einen std :: string / std :: vector types in meiner MyOrder-Klasse. Auch verwende ich Pools für andere Klassen als MyOrder, die std :: string / std :: vector types enthalten wie Mitglieder auch) den gleichen Speicherpool verwenden? Wenn ja, wie stelle ich sicher, dass sie das eine oder andere tun?
  2.   

Der ganze Sinn eines Pools besteht darin, mehr als ein Objekt hinein zu legen. Wenn es nur eine wäre, würden Sie keinen Pool brauchen. Also, ja, Sie können mehrere Objekte einfügen, einschließlich des dynamischen Speichers von mehreren std::string -Objekten.

Ob dies jedoch zu irgendwelchen Leistungsgewinnen führt, bleibt abzuwarten. Sie verwenden einen Pool, weil Sie Grund haben anzunehmen, dass es schneller als der Allzweckzuordner ist (anstatt es z. B. zum Zuweisen von Speicher aus einem bestimmten Bereich, wie z. B. gemeinsam genutztem Speicher) zu verwenden. Normalerweise ist ein solcher Pool schneller, da er Annahmen über die Größe der Objekte machen kann, die in ihm zugeordnet sind. Das trifft sicherlich auf Ihre MyOrder -Klasse zu: Objekte davon haben immer die gleiche Größe, ansonsten (größere abgeleitete Klassen) werden Sie ihnen im Pool nicht zugeordnet.
Das ist anders für std::string . Der Sinn einer dynamisch zuweisenden String-Klasse liegt darin, dass sie sich an beliebige String-Längen anpasst. Die Speicherblöcke, die dafür benötigt werden, sind von unterschiedlicher Größe (andernfalls könnten Sie nur Arrays chartern). Ich sehe wenig Platz für einen Pool-Allokator, um den Allzweck-Allokator dafür zu verbessern.

Nebenbei bemerkt: Ihr überladenes operator new() gibt das Ergebnis des Aufrufs des globalen zurück, aber Ihr operator delete übergibt einfach alles, was auf dem Weg zum free() dieses Pools ist. Das erscheint mir sehr verdächtig.

    
sbi 08.05.2012 19:43
quelle
1

Die Verwendung eines benutzerdefinierten Zuordners für die std::string / std::vector in Ihrer Klasse würde funktionieren (vorausgesetzt, der Zuordner ist korrekt) - aber nur Leistungstests sehen, ob Sie wirklich davon profitieren.

Alternativ können Sie, wenn Sie wissen, dass std::string / std::vector Obergrenzen hat, einen dünnen Wrapper um ein std::array (oder normales Array, wenn Sie nicht c ++ 11 haben) implementieren es ist ein Tropfen im Ersatz.

Auch wenn die Größe unbegrenzt ist, könnten Sie, wenn die meisten -Werte kleiner sind, die oben genannten std::array -basierten Implementierungen erweitern, indem Sie sie mit Ihrem Pooled Allocator zuweisen sie füllen sich.

    
Node 17.05.2012 18:54
quelle