In der Compilertheorie bezeichnet die Entfernung toten Codes ( auch Dead-Code - Eliminierung , Dead-Code-Stripping oder Dead-Code-Strip genannt ) eine Compileroptimierung , die toten Code (Code, der keinen Einfluss auf das Programmergebnis hat) entfernt . Das Entfernen solchen Codes bietet mehrere Vorteile: Es reduziert die Programmgröße (in manchen Kontexten ein wichtiger Faktor), verringert den Ressourcenverbrauch, beispielsweise die Anzahl der zu übertragenden Bytes [ 1 ] , und ermöglicht es dem laufenden Programm, irrelevante Operationen zu vermeiden , was die Laufzeit verkürzt . Zudem kann es durch die Vereinfachung der Programmstruktur weitere Optimierungen ermöglichen. Toter Code umfasst Code, der niemals ausgeführt werden kann ( unerreichbarer Code ), und Code, der lediglich tote Variablen beeinflusst (in die geschrieben, aber nie wieder gelesen wird), also für das Programm irrelevant ist.
Beispiele
Betrachten Sie das folgende in C geschriebene Beispiel .
int foo ( void ) { int a = 24 ; int b = 25 ; // Zuweisung an tote Variable int c ; c = a * 4 ; return c ; b = 24 ; // Nicht erreichbarer Code return 0 ; }Eine einfache Analyse der Verwendung der Werte zeigt, dass der Wert bnach der ersten Zuweisung innerhalb von nicht verwendet wird foo. Da bdie Variable innerhalb von als lokale Variable deklariert ist foo, kann ihr Wert außerhalb von nicht verwendet werden foo. Somit bist die Variable überflüssig , und ein Optimierer kann ihren Speicherplatz freigeben und ihre Initialisierung eliminieren.
Da die erste return-Anweisung bedingungslos ausgeführt wird und keine nachfolgende Marke existiert, die mit einem "goto" erreicht werden könnte, ist kein möglicher Ausführungspfad zur zweiten Zuweisung an vorhanden b. Daher ist die Zuweisung unerreichbar und kann entfernt werden. Hätte die Prozedur einen komplexeren Kontrollfluss , beispielsweise eine Marke nach der return-Anweisung und ein "goto" gotoan anderer Stelle in der Prozedur, so könnte ein möglicher Ausführungspfad zur Zuweisung an existieren b.
Obwohl innerhalb der Funktion Berechnungen durchgeführt werden, werden deren Ergebnisse nicht an Stellen gespeichert, auf die außerhalb des Funktionsbereichs zugegriffen werden kann. Da die Funktion zudem einen statischen Wert (96) zurückgibt, kann dieser auf den zurückgegebenen Wert vereinfacht werden (diese Vereinfachung wird als Konstantenfaltung bezeichnet ).
Die meisten modernen Compiler bieten Optionen zur Aktivierung der Dead-Code-Eliminierung, teilweise auf verschiedenen Ebenen. Eine niedrigere Ebene entfernt beispielsweise nur nicht ausführbare Anweisungen. Eine höhere Ebene reserviert möglicherweise auch keinen Speicherplatz für ungenutzte Variablen. Eine noch höhere Ebene identifiziert und entfernt Anweisungen oder Funktionen, die keinen Zweck erfüllen.
Die Eliminierung von totem Code wird häufig als Alternative zur optionalen Codeeinbindung mittels eines Präprozessors eingesetzt . Betrachten Sie den folgenden Code.
// DEBUG_MODE auf false setzen constexpr bool DEBUG_MODE = false ;int main ( void ) { int a = 5 ; int b = 6 ; int c ; c = a * ( b / 2 ); if ( DEBUG_MODE ) { printf ( "%d \n " , c ); } return c ; }Da die Konstante aufgrund ihrer Definition immer den Wert „ falschDEBUG_MODE “ ergibt , kann der Code innerhalb der if-Anweisung niemals ausgeführt werden, und die Entfernung von totem Code würde ihn vollständig aus dem optimierten Programm entfernen. Diese Technik ist beim Debuggen üblich , um optional Codeblöcke zu aktivieren; die Verwendung eines Optimierers mit Totcode-Eliminierung macht den Einsatz eines Präprozessors für dieselbe Aufgabe überflüssig.
In der Praxis entsteht ein Großteil des vom Optimierer gefundenen toten Codes durch andere Transformationen innerhalb des Optimierers. Beispielsweise fügen die klassischen Verfahren zur Reduzierung der Operatorstärke neue Berechnungen in den Code ein und machen die älteren, aufwändigeren Berechnungen überflüssig. [ 2 ] Die anschließende Eliminierung des toten Codes entfernt diese Berechnungen und vervollständigt den Effekt (ohne den Algorithmus zur Stärkereduzierung zu verkomplizieren).
Historisch gesehen erfolgte die Eliminierung von totem Code mithilfe von Informationen aus der Datenflussanalyse . [ 3 ] Ein auf der statischen Einzelzuweisungsform (SSA) basierender Algorithmus findet sich im Original-Zeitschriftenartikel zur SSA -Form von Ron Cytron et al. [ 4 ] Robert Shillingsburg (auch bekannt als Shillner) verbesserte den Algorithmus und entwickelte einen Begleitalgorithmus zur Entfernung überflüssiger Kontrollflussoperationen. [ 5 ]
Dynamische Dead-Code-Eliminierung
Toter Code wird im Allgemeinen als bedingungslos tot betrachtet. Daher ist es sinnvoll, toten Code durch Dead-Code-Eliminierung zur Kompilierzeit zu entfernen .
In der Praxis ist es jedoch üblich, dass Codeabschnitte nur unter bestimmten Bedingungen toten oder unerreichbaren Code darstellen , die zum Zeitpunkt der Kompilierung oder Assemblierung möglicherweise nicht bekannt sind. Solche Bedingungen können durch unterschiedliche Laufzeitumgebungen bedingt sein (z. B. verschiedene Versionen eines Betriebssystems oder unterschiedliche Mengen und Kombinationen von Treibern oder Diensten, die in einer bestimmten Zielumgebung geladen werden). Dies kann unterschiedliche Sonderfälle im Code erfordern, während der Code in anderen Fällen bedingt tot sein kann. [ 6 ] [ 7 ] Darüber hinaus kann die Software (z. B. ein Treiber oder ein residenter Dienst) so konfiguriert werden, dass bestimmte Funktionen je nach Benutzerpräferenzen ein- oder ausgeschlossen werden, wodurch ungenutzte Codeabschnitte in einem bestimmten Szenario nutzlos werden. [ 6 ] [ 7 ] Obwohl modulare Software so entwickelt werden kann, dass Bibliotheken dynamisch nur bei Bedarf geladen werden, ist es in den meisten Fällen nicht möglich, nur die relevanten Routinen aus einer bestimmten Bibliothek zu laden. Selbst wenn dies unterstützt würde, kann eine Routine immer noch Codeabschnitte enthalten, die in einem bestimmten Szenario als toter Code gelten, aber bereits zur Kompilierzeit nicht ausgeschlossen werden konnten.
Die Techniken, die verwendet werden, um den Bedarf dynamisch zu erkennen, Abhängigkeiten zu identifizieren und aufzulösen, solchen bedingt toten Code zu entfernen und den verbleibenden Code beim Laden oder zur Laufzeit neu zu kombinieren, werden als dynamische Totcode-Eliminierung [ 8 ] [ 9 ] [ 10 ] oder dynamische Totbefehls-Eliminierung [ 11 ] bezeichnet .
Most programming languages, compilers and operating systems offer no or little more support than dynamic loading of libraries and late linking, therefore software utilizing dynamic dead-code elimination is very rare in conjunction with languages compiled ahead-of-time or written in assembly language.[12][13][14] However, language implementations doing just-in-time compilation may dynamically optimize for dead-code elimination.[10][15][16]
Although with a rather different focus, similar approaches are sometimes also utilized for dynamic software updating and hot patching.
See also
- Redundant code
- Simplification (symbolic computation)
- Partial-redundancy elimination
- Conjunction elimination
- Dynamic software updating
- Dynamic coupling (computing)
- Self-relocation
- Software cruft
- Tree shaking
- Post-pass optimization
- Profile-guided optimization
- Superoptimizer
- Function multi-versioning
References
- ^Malavolta, Ivano et al. “JavaScript Dead Code Identification, Elimination, and Empirical Assessment.” IEEE transactions on software engineering 49.7 (2023): 3692–3714. Web.
- ^Allen, Frances; Cocke, John; Kennedy, Ken (June 1981). "Reduction of Operator Strength". In Jones, Neil D.; Muchnick, Steven Stanley (eds.). Program Flow Analysis: Theory & Application. Prentice-Hall. ISBN 0-13729681-9.
- ^Kennedy, Ken (June 1981). "A Survey of Data-flow Analysis Techniques". In Jones, Neil D.; Muchnick, Steven Stanley (eds.). Program Flow Analysis: Theory & Application. Prentice-Hall. ISBN 0-13729681-9.
- ^Cytron, Ron K.; Ferrante, Jeanne; Rosen, Barry K.; Zadeck, F. Kenneth (1991). Efficiently Computing Static Single Assignment Form and the Program Dependence Graph. ACM TOPLAS 13(4).
- ^Cooper, Keith D.; Torczon, Linda (2003) [2002-01-01]. Engineering a Compiler. Morgan Kaufmann. pp. 498ff. ISBN 978-1-55860698-2.
- ^ a b Paul, Matthias R. (2002-04-03) [2001-06-18]. "[fd-dev] Ctrl+Alt+Del" . freedos-dev . Abgerufen am 09.09.2017 . […] Jede der […] Optionen kann bei der Installation dauerhaft ausgeschlossen werden (wodurch dank unserer
dynamischen Entfernung von totem Code
auch Speicherplatz für die entsprechenden Codeabschnitte gespart wird
) oder später jederzeit über API-Funktionen deaktiviert oder aktiviert werden, falls ein Neustart des Rechners verhindert werden soll. […] Wir erwägen, weitere synchrone Cache-Flush-Aufrufe hinzuzufügen. […] Dank unserer Methode zur dynamischen Entfernung von totem Code würde dies in einer bestimmten Zielkonfiguration keine unnötige Speicherbelegung verursachen, da ein bestimmter Cache-Flush-Aufruf nur dann in das FreeKEYB-Laufzeit-Image aufgenommen wird, wenn der entsprechende Festplatten-Cache ebenfalls geladen ist oder FreeKEYB über Befehlszeilenoptionen angewiesen wurde, die entsprechende Unterstützung zu laden.
{{cite web}}CS1-Wartung: Veralteter Archivierungsdienst ( Link ) - ^ a b Paul, Matthias R. (06.04.2002). "[fd-dev] Ctrl+Alt+Del" . freedos-dev . Abgerufen am 27.04.2019 .
[…] FreeKEYB erstellt das Laufzeit-Image des Treibers zur Initialisierungszeit abhängig vom Rechnertyp, der verwendeten Tastatur, dem Tastaturlayout, dem Land und der Codepage, der installierten Maus und Grafikkarte(n), den anderen auf dem System geladenen Treibern, dem Betriebssystem und den verwendeten Lade- und Verschiebungsmethoden, den enthaltenen Funktionen und den in der Befehlszeile angegebenen Konfigurationsoptionen. Aufgrund der Vielzahl unterstützter Befehlszeilenparameter und -optionen […] (etwa fünfzig Parameter […] mit mehreren möglichen Einstellungen) gibt es eine hohe Anzahl an Funktionskombinationen mit unzähligen Abhängigkeiten […] was zu einer […] endlosen Anzahl von […] unterschiedlichen Ziel-Images führt. Die dynamische Dead-Code-Eliminierungstechnik von FreeKEYB löst diese Abhängigkeiten auf und entfernt toten Code und Daten. Sie ist nicht darauf beschränkt, wie in der klassischen TSR-Programmierung eine begrenzte Anzahl von Modulen oder ganzen Unterprogrammen ein- oder auszuschließen und Dispatch-Tabellen zu korrigieren, sondern arbeitet auf Byte-Ebene und kann einzelne Anweisungen inmitten größerer Routinen entfernen, die über den gesamten Code verteilt sind, um einen bestimmten Fall zu behandeln oder eine bestimmte Funktion zu unterstützen. Spezielle Tools analysieren den Code und erstellen Korrekturtabellen. Die automatisierte Verwendung bedingter Definitionen deklariert die verschiedenen Fälle nicht nur optional zur Assemblierungszeit, sondern auch zur Initialisierungszeit. Dadurch entsteht kein Overhead durch toten Code im Laufzeit-Image. Alle Abhängigkeiten zwischen diesen Bedingungen werden verfolgt, das Laufzeit-Image wird dynamisch erstellt und verschoben, alle Referenzen zwischen diesen kleinen, sich ändernden Binärteilen werden korrigiert, und das kompakte .COM/.SYS-Modell kann weiterhin verwendet werden. Die API zum Importieren und Exportieren von Objektstrukturen zwischen FreeKEYB und der aufrufenden Anwendung wird zur Initialisierungszeit ausgeführt. Sie können intern transparent in ihrer Größe angepasst und verschoben werden […] zur Laufzeit […]
{{cite web}}CS1-Wartung: Veralteter Archivierungsdienst ( Link ) - ^ Thammanur, Sathyanarayan (31.01.2001). Ein Framework zur Just-in-Time-Registerzuweisung und Codeoptimierung für eingebettete Systeme (Masterarbeit). Universität von Cincinnati , Ingenieurwesen: Computertechnik. ucin982089462.[1] Archiviert am 28.07.2019 in der Wayback Machine [2] Archiviert am 28.07.2019 in der Wayback Machine
- ^ Kubice, Jan (2024-10-17). "Dynamische Eliminierung von totem Code: Optimierung für Flexibilität" .
- ^ a b Conway, Andrew (04.12.1995). „Zyklische Datenstrukturen“ . Newsgroup : comp.lang.functional . Abgerufen am 03.07.2017 .
[…]
Lazy Evaluation
ist im Grunde
die dynamische Eliminierung von totem Code
. […]
{{cite newsgroup}}CS1-Wartung: Veralteter Archivierungsdienst ( Link )(Anmerkung: Möglicherweise die erste öffentliche Verwendung des Begriffs „dynamische Dead-Code-Eliminierung“ , allerdings nur konzeptionell und mit Fokus auf verzögerte Auswertung in funktionalen Sprachen .) - ^ Butts, J. Adam; Sohi, Guri (Oktober 2002). „Dynamische Erkennung und Eliminierung toter Anweisungen“ (PDF) . San Jose, CA, USA: Computer Science Department, University of Wisconsin-Madison . ASPLOS X ACM 1-58113-574-2/02/0010 . Abgerufen am 23. Juni 2017 .
{{cite web}}CS1-Wartung: Veralteter Archivierungsdienst ( Link ) - ^ Paul, Matthias R.; Frinke, Axel C. (1997-10-13) [Erstveröffentlichung 1991], FreeKEYB - Erweiterter DOS-Tastatur- und Konsolentreiber (Benutzerhandbuch) (Version 6.5)[3] (Anmerkung: FreeKEYB ist ein Unicode -basierter, dynamisch konfigurierbarer Nachfolger von K3PLUS, der die meisten Tastaturlayouts , Codepages und Ländercodes unterstützt . Der Treiber nutzt einen Standard- Makroassembler sowie ein Framework mit automatischen Vor- und Nachbearbeitungs-Analysewerkzeugen, um Abhängigkeits- und Code-Morphing -Metadaten zu generieren, die zusammen mit dem Binärcode in die ausführbare Datei eingebettet werden. Ein selbstverwerfender, relaxierender und verschiebender Loader implementiert dynamische Dead-Code-Eliminierungs- und Verschiebungstechniken auf Byte-Ebene zur Ladezeit sowie selbstmodifizierenden Code und Rekonfigurierbarkeit zur Laufzeit , um den Speicherbedarf zu minimieren und sich je nach zugrunde liegender Hardware, Betriebssystem- und Treiberkonfiguration sowie dem ausgewählten Funktionsumfang und Gebietsschema der kanonischen Form anzunähern (etwa sechzig Konfigurationsschalter mit Hunderten von Optionen für eine nahezu unbegrenzte Anzahl möglicher Kombinationen). Diese Komplexität und Dynamik bleiben für Benutzer verborgen, die wie bei einem herkömmlichen Treiber mit einer einzigen ausführbaren Datei arbeiten. K3PLUS war ein erweiterter Tastaturtreiber für DOS, der zu seiner Zeit in Deutschland weit verbreitet war und für einige andere europäische Sprachen angepasst werden konnte. Er unterstützte bereits einen Teil der Funktionen, implementierte aber keine dynamische Totcode-Eliminierung.
- ^ Paul, Matthias R.; Frinke, Axel C. (2006-01-16), FreeKEYB - Erweiterter internationaler DOS-Tastatur- und Konsolentreiber (Benutzerhandbuch) (v7 vorläufige Ausgabe)
- ^ Paul, Matthias R. (10.04.2001). „[ANN] FreeDOS Beta 6 veröffentlicht“ (auf Deutsch). Newsgruppe : de.comp.os.msdos . Abgerufen am 02.07.2017 .
[…] brandneue[s] Feature, der
dynamischen Dead-Code-Elimination
, die jeweils notwendigen Bestandteile des Treibers erst zum Installationszeitpunkt zusammenbastelt und reloziert, so dass keine ungenutzten Code- oder Datenbereiche mehr resident bleiben (z. B. wenn jemand ein bestimmtes FreeKEYB-Feature nicht benötigt). […]
{{cite newsgroup}}CS1-Wartung: Veralteter Archivierungsdienst ( Link )(Anmerkung: Dies ist die erste bekannte Implementierung einer dynamischen, bytegenauen Entfernung von totem Code für Software, die im Voraus assembliert oder kompiliert wurde .) - ^ Johng, Yessong; Danielsson, Per; Ehnsiö, Per; Hermansson, Mats; Jolanki, Mika; Moore, Scott; Strander, Lars; Wettergren, Lars (08.11.2002). „Kapitel 5. Java-Übersicht und iSeries-Implementierung – 5.1.1. Verschiedene Komponenten“. Intentia Movex Java auf dem IBM iSeries Server – Ein Implementierungsleitfaden – Übersicht über Movex Java auf dem iSeries Server – Installation und Konfiguration von Movex Java auf iSeries – Tipps und Techniken für den Betrieb (PDF) . Red Books. IBM Corp. S. 41. ISBN 0-73842461-7SG24-6545-00. Archiviert (PDF) vom Original am 08.10.2013 . Abgerufen am 20.04.2019 .[4]
- ^ Polito, Guillermo (2015). „Virtualisierungsunterstützung für Laufzeitspezialisierung und -erweiterung von Anwendungen – Programmiersprachen“ (PDF) . Université des Sciences et Technologies de Lille . S. 111–124 . HAL-ID: tel-01251173. Archiviert (PDF) vom Original am 23.06.2017 . Abgerufen am 23.06.2017 .
Weiterführende Literatur
- Bodík, Rastislav; Gupta, Rajiv (Juni 1997). „Partielle Eliminierung von totem Code mittels Slicing-Transformationen“. Proceedings der ACM SIGPLAN 1997 Konferenz über Programmiersprachenentwurf und -implementierung (PLDI '97) : 682–694 .
- Aho, Alfred Vaino ; Sethi, Ravi ; Ullman, Jeffrey David (1986). Compiler – Prinzipien, Techniken und Werkzeuge . Addison Wesley Publishing Company . ISBN 0-201-10194-7Die
- Muchnick, Steven Stanley (1997). Fortgeschrittener Compilerbau und -implementierung . Morgan Kaufmann Publishers . ISBN 1-55860-320-4Die
- Grüne, Dick ; Bal, Henri Elle ; Jacobs, Ceriel JH; Langendoen, Koen G. (2000). Modernes Compiler-Design . John Wiley & Sons, Inc. ISBN 0-471-97697-0Die
- Kennedy, Ken ; Allen, Randy (2002). „Kapitel 4.4. Datenflussanalyse – Kapitel 4.4.2. Eliminierung von totem Code“. Optimierung von Compilern für moderne Architekturen: Ein abhängigkeitsbasierter Ansatz (Digitaldruck der 1. Auflage, 2011). Academic Press / Morgan Kaufmann Publishers / Elsevier . S. 137 , 145–147 , 167. ISBN 978-1-55860-286-1. LCCN 2001092381 .
- Muth, Robert; Debray, Saumya K.; Watterson, Scott; De Bosschere, Koen (Januar 2001) [1999-11-02]. „alto: ein Link-Time-Optimierer für den Compaq Alpha“. Software: Practice and Experience . 31 (1): 67–101 . CiteSeerX 10.1.1.33.4933 . doi : 10.1002/1097-024X(200101)31:1<67::AID-SPE357>3.0.CO;2-A . S2CID 442062 .[5]