C ++ Russia Piter 2019 berichtet Rückblick

In einem gemeinsamen ITMO- und JetBrains- Masterstudiengang bitten wir Studenten, die zur Konferenz geschickt werden, einen Bericht mit einer Überprüfung der Berichte zu verfassen.
Wir veröffentlichen einen dieser Berichte über die Konferenz C ++ Russia Piter 2019. Der Autor ist ein Student im zweiten Jahr, Artyom Khoroshev.



Anfang november habe ich an der cpp-russia-piter konferenz teilgenommen, im folgenden werde ich über die berichte sprechen, an die ich mich erinnere.

Roman Rusyaev: C ++ - Ausnahmen durch das Prisma der Compileroptimierungen


Ein interessanter Bericht, in dem der Sprecher am Beispiel von LLVM über Null-Kosten-Ausnahmen in modernem C ++ sprach.

LLVM IR präsentiert das Programm als Kontrollflussdiagramm. In den Knoten des Graphen befinden sich Anweisungsblöcke, die befolgt werden müssen. Am Ende jedes Blocks befindet sich ein Abschlusszeichen, das die Kontrolle an den nächsten Block überträgt. Das Abschlusszeichen kann ein bedingter Übergang zu einem anderen Block, ein Rückgabebefehl oder ein spezieller Aufrufbefehl sein, der die Semantik des Aufrufs der Funktion aufweist und bei Erfolg den Kontrollfluss zu einem Block überträgt und im Ausnahmefall den Block angibt, zu dem Sie ihn verarbeiten möchten. Anweisungen innerhalb eines Blocks haben die Eigenschaft, dass wir alle Anweisungen ausführen, wenn wir auf einen Block treffen, oder dass wir überhaupt nicht in diesen Block fallen. Es gibt Optimierungen, die nur innerhalb eines einzelnen Blocks funktionieren können. Bei kleinen Blöcken wird der Kontext kleiner, daher ist es schlechter, Optimierungen vorzunehmen.
Der Redner sprach darüber, wie moderne Compiler Invoke-Anweisungen in Call-Anweisungen umwandeln können, die nicht mehr terminal sind, und dem Compiler dadurch mehr Raum für Optimierungen geben. Um sich jedoch nicht auf den Compiler zu verlassen, können Sie die noexcept-Funktion selbst schreiben (sofern dies korrekt ist), um sicherzustellen, dass der Compiler alle Optimierungen ausführt.

(Folien melden)

Maxim Khizhinsky: Komfortunterkunft für Schauspieler und Handler


Der Sprecher hat sich zum Ziel gesetzt, eine Reihe von Problemen im Zusammenhang mit der parallelen Programmierung zu beseitigen:

  • geteilte Daten
  • Kontextwechsel,
  • synchronisieren
  • Häufige spontane Erzeugung von Strömungen für kurzfristige Anforderungen.

Infolgedessen schlug der Redner vor, sein Programm in Komponenten zu unterteilen, deren Lebensdauer der Lebensdauer des Programms entspricht, und Komponenten in „Wohnungen“ zu unterteilen, deren Anzahl der Anzahl der Threads entsprechen sollte. Die Komponenten selbst sind daher Singlethread-Komponenten, und die Kommunikation zwischen den Komponenten sollte über die Nachrichtenübermittlung erfolgen. Ich bin damit einverstanden, dass dies das Problem löst, aber auf Kosten aller Anpassungen unseres Programms müssen wir dies zum Zeitpunkt der Kompilierung tun. Zum Zeitpunkt der Kompilierung ist es mindestens erforderlich, die Komponenten gleichmäßig auf die „Wohnungen“ zu verteilen, wodurch eine lastabhängige Neuverteilung des Systems verhindert wird. Aus diesem Grund sieht die Lösung meiner Meinung nach nicht flexibel genug aus.

(Folien melden)

Nikolay Beloborodov: Die Verwendung von Plattenverteilern in hochbelasteten Netzwerkanwendungen


Der Name spricht für sich. Der Redner erklärte, wie sie die Systemleistung mithilfe eines Plattenverteilers signifikant steigern konnten. Der Plattenverteiler arbeitet mit mehreren Einheiten:

  • Die Platte ist ein zusammenhängender Speicherbereich (normalerweise eine feste Größe), der in Abschnitte gleicher Größe unterteilt ist. In diesen Bereichen werden Objekte gleicher Größe gespeichert.
  • Cache - eine Liste von Platten mit der gleichen Aufteilung,
  • Slab Allocator - eine Reihe von Caches.

Dank dieser Konstruktion werden Objekte gleicher Größe lokal gespeichert. Die Aufhebung der Zuordnung wurde als Zeichen dafür entworfen, dass eine bestimmte Site schwach ist und wiederverwendet werden kann. Dies vermeidet Speicherfragmentierung.

Aus dieser Definition der Platte eines Allokators wird deutlich, dass sie gut geeignet ist, die Freigabe von Objekten hervorzuheben, deren Größe in einem begrenzten Intervall liegt. Wenn Sie beispielsweise jedes Mal eine größere Größe zuweisen, wird ein neuer Cache erstellt, und die alten Caches werden nicht wiederverwendet.

Der Redner sagte, dass aus diesem Grund einige Container zugunsten anderer aufgegeben werden müssten. Zum Beispiel wurde der Vektor durch eine Liste, die Hashmap durch einen Baum ersetzt, aber dennoch wurde ein Leistungsgewinn erzielt.

(Folien melden)

Anton Polukhin: C ++ Taxi Tricks


Die Berichte von Anton Polukhin sind immer interessant, und die Lösungen, die er anbietet, sehen gut aus. Diesmal zeigte Anton, wie das Pimpl-Muster in Bezug auf die dynamische Zuordnung verbessert werden kann. Dazu müssen Sie das Repository für das Implementierungsobjekt im Objekt selbst platzieren. Lassen Sie mich daran erinnern, dass das klassische Pickelmuster wie folgt lautet:

// Foo.h struct Foo { Foo(); private: struct Foo_impl; //forward declaration std::unique_ptr<Foo_impl> impl; }; // Foo.cpp //implementation struct Foo::Foo_impl { }; 

Wir wollen die dynamische Zuordnung aufheben, dafür bereiten wir vorab einen Platz direkt im Foo-Objekt vor:
 // Foo.h struct Foo { Foo(); private: struct Foo_impl; //forward declaration std::aligned_storage_t<sizeof(Foo_impl), alignof(Foo_impl)> impl; }; // Foo.cpp //implementation struct Foo::Foo_impl { } 

Diese Methode funktioniert nicht, da wir in Foo.h keine vollständigen Informationen über den Typ Foo_impl haben und ein Kompilierungsfehler empfangen wird. Die einzige verbleibende Lösung besteht darin, die Größe des Speichers im Voraus zu erraten.

 // Foo.h struct Foo { Foo(); private: struct Foo_impl; //forward declaration constexpr std::size_t kImplSize = 32; constexpr std::size_t kImplAlign = 8; std::aligned_storage_t<kImplSize, kImplAlign> impl; }; // Foo.cpp //implementation struct Foo::Foo_impl { } 

Sie müssen jedoch überprüfen, ob die Größe noch korrekt ist. Dies ist notwendig, da es sich bei dem Versuch, das Objekt in einem für es ungeeigneten Puffer abzulegen, um UB handelt.

 // Foo.h struct Foo { Foo(); ~Foo(); private: constexpr std::size_t kImplSize = 32; constexpr std::size_t kImplAlign = 8; struct Foo_impl; //forward declaration std::aligned_storage_t<kImplSize, kImplAlign> impl; }; // Foo.cpp //implementation struct Foo::Foo_impl { } struct Foo::~Foo() { static_assert(kImplSize==sizeof(Foo_impl),"Size and sizeof(T) mismatch"); static_assert(kImplAlign==alignof(kImplAlign),"Alignment and alignof(T) mismatch"); // call destructor of Foo_impl } 

Wir überprüfen die cpp-Datei, und wenn etwas falsch angezeigt wird, schließen wir mit einem Kompilierungsfehler und drucken die richtige Größe der Struktur aus, damit der Programmierer sie vom zweiten Versuch an erraten kann.

Anton zeigte, wie man seine Serialisierungsbibliothek in verschiedenen Formaten benutzerfreundlich macht, ohne die ADL-Funktion zu vergessen: Wenn Vorlagenparameter für Funktionsargumente vorhanden sind, wird die Funktion im Parameternamensraum dieser Argumente gesucht.

(Folien melden)

Eric Niebler: Eine einheitliche Abstraktion für Async in C ++


Ein interessanter Bericht, der die Probleme asynchroner Abstraktionen im vorhandenen Sprachstandard behandelt: Warum sind die Zukunft und das Versprechen langsam und ob wir die Bibliothek so gestalten können, dass diese Overheads vermieden werden. Die Facebook-Entwickler scheinen eine anständige Lösung zu haben: https://github.com/facebookexperimental/libunifex

(Folien melden)

Dmitry Kozhevnikov und Andrey Davydov: Zwei Berichte über Module


Das Programm hatte zwei aufeinanderfolgende Berichte über die Module. Nach dem Anhören beider Berichte stellte sich heraus, dass die Module noch nicht einsatzbereit sind. Dies hat mich ein wenig verärgert, da ich im Grunde nicht daran interessiert war, wie dieses neue Feature der Sprache implementiert wird, und ich dachte, dass C ++ 20 sofort herauskommen und einsatzbereit sein würde. Leider stellte sich heraus, dass dies nicht so ist.

(Folien mit Berichten: 1 , 2 )

Fazit


Die vergangene Konferenz zeigte interessante Beispiele für die Verwendung bekannter Sprachmerkmale. Eine große Anzahl von Berichten betraf Chips aus dem folgenden Standard - C ++ 20. Dies ist natürlich für alle C ++ - Entwickler sehr nützlich.

Source: https://habr.com/ru/post/de480798/


All Articles