Binärkompatibilität: jetzt oder nie

Übersetzung der Veröffentlichung von Titus Winters in der Arbeitsgruppe 21 (WG21) - C ++ Language Standardization Committee. Der Autor diskutiert ein wichtiges Thema: Unterstützung für Abwärtsbinärkompatibilität oder ABI (Application Binary Interface).

In den letzten Jahren habe ich bei WG21 aktiv dafür geworben, dass Fortschritt wichtiger ist als Abwärtskompatibilität. Aber ich selbst glaube nicht mehr daran, insbesondere im Hinblick auf die Aufrechterhaltung der Binärkompatibilität (ABI). In den letzten drei Releases (C ++ 14, C ++ 17 und C ++ 20) war ABI so stabil wie möglich. Selbst wenn WG21 beschließt, die ABI-Abwärtskompatibilität in C ++ 23 zu unterbrechen, bieten wir seit mehr als 10 Jahren Binärkompatibilität auf vielen Plattformen. Meiner Meinung nach dominiert das Gesetz von Hyrum bei umfangreichen Änderungen von Softwaresystemen. Jetzt können Sie nicht sagen, wie viele Benutzer davon ausgehen, dass die Stabilität der ABI-Standardbibliothek (egal wie weise oder explizit oder implizit) fest in den Subkortex eingenäht ist, vielleicht die Hälfte der C ++ - Entwickler weltweit.


Ich führe eine Liste darüber, was WG21 in der Sprache beheben könnte, wenn wir uns entscheiden, den ABI zu „brechen“. Und ich kann nicht mit Sicherheit sagen, dass die Gesamtkosten für Nacharbeiten, die nur die Implementierung dieser Liste erfordern, mit den Kosten für die Verletzung von ABI im gesamten Ökosystem vergleichbar sind. Wir haben viele kleine Verbesserungen in der Konsistenz der API, der Qualität des Standardbibliothekscodes usw. gesehen, aber ohne Zweifel gibt es keine einzige "Durchbruch" -Änderung, die diese Kosten für den durchschnittlichen Entwickler rechtfertigen würde. Vielleicht würden wir bessere Implementierungen des Standards erhalten und die Möglichkeit geben, Probleme für Implementierungen zu lösen, die heute nicht den Standardspezifikationen entsprechen. Aber keine einzige Verbesserung auf meiner Liste ist eindeutig die Kosten wert.


Noch wichtiger ist, dass wir aufgrund von ABI-Einschränkungen keine signifikanten Leistungsverluste beseitigen können. Wir können die erheblichen Kosten für die Übergabe von unique_ptr nach Wert nicht loswerden [Chandlers Vortrag auf CppCon 2019 wird später veröffentlicht], wir können std :: hash oder die Platzierung der Klasse im Speicher für unorder__ap nicht ändern, ohne dass jeder gezwungen ist, alles überall neu zu kompilieren. Die Leistung von Hashes wurde im Laufe der Jahre eingehend untersucht. Unter Berücksichtigung der Optimierung der Suchvorgänge in der Tabelle und des eigentlichen Hashings sind wir zuversichtlich, dass wir eine unordered_map / std :: hash-Implementierung bereitstellen können, die API-kompatibel ist und eine Leistungssteigerung von 200-300% bietet. ABI-Einschränkungen erlauben dies jedoch nicht. Zusätzliche Studien zur Optimierung und Optimierung von SSO für std :: string deuten auf eine nicht triviale Leistungssteigerung hin (1% bei Mikrobenchmarks und Skalierung) - die API ist nicht betroffen, ABI-Einschränkungen lassen dies jedoch nicht zu.

Der ausschließlich von ABI blockierte Gesamtproduktivitätsverlust erreicht mehrere Prozentpunkte - möglicherweise bis zu 5-10%. Dies ist nicht etwas, worauf das gesamte Ökosystem nicht verzichten kann, aber es kann für einige Organisationen (darunter auch Google) nicht akzeptabel sein. Dies ist natürlich ein großer Leistungsverlust, der für C ++ akzeptabel ist: Denken Sie daran, dass dies eine Sprache ist, die behauptet, dass sie keinen Raum für einen produktiveren Konkurrenten lässt. Die meisten Benutzer scheinen über diesen Leistungsabfall nicht besorgt zu sein: Es gibt andere Hash-Tabellen-Implementierungen für diejenigen, die über die absolute Leistung besorgt sind. Die allgemeine Ineffizienz, die mit der Übergabe von unique_ptr an Wert und anderen Problemen der ABI-Sprache verbunden ist, tritt bei einer sehr geringen Anzahl von Aufgaben in den Vordergrund. Unternehmen, die maximale Produktivität benötigen, können ihren eigenen Weg gehen (und dies tun), indem sie nicht standardmäßige Bibliotheken und nicht standardmäßige Konfigurationstools verwenden. Dies ist natürlich und muss klar verstanden werden.



Eine Änderung des ABI wirkt sich auf eine relativ größere Anzahl von Benutzern aus. Ich vermute, dass ein erheblicher Teil dieser Benutzer nicht ahnt, wie stark ihre Abhängigkeit von ABI ist. Im Ökosystem der Google-Server wird fast alles von der Quelle gesammelt, es gibt nur wenige externe Abhängigkeiten und es gibt eine überdurchschnittliche Möglichkeit, ein umfangreiches Refactoring durchzuführen. Aber selbst für uns kosteten die jüngsten ABI-Änderungen an der Standardbibliothek 5-10 Entwicklungsjahre.

Die Gesamtkosten für die Unterbrechung der ABI-Abwärtskompatibilität für das gesamte C ++ - Ökosystem können im „ Millennium Engineer “ konservativ geschätzt werden: Die Koordination des Wiederaufbaus für jeden Anbieter von Plug-Ins, .so oder DLL in der Welt erfordert enorme Humanressourcen. Zusammen mit der Trennung des Ökosystems aufgrund von C ++ 20-Modulen kann eine Änderung des ABI in der Entwicklungs- und Implementierungszeitleiste von C ++ 23 zu einer harten Trennung des Ökosystems führen.



Es gibt viele Fragen, die mit dieser Diskussion nicht beantwortet werden können. Wie lange können wir bis zu dem Punkt fortfahren, an dem die Änderung des ABI von "nur nützlich" zu einer kritischen Notwendigkeit wird? Wenn wir uns ausdrücklich für die Unterstützung der ABI-Stabilität entscheiden, wie teuer wird die Änderung sein, wenn und wann ein derart kritischer Bedarf entsteht? Wenn Sicherheitsprobleme wie Spectre und Meltdown eine Änderung der Aufrufkonvention erfordern, wie viel kostet C ++, um diesen Meilenstein zu überwinden? Welcher Anteil der Entwickler verwendet C ++, weil wir behaupten, die Leistung über alles zu stellen? Schlimmer noch: Wie lange kann C ++ behaupten, die schnellste Sprache zu sein und muss solche Optimierungen nicht vornehmen?


Wenn wir den ABI bewusst nicht zulassen können oder wollen, muss diese Entscheidung lautstark geäußert werden. Wir müssen klar sagen, dass dies eine Sprache ist, mit der die ABI-Stabilität über den letzten Prozent der Produktivität liegt. Ich bin bereit zu argumentieren, dass dies in der Praxis in den letzten Jahren der Fall war. Wir müssen die Benutzer wissen lassen, was sie von uns erwarten können, und sie müssen wissen lassen, dass Bibliotheken wie Boost, Folly oder Absail die richtige Wahl treffen müssen, wenn Leistung benötigt wird. Dies hilft jedoch nicht bei solchen ABI-bezogenen Einschränkungen in der Sprache selbst wie den Kosten für die Übertragung von unique_ptr. Die Standardbibliothek behält ihre Bedeutung in diesem Entwicklungsmodell: Die Standardbibliothek wird für Kompatibilität und Stabilität verwendet. Dies erfordert möglicherweise eine Änderung des Fokus und der Entwicklungsrichtung: Wir möchten möglicherweise mehr Flexibilität bei sich ändernden Bedingungen und keine „saubere“ Leistung erzielen.


Wenn wir argumentieren, dass Produktivität wichtiger ist als ABI-Stabilität, müssen wir sofort entscheiden, wann genau wir die Abwärtskompatibilität „brechen“ und alles Mögliche tun, damit das Ökosystem solche Änderungen akzeptiert. Und klar und laut erklären, dass wir diesen Weg gehen. Sie müssen verstehen, dass je mehr Zeit zwischen solchen Änderungen vergeht, desto teurer werden sie - denn im Laufe der Zeit wird es immer mehr eine nicht unterstützte Abhängigkeit von ABI geben. Unsere „Implementierer“ haben sehr deutlich gemacht, dass kompatible C ++ 11-Änderungen schmerzhaft und teuer sind. Der Wunsch, die Wiederholung solcher Kosten zu vermeiden, ist natürlich, aber Sie müssen wählen: Entweder wiederholen wir sie nicht, weil wir den ABI nicht ändern, oder wir senken die Kosten.


Im Wesentlichen gibt es drei Möglichkeiten für WG21:

  1. Die Entscheidung, in welcher Version das ABI geändert wird, spielt in C ++ 23 oder C ++ 26 keine Rolle. Warnen Sie Personen und entwickeln Sie sofort Tools und Diagnosen, um Orte zu identifizieren, die kaputt gehen. Konzentriert sich auf konsistentere Praktiken und Tools zur Unterstützung zukünftiger ABI-Änderungen. Es liegt nicht im Interesse eines bestimmten Implementierers, seine Benutzer den Folgen einer Änderung des ABI auszusetzen. Wenn dies bei anderen Implementierungen nicht der Fall ist, sollte die Änderung des ABI eine koordinierte Aktivität zum Nutzen künftiger Benutzer sein. Im Idealfall müssen Sie alles kaputt machen, um zu verdeutlichen, dass im C ++ 23-Modus kompilierter Code nicht mit dem in früheren Modi kompilierten Code kompatibel ist. Wenn jemand auf eine Neuerstellung verzichten kann und andere Fehler im Layout oder zur Laufzeit haben, erhöht dies nur das Missverständnis und die Enttäuschung.
  2. Entscheiden Sie, dass wir uns um ABI-Stabilität bemühen, indem Sie die heutige Praxis formalisieren. Dies ist seit vielen Jahren der Fall, als Standardimplementierer das Recht hatten, gegen ABI-Änderungen ein Veto einzulegen. Wir haben die Abwärtskompatibilität von ABI bereits über die Reinheit und Leistung des Designs gestellt. Wenn wir dies erkennen und den Benutzern klar sagen, wird das Ökosystem besser. Der Wert zusätzlicher Bibliotheken steigt für diejenigen, die die letzten Leistungseinbußen hinnehmen müssen, aber nicht die vom Standard bereitgestellte Stabilität benötigen. Andere leistungsorientierte Sprachen könnten unsere Position in Zukunft in Frage stellen.
  3. Nicht in der Lage sein, eine Richtung zu wählen und den Status Quo zu speichern. Dies ist für mich das Worst-Case-Szenario: Wir achten weiterhin implizit verstärkt auf die Abwärtskompatibilität von ABI. Wir sagen "Leistung" und stimmen für "Binärkompatibilität". Eine solche Dissonanz schadet dem Ökosystem und impliziert eine mangelnde Übereinstimmung über die Prioritäten der Sprache. Ich hoffe aufrichtig, dass wir durch die Bemühungen der Umsetzer und der GD den notwendigen Konsens erreichen.

Ich glaube, dass Option Nr. 1 besser für Benutzer geeignet ist, die maximale Leistung benötigen, aber sie hat unglaubliche Kosten für das Ökosystem und kann in Zukunft zu einer Fragmentierung der Sprache führen. Option 2 ist eine langweilige, verantwortungsbewusste und würdige Wahl: Es ist traurig zuzugeben, dass wir uns in die Ecke des Raums gemalt haben und versuchen, die damit verbundenen Verluste zu minimieren. Die Wahl von Option Nr. 3 bedeutet, nicht zu verwalten, und ich bete, dass dies vermieden wird: Jede explizite Wahl ist besser als die derzeitige Dissonanz und Unfähigkeit, eine Einigung über die Wahl langfristiger Ziele zu erzielen.

Ich verstehe, dass wir unsere gegenwärtige Position durch viele kleine Handlungen scheinbar vernünftiger Untätigkeit erreicht haben. In den letzten 10 Jahren wurde keine einzige Änderung vorgenommen, die eine Verletzung der Binärkompatibilität rechtfertigen könnte, aber die implizite Politik der Aufrechterhaltung der Abwärtskompatibilität ist für das Ökosystem destruktiv geworden. Durch die explizite Übernahme einer solchen Richtlinie eröffnen wir C ++ jedoch eine weitere Möglichkeit, die Bühne schrittweise zu verlassen: Sie können keine systemorientierte Sprache sein, die auf Produktivität ausgerichtet ist, und so viel Platz für eine produktivere Sprache lassen. Theoretisch kann jeder Anbieter entscheiden, ABI in einer zukünftigen Version zu „brechen“, aber die allgemeine Denkrichtung scheint anders zu sein. Ich bin sicher, dass eine Diskussion und ein Konsens zwischen den Implementierern des Standards und der WG21 erforderlich sind: Welche Prioritäten sollte ich wählen?

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


All Articles