Compatibilité binaire: maintenant ou jamais

Traduction de la publication de Titus Winters dans le groupe de travail 21 (WG21) - Comité de normalisation du langage C ++. L'auteur discute d'une question importante: la prise en charge de la compatibilité binaire en amont ou ABI (interface binaire d'application).

Au cours des dernières années au WG21, j'ai activement promu que le progrès est plus important que la compatibilité descendante. Mais je n'y crois plus moi-même, notamment en ce qui concerne le maintien de la compatibilité binaire (ABI). Dans les trois dernières versions (C ++ 14, C ++ 17 et C ++ 20), ABI était aussi stable que possible. Même si WG21 décide de rompre la compatibilité descendante ABI en C ++ 23, nous fournissons la compatibilité binaire sur de nombreuses plateformes depuis plus de 10 ans. À mon avis, la loi d'Hyrum domine dans les modifications à grande échelle des systèmes logiciels. Maintenant, vous ne pouvez pas dire combien d'utilisateurs ont l'hypothèse de la stabilité de la bibliothèque standard ABI (quelle que soit sa sagesse ou son explicite ou implicite) est fermement «cousue dans le sous-cortex», peut-être la moitié des développeurs C ++ dans le monde.


Je garde une liste de ce que WG21 pourrait corriger dans la langue si nous décidons de «casser» l'ABI. Et je ne peux pas affirmer avec certitude que le coût total des retouches, qui impliquera la mise en œuvre de cette liste uniquement, est comparable au coût de la violation de l'ABI dans tout l'écosystème. Nous avons vu de nombreuses petites améliorations dans la cohérence de l'API, la qualité du code de bibliothèque standard, etc., mais sans aucun doute il n'y a pas un seul changement «révolutionnaire» qui justifierait ce coût pour le développeur moyen. Nous pourrions peut-être obtenir de meilleures implémentations de la norme, donner une chance de résoudre les problèmes d'implémentations qui ne sont pas conformes aux spécifications de la norme aujourd'hui. Mais aucune amélioration de ma liste ne vaut clairement le coût.


Plus important encore, en raison des limitations ABI, nous ne pouvons pas éliminer les pertes de performances significatives. Nous ne pouvons pas nous débarrasser du coût important du passage de unique_ptr par valeur [le discours de Chandler sur CppCon 2019 sera publié plus tard], nous ne pouvons pas changer std :: hash ou le placement de la classe en mémoire pour unordered_map sans forcer tout le monde à tout recompiler partout. Les performances des hachages ont été largement étudiées au fil des ans et, compte tenu de l'optimisation des recherches dans le tableau et du hachage proprement dit, nous sommes convaincus que nous pouvons fournir une implémentation unordered_map / std :: hash compatible avec l'API et offrant une amélioration des performances de 200 à 300%. Mais les restrictions ABI ne le permettent pas. Des études supplémentaires sur l'optimisation et le réglage de l'authentification unique pour std :: string suggèrent une augmentation non négligeable des performances (1% dans les repères microbiens et la mise à l'échelle) - l'API n'est pas affectée, mais les restrictions ABI ne le permettent pas.

La perte totale de productivité bloquée exclusivement par ABI atteint plusieurs points de pourcentage - peut-être jusqu'à 5-10%. Ce n'est pas quelque chose dont l'écosystème dans son ensemble ne peut se passer, mais il peut ne pas être acceptable pour certaines organisations (Google parmi elles). Bien sûr, cela représente une perte de performances importante par rapport à ce qui est acceptable pour C ++: rappelez-vous qu'il s'agit d'un langage qui prétend qu'il ne laisse aucune place à un concurrent plus productif. La plupart des utilisateurs ne semblent pas préoccupés par cette dégradation des performances: il existe d'autres implémentations de table de hachage pour ceux qui sont préoccupés par les performances absolues. L'inefficacité générale associée à la transmission de valeur unique_ptr et à d'autres problèmes du langage ABI apparaît au premier plan dans un très petit nombre de tâches. Les organisations qui ont besoin d'une productivité maximale peuvent suivre leur propre chemin (et le faire), en utilisant des bibliothèques non standard et des outils de configuration non standard. Ceci est naturel et doit être clairement compris.



Un changement dans ABI affectera un nombre relativement plus grand d'utilisateurs. Je soupçonne qu'une proportion importante de ces utilisateurs ne soupçonnent pas à quel point leur dépendance à l'ABI est forte. Dans l'écosystème des serveurs de Google, presque tout est collecté à la source, il y a peu de dépendances externes et il y a une opportunité meilleure que la moyenne d'entreprendre un refactoring à grande échelle. Mais même pour nous, les récents changements révolutionnaires de la bibliothèque ABI ont coûté 5 à 10 années d'ingénierie.

Le coût total de la rupture de la compatibilité descendante ABI pour l'ensemble de l'écosystème C ++ peut être estimé de manière prudente dans « Millennium Engineer »: coordonner la reconstruction pour chaque fournisseur de plug-ins, .so ou dll dans le monde nécessitera d'énormes ressources humaines. Avec la séparation de l'écosystème due aux modules C ++ 20, la modification de l'ABI dans le calendrier de développement et de mise en œuvre de C ++ 23 peut conduire à une séparation difficile de l'écosystème.



Il y a beaucoup de questions auxquelles cette discussion ne peut répondre. Combien de temps pouvons-nous continuer au point où le changement de l'ABI de juste utile deviendra une nécessité critique? Si nous choisissons explicitement le support de stabilité ABI, combien coûtera le changement quand et quand un tel besoin critique se présentera? Si des problèmes de sécurité tels que Spectre et Meltdown nécessitent une modification de la convention d'appel, combien coûtera C ++ pour surmonter cette étape? Quelle proportion de développeurs utilise C ++ parce que nous prétendons mettre la performance au-dessus de tout le reste? Pire: combien de temps le C ++ peut-il prétendre être le langage le plus rapide et ne pas avoir à faire de telles optimisations?


Si nous ne pouvons pas consciemment permettre ou ne voulons pas changer l'ABI, alors cette décision doit être exprimée haut et fort. Nous devons clairement dire qu'il s'agit d'un langage qui place la stabilité ABI au-dessus des derniers pour cent de productivité. Je suis prêt à affirmer que, dans la pratique, cela a été le cas ces dernières années. Nous devons faire savoir aux utilisateurs à quoi s'attendre de nous, et leur faire savoir que des bibliothèques comme Boost, Folly ou Absail sont censées faire le bon choix si des performances sont nécessaires. Mais cela n'aide en rien les restrictions liées à ABI dans le langage lui-même, comme le coût de transmission de unique_ptr. La bibliothèque standard conserve son importance dans ce modèle de développement: la bibliothèque standard est ce que nous utilisons pour la compatibilité et la stabilité. Cela peut nécessiter un changement d'orientation et de direction du développement: nous pouvons vouloir concevoir pour plus de flexibilité dans des conditions changeantes, et non pour des performances «propres».


Si nous soutenons que les performances sont plus importantes que la stabilité ABI, nous devons immédiatement décider quand exactement nous allons "casser" la compatibilité descendante et faire tout notre possible pour que l'écosystème accepte de tels changements. Et déclarer clairement et haut et fort que nous allons dans cette direction. Vous devez comprendre que plus le temps s'écoule entre de tels changements, plus ils deviendront coûteux - car au fil du temps, il y aura une dépendance de plus en plus non prise en charge sur ABI. Nos «implémenteurs» ont indiqué très clairement que les modifications de la compatibilité C ++ 11 étaient douloureuses et coûteuses. La volonté d'éviter la répétition de tels coûts est naturelle, mais vous devez choisir: soit nous ne les répétons pas, car nous ne modifions pas l'ABI, soit nous diminuons les coûts.


En substance, il existe trois possibilités pour WG21:

  1. Décider dans quelle version l'ABI sera modifiée n'a pas d'importance en C ++ 23 ou C ++ 26. Avertissez les gens et développez immédiatement des outils et des diagnostics pour aider à identifier les endroits qui se briseront. Se concentre sur des pratiques et des outils plus cohérents pour prendre en charge les futurs changements ABI. Il n'est pas dans l'intérêt d'un implémenteur particulier d'exposer ses utilisateurs aux conséquences de la modification de l'ABI, si d'autres implémentations ne le font pas, la modification de l'ABI devrait être une activité coordonnée au profit des futurs utilisateurs. Idéalement, vous devez tout casser - pour indiquer clairement que le code compilé en mode C ++ 23 est incompatible avec le code compilé dans les modes précédents. Si quelqu'un peut se passer de la reconstruction et que d'autres auront des erreurs dans la mise en page ou au moment de l'exécution, cela ne fera qu'augmenter les malentendus et les déceptions.
  2. Décidez que nous visons la stabilité de l'ABI en formalisant la pratique d'aujourd'hui. Cela a été le cas pendant de nombreuses années lorsque les implémenteurs standard avaient le droit de veto sur les modifications ABI - nous avons déjà placé la compatibilité descendante ABI au-dessus de la pureté et des performances de conception. Si nous reconnaissons cela et disons clairement aux utilisateurs, l'écosystème sera meilleur. La valeur des bibliothèques supplémentaires augmentera pour ceux qui ont besoin de presser les dernières baisses de performances, mais ne nécessitent pas la stabilité fournie par la norme. D'autres langues axées sur les performances pourraient remettre en question notre position à l'avenir.
  3. Ne pas pouvoir choisir une direction et sauver le statu quo. C'est le pire des cas pour moi: nous continuons implicitement d'accorder plus d'attention à la compatibilité descendante ABI. Nous disons «performance» et votons «compatibilité binaire». Une telle dissonance nuit à l'écosystème et implique un manque d'accord sur les priorités linguistiques. J'espère sincèrement que grâce aux efforts des exécutants et de la DG, nous parviendrons au consensus nécessaire.

Je pense que l'option n ° 1 convient mieux aux utilisateurs qui ont besoin de performances maximales, mais elle a un coût incroyable pour l'écosystème et peut conduire à une fragmentation de la langue à l'avenir. L'option numéro 2 est un choix ennuyeux, responsable et digne: il est triste d'admettre que nous nous sommes peints dans le coin de la pièce et essayons de minimiser les pertes qui y sont associées. Choisir l'option n ° 3 signifie ne pas gérer, et je prie pour que cela soit évité: tout choix explicite vaut mieux que la dissonance et l'incapacité actuelles de parvenir à un accord sur le choix des objectifs à long terme.

Je comprends que nous avons atteint notre position actuelle grâce à de nombreux petits actes d'inaction apparemment raisonnable. Au cours des 10 dernières années, aucun changement n'a été apporté qui pourrait justifier une violation de la compatibilité binaire, mais la politique implicite de maintien de la compatibilité descendante est devenue destructrice pour l'écosystème. Cependant, en adoptant explicitement une telle politique, nous ouvrirons une autre possibilité pour C ++ de quitter progressivement la scène: vous ne pouvez pas être un langage orienté système et axé sur les performances, laissant autant de place à un langage plus productif. En théorie, chaque fournisseur peut décider de «casser» ABI dans toute version future, mais l'orientation générale de la pensée semble différente. Je suis sûr que la discussion et le consensus entre les responsables de la mise en œuvre de la norme et le WG21 sont nécessaires: quelles priorités dois-je choisir?

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


All Articles