Optimierung des Programmcodes. Hauptmerkmale der Codeoptimierung durch den Programmierer und Compiler

Manchmal kann es schwierig sein zu entscheiden, welches Konstrukt besser ist, i++ oder ++i zu verwenden, oder zwischen if-else und switch zu wählen. Dieser Artikel, der speziell für die iT-Works-Community geschrieben wurde, stellt die realsten Code-Optimierungstools vor, die jeder professionelle Programmierer kennen sollte.

Einige Leute denken, dass die Zeiten der Optimierung auf Codeebene für immer vorbei sind, aber das stimmt nicht. Nun gibt es viele Plattformen, auf denen es keine so mächtigen Compiler gibt wie in Microsoft Visual Studio. Beispielsweise Shader-Sprachen (hlsl, glsl) oder Code für CUDA, PlayStation3, SPU bzw mobile Plattformen. Abhängig von der Organisation des Codes kann seine Effizienz um das Zehnfache variieren, manchmal aufgrund von Compiler-Ineffizienz, häufiger jedoch aufgrund von Speicherzugriffen.

Wenn Sie für verschiedene Plattformen programmieren, studieren Sie die Fähigkeiten Ihres Compilers und die Merkmale der Prozessorarchitektur (wenn Sie für eine bestimmte Konsole schreiben). Führen Sie Leistungstests verschiedener Optimierungsoptionen durch. Es ist oft schwierig zu erraten, welche Methoden am effektivsten sind. Und dieser Artikel wird Ihnen verschiedene Tricks zeigen, die Ihnen helfen können. Sie sollten jedoch nicht blind optimieren, ohne vorherige Analyse und Profilerstellung. Denken Sie daran, dass vorzeitige Optimierung böse ist.

Wenn Sie ein Programmierer in VS unter Windows sind, wird der Compiler höchstwahrscheinlich viele der beschriebenen Optimierungstechniken effektiv bewältigen. Achten Sie auf die Punkte der Arbeit mit dem Gedächtnis, und ich empfehle Ihnen auch, sich mit der Technik vertraut zu machen datenorientiertes Design. Suchen Sie nach einigen Tipps zur Verwendung in dem Artikel.

Fangen wir also an:

1. Verwenden Sie Anweisungen zur Datenvektorisierung und Vektorverarbeitung (z. B. SSE in der CPU oder packen Sie Daten, wenn Sie Shader oder CUDA verwenden). Dies ermöglicht die Verwendung der SIMD-Architektur (Single Instruction, Multiple Data), die die Berechnungsgeschwindigkeit erheblich erhöht. Wenn Sie sich für diese Methode entscheiden, vergessen Sie nicht die Datenausrichtung im Speicher.

2. Es ist effizienter, in einem Mix zu addieren und zu multiplizieren, als erst alles zu addieren und dann alles zu multiplizieren. Dies liegt daran, dass Addition und Multiplikation von unterschiedlichen Prozessormodulen durchgeführt werden und gleichzeitig durchgeführt werden können.
int a,b,c,k,m,n,t,f1,f2,f3,g1,g2,g3; a = b + c; k = m + n; t = a + k; f1 = f2 * f3; g1 = g2 * g3; Weniger effizient als: a = b + c; f1 = f2 * f3; k = m + n; g1 = g2 * g3; t = a + k;

3. Es gibt keinen Geschwindigkeitsunterschied beim Arbeiten mit Float und Double beim Addieren und Multiplizieren. Sie werden in derselben Anzahl von Prozessorzyklen ausgeführt und verwenden dieselben Register. Beim Teilen und Wurzelziehen ist Float schneller. Wenn Sie jedoch große Datenmengen verwenden, kann es aufgrund des Caches zu einer Typisierung kommen weniger Speicher(d. h. Float), daher ist es im Allgemeinen vorzuziehen, es zu verwenden. Die Wahl von Double ist sinnvoll, wenn mehr Präzision erforderlich ist.

4.
Lass uns essen. konstanter Float a = 100,0f; float some1 = some3 * 1.0f/a; float some2 = some4 * 1.0f/a; effizienter ist es nicht zu schreiben: const float a_inv = 1.0f / a; some1 = some3 * a_inv; some2 = some4 * a_inv; und so: some1 = some3 * (1.0f / a); some2 = some4 * (1.0f/a); Warum sollte es effizienter sein? Operatoren mit gleichem Vorrang werden nacheinander ausgeführt. Das bedeutet, dass zuerst die Multiplikation und dann die Division durchgeführt wird. Wenn Sie die Divisionsoperation in Klammern einrahmen, führt der Compiler sie aus, und in Echtzeit wird nur die Multiplikationsoperation ausgeführt. Was die Unterschiede zwischen Option 3 und Option 2 betrifft, so wird bei der 3. Option keine zusätzliche Variable erstellt, es muss nicht darüber nachgedacht werden, was diese Variable ist, wenn man sich den Code ansieht. Und die Wirksamkeit der 2. und 3. Option wird gleich sein.

5. Float ist bei großen Datenmengen und Berechnungen damit rentabler als Double (wegen Cache Misses, siehe Punkt 3).

6.
a, b - beliebiger Ausdruck Func1, Func2 - Funktionen, die aufgerufen werden, um die Bedingung zu berechnen if(a && b) - Sie müssen die erste weniger wahrscheinliche Bedingung setzen, für mehr Effizienz if(a || b) - Sie müssen Stellen Sie zuerst die wahrscheinlichste Bedingung ein, um effizienter zu werden, wenn (Func1() && Func2()) - Sie müssen den schnelleren Operator zuerst setzen

7.
void Func(int* a) ( int b = 10; Die folgenden Zeilen sind gleich effizient (hinsichtlich der Ausführungszeit): b = 100; *a = 100; ) Dies geschieht, weil der Stapelzeiger auf die Stapelvariable zugreift. Es gibt auch eine Pointer-Dereferenzierung.

8. Wenn es eine große Anordnung von Strukturen gibt, müssen Sie die Größe ihrer Elemente gleich der Zweierpotenz machen. Dann wird der Durchgang durch ein solches Array aufgrund der Ausrichtung des Zeigers auf jede Struktur im Array viel schneller (4-6 mal).

9.
int a[ 1000 ]; for(int i =0; i<1000; ++i) a[ i ] = 50; Значительно эффективнее будет: int* p = a; for(int i =0; i<1000; ++i, ++p) *p = 50;

10.
SomeClass*p; - Zeiger auf Array von Elementen x = *(p++); - viel effizienter x = *(++p); Aus dem gleichen Grund wie Punkt 1. Im ersten Fall wird der Zeiger parallel dereferenziert und inkrementiert, im zweiten Fall sequentiell.

11. Die Anzahl der Spalten eines zweidimensionalen Arrays sollte vorzugsweise gleich einer Zweierpotenz sein. Dies erhöht die Arbeitsgeschwindigkeit mit dem Array. Dadurch werden Zeiger auf die ersten Elemente jeder Zeile ausgerichtet, wodurch der Elementzugriff beschleunigt wird.
int mas[ 10 ][ 16 - die Anzahl der Spalten sollte vorzugsweise eine Zweierpotenz sein]

12.
u32a; f32b; b = (f32)(i32)a; - schneller b = (f32)a;

13. Vermeiden Sie Type Casting.
Schwimmer f; int ein; Float b = (float)a; - lang int m = (int)f; - sehr lang

14. Verwenden Sie Rundungsoperationen mit Bedacht:
nur für unsigned: (u32)x sind 10x mal schneller als "u32(floor(x))" u32(x + 1.0f) sind 10x mal schneller als "u32(cell(x))" u32(x + 0.5f) sind 10x mal schneller als "u32(round(x))"
15.
Schwimmer f = 1,0f; *(int*)&f ^= 0x80000000; - schneller als f *= -1.0f;

16. Wenn sequentielle Werte von case-Parametern in switch verwendet werden (case 0: case 1: case 2:...), dann ist switch viel effizienter als if-else. Dies liegt daran, dass bei if-else der Wert jeder Bedingung berechnet wird und bei solchen Parametern im switch-Konstrukt der Wert einmal berechnet wird und dann sofort auf den gewünschten übergegangen wird Artikel.

17. Verzweigung ist böse. Versuchen Sie, ihre Anzahl zu reduzieren. Machen Sie sie nicht in großen Schleifen. Schalter ist auch ein Zweig. Der Prozessor versucht, das Ergebnis der Bedingung vorherzusagen (Verzweigungsvorhersage), und wenn der Wert des Ausdrucks fast immer gleich ist, hat die Verzweigung keinen Einfluss auf die Geschwindigkeit der Codeausführung. Im Allgemeinen ist die Verzweigungsvorhersage jedoch in 50 % der Fälle falsch, was den Algorithmus verlangsamt. Jede Verzweigung ist ein Übergang zu einer Folge von Prozessorbefehlen. Ein solcher Übergang unterbricht die Befehlspipeline des Prozessors und ist ziemlich teuer.

Dies gilt insbesondere für Shader, SPU-Subroutinen, CUDA-Subroutinen und in Algorithmen, in denen eine große Datenmenge verarbeitet wird. Wenn Sie Code für hunderttausend Partikel ausführen müssen, versuchen Sie, die Anzahl der Verzweigungen zu minimieren. Dies kann die Codeausführung erheblich beschleunigen.

Konstante int NN = 12500000; konstant int N = 10; Folgendes ist schlecht (200 ms auf meiner Maschine): for(int i = 0; i< NN; ++i) { switch(i % N) { case 0: res += 10; break; case 3: res += 30; break; case 5: res += 50; break; case 6: res += 60; break; case 8: res += 80; break; } } гораздо лучше (120 ms на моей машине): const int arr = { 10, 0, 0, 30, 0, 50, 60, 0, 80, 0 }; for(int i = 0; i < NN; ++i) res += arr[ i % N ];

18. Betrachten Sie ein Beispiel. Ein 2D-Sprite enthält ein Array von Vertex[ 4 ]. Es wäre viel effizienter, nur einen Scheitelpunkt zu speichern und im Sprite den Offset-Index relativ zum ersten Element.
Dadurch werden 16 Bytes für jedes Sprite in Bezug auf Speicher eingespart, und in Bezug auf die Geschwindigkeit wird es 30 Prozent schneller sein, die Scheitelpunkte zu passieren. Das ist datenorientiertes Design. Dasselbe gilt für C#.

Schwerpunkte der Optimierung:
1. Reduzierung der Anzahl der Filialen
2. Gruppieren von Daten nach gleichen Typen im Speicher (in C# hat noch niemand Arrays von Strukturen gelöscht)
3. Reduzierung der Größe von Strukturen

19.Inline-Funktionen:
+ gibt Geschwindigkeitsgewinn
- erhöht den Code
- Fügt beim Kompilieren Abhängigkeiten (*.h-Dateien) zum Code hinzu. Dies erhöht die Kompilierungszeit und das Volumen, wenn Code in einer Funktion geändert wird

Daten:
1. Der Compiler darf die Funktion nicht inlinen (sogar _forceinlie - es gibt keine Inlining-Garantie)
2. Wenn die Geschwindigkeitsoptimierung aktiviert ist, fügt der VS-Compiler alle Funktionen nach eigenem Ermessen ein, auch wenn sie nicht als inline deklariert sind.

Fazit: Sie sollten die Verwendung von Inline-Funktionen vermeiden. Jetzt ist dies nicht notwendig. Eine Ausnahme kann nur sehr häufig ausgeführter Low-Level-Code sein (z. B. mathematische Funktionen) oder wenn Sie ein Programm mit einem Compiler ohne vollständige Codeoptimierung schreiben (z. B. ist die Verwendung von Inline für den PlayStation3-Compiler immer noch relevant).

20. Betrachten Sie das Ergebnis der Änderung der Reihenfolge der Variablen in der Struktur.
struct s1 ( short int a; double b; int d; ) sizeof(s1[ 10 ]) == 24 * 10 struct s2 ( double b; int d; short int a; ) sizeof(s1[ 10 ]) == 16 * 10 doppelt mal 8 wird immer ausgerichtet

21. Durch Umstellen der Stellen der Terme für den Float-Wert ändert sich die Summe:
1e+8f + 1,23456 - 1e+8f == 0, aber 1e+8f - 1e+8f + 1,23456 == 1,23456

22. Die binäre Suche sollte nicht für eine kleine Anzahl von Elementen verwendet werden. Wenn die Anzahl der Elemente weniger als 40-60 beträgt (diese Anzahl kann von der Implementierung der Algorithmen abweichen, liegt aber in etwa in dieser Größenordnung), ist die binäre Suche langsamer als die lineare.

23.
Es ist so möglich: bool b; int a = b ? x:y; Aber schneller: int b; (0 - falsch, -1 - wahr) int a = (x & b) | (y & ~b);

24.
int a, b; 1. int x = (a >= b ? 1: 0); 2. int x = (a >= b ? -1: 0); Kann ersetzt werden durch: 1. int x = (b - a) >> 31; 2. int x = (b - a) & 0x80000000;

25.
i32 iIndex; Bedingung: if(iIndex< 0 && iIndex >= iSize) Kann ersetzt werden durch: if((u32)iIndex >= iSize) Bedingung: if(i >= min && i<= max) Можно заменить таким: if((u32)(i-min) <= (u32)max - min)

26. Oben war ein Beispiel dafür, wie switch in ein statisches konstantes Array umgewandelt werden kann und auf das per Index zugegriffen werden kann. Dies gilt beispielsweise für rtti (Runtime Type Identification). Wenn der Funktionszeigerschalter auf diese Weise definiert ist, kann es äußerst nützlich sein, ihn durch einen zeitkonstanten Zugriff auf die gewünschte Funktion zu ersetzen. Dasselbe gilt, wenn es sich um eine Zustandsmaschine handelt. Anstatt dem Schalter ein neues Element hinzuzufügen, kann es dem obigen Array hinzugefügt werden. Aber denken Sie an Punkt 16.

int func(int index) ( switch(index) ( case 0: return f_Func1(); case 3: return f_Func2(); case 4: return f_Func2(); .. case .. return f_FuncN(): ) return 0; ) ersetzen durch: int func(int index) ( static funcPtr array = ( &f_Func1, NULL, &f_Func2, ... &f_FuncN ) return array[ index ](); )

Zusätzlich

Weitere Tipps zum Schreiben von effizienterem Code finden Sie in den Artikeln:

Ein wenig über das Traurige: Unser ganzes Leben ist ein Kampf mit Bremsen. Und so kann es nicht ewig weitergehen. Alles muss optimiert werden – vom Arbeitsplatz bis zur Zeit. In diesem Artikel habe ich Beispiele für die Codeoptimierung in der Programmiersprache Delphi gegeben, aber glauben Sie mir, diese Tipps können Ihnen im wirklichen Leben nützlich sein, wenn Sie darüber nachdenken.

1. Fast alles lässt sich optimieren. Und selbst wo es Ihnen scheint, dass alles schnell geht, können Sie es noch schneller machen. Es muss daran erinnert werden, dass jedes Problem auf verschiedene Arten gelöst werden kann und Ihre Aufgabe darin besteht, die rationalste davon auszuwählen.

2. Optimierung sollte immer an Schwachstellen im Programmcode ansetzen. Normalerweise muss etwas, das so schnell funktioniert, nicht optimiert werden. Und der Effekt einer solchen Optimierung wird minimal sein.

3. Bei der Optimierung müssen Sie alle Operationen und jeden Bediener analysieren, ohne etwas zu verpassen. Normalerweise beginnt die Optimierung an den Stellen im Code, an denen sich regelmäßig wiederholende Operationen, Zyklen, befinden. Was sich innerhalb der Schleife befindet, wird n-mal wiederholt. Je weniger Code sich also in der Schleife befindet, desto schneller berechnet der Prozessor ihn. Stellt sich heraus, dass der Kreislauf zu groß ist, kann er in mehrere kleinere zerlegt werden. In diesem Fall wird die Größe unseres Programms zunehmen, aber die Geschwindigkeit wird zunehmen.

4. Versuchen Sie, weniger Fließkommaberechnungen zu verwenden. Alle Operationen mit ganzen Zahlen werden um eine Größenordnung schneller ausgeführt. Auch Multiplikations- oder Divisionsoperationen dauern lange. Anstelle der Multiplikation ist es besser, die Addition zu verwenden, und die Division kann durch eine Verschiebung ersetzt werden. Shift ist viel schneller als Multiplikation und Division. Dies liegt daran, dass alle Zahlen binär gespeichert werden. Wenn Sie eine Zahl von Dezimal in Binär umwandeln und die Zahl um eine Stelle nach rechts verschieben, werden Sie feststellen, dass diese Operation der Division durch 2 ähnelt. Beim Verschieben nach links wird die Zahl durch 2 geteilt. Obwohl diese Operationen sind ähnlich, die Verschiebung arbeitet um ein Vielfaches schneller.

5. Belasten Sie Prozeduren beim Erstellen nicht mit einer großen Anzahl von Eingabeparametern. Und das alles, weil bei jedem Aufruf der Prozedur ihre Parameter in einen speziellen Bereich des Speichers, den Stack, hochgehoben und nach dem Beenden von dort entfernt werden. Es ist auch notwendig, sorgfältig und mit den Parametern selbst zu handeln. Es ist nicht nötig, den Prozeduren die Variablen zuzusenden, die die Daten des großen Umfangs in der reinen Form enthalten. Es ist besser, die Adresse der Speicherzelle zu übergeben, in der die Daten gespeichert sind, und innerhalb der Prozedur bereits mit dieser Adresse zu arbeiten.

6. In den kritischsten Momenten des Programms, z. B. bei der Ausgabe auf dem Bildschirm, können Sie die Assembler-Sprache verwenden. Sogar der eingebaute Assembler von Delphi ist viel schneller als Funktionen in der Muttersprache. Der Assembler-Code kann in ein separates Modul ausgelagert, kompiliert und mit Ihrem Programm verbunden werden.

7. Es gibt keine unnötigen Kontrollen. Denken Sie nicht, dass es auch für den Benutzer nicht auftreten wird, wenn Sie keine nicht standardmäßige Situation haben. Bestätigen Sie immer, was der Benutzer eingibt, ohne darauf zu warten, dass die Eingabe erforderlich ist.

8. Wenn Sie ein ziemlich großes und umständliches Programm schreiben, fügen Sie Kommentare hinzu. Der Compiler ignoriert sie weiterhin. Und wenn Sie plötzlich die Quellcodes Ihrer Programme verkaufen möchten, erhöhen Kommentare ihren Preis, und Sie können sich leichter selbst darin bewegen.

9. Um einen guten Effekt zu erzielen, müssen Sie die IDE, die integrierte Entwicklerumgebung, die Sprache, in der Sie programmieren, in unserem Fall Delphi, kennen. Normalerweise können Sie mit IDE-Optionen verschiedene Arten von Compilern auswählen, und die Standardeinstellung ist die einfachste und schnellste Kompilierung, die jedoch weniger optimierten Code erstellt. Setzen Sie deshalb immer den am besten optimierenden Typ des Compilers ein.

10. Versuchen Sie, Programme mit einer Standardschnittstelle auszustatten. Nun, Sie müssen keine dreieckigen Schaltflächen, nicht standardmäßigen Menüs und anderen grafischen Schnickschnack erstellen. All dies verlangsamt das Programm erheblich, verbraucht eine große Menge an Computerressourcen und erfordert zusätzliche Entwicklungszeit. Zum Beispiel ist echtes UNIX im Allgemeinen eine normale Shell – eine Zeile zum Eingeben von Befehlen.

Das ist wie alles. Ich wünsche Ihnen viel Glück beim Schreiben Ihrer Programme, befolgen Sie einfach diese Tipps und Sie werden erfolgreich sein.

Und die Effizienz verbessern. Zu den Optimierungszielen gehören die Reduzierung der Codemenge, der vom Programm verwendeten RAM-Menge, die Beschleunigung des Programms und die Reduzierung der Anzahl der E/A-Operationen.

Die Hauptanforderung, die normalerweise an das Optimierungsverfahren gestellt wird, besteht darin, dass das optimierte Programm das gleiche Ergebnis und die gleichen Nebenwirkungen auf den gleichen Satz von Eingabedaten haben muss wie das nicht optimierte Programm. Diese Anforderung spielt jedoch möglicherweise keine besondere Rolle, wenn der Gewinn aus der Verwendung der Optimierung als wichtiger angesehen werden kann als die Folgen einer Änderung des Verhaltens des Programms.

Arten der Optimierung

Die Codeoptimierung kann sowohl manuell, durch einen Programmierer als auch automatisch durchgeführt werden. Im letzteren Fall kann der Optimierer entweder ein separates Softwaretool sein oder in den Compiler eingebaut sein (der sogenannte Optimierungscompiler). Darüber hinaus sollte beachtet werden, dass moderne Prozessoren die Reihenfolge optimieren können, in der Codeanweisungen ausgeführt werden.

Es gibt Konzepte wie High-Level- und Low-Level-Optimierung. Optimierungen auf hoher Ebene werden meistens von einem Programmierer durchgeführt, der, indem er mit abstrakten Einheiten (Funktionen, Prozeduren, Klassen usw.) arbeitet und sich ein allgemeines Modell zur Lösung eines Problems vorstellt, das Design des Systems optimieren kann. Optimierungen auf der Ebene elementarer Strukturblöcke des Quellcodes (Schleifen, Verzweigungen etc.) werden üblicherweise auch als High Level bezeichnet; manche heben sie als separate („mittlere“) Ebene hervor (N. Wirth?). Die Low-Level-Optimierung wird in der Phase durchgeführt, in der der Quellcode in eine Reihe von Maschinenanweisungen umgewandelt wird, und häufig unterliegt diese Phase der Automatisierung. Assembler-Programmierer glauben jedoch, dass keine Maschine einen guten Programmierer in dieser Hinsicht übertreffen kann (wobei sich alle einig sind, dass ein schlechter Programmierer Maschinen noch schlechter macht).

Auswahl des zu optimierenden Bereichs

Beim manuellen Optimieren von Code gibt es ein weiteres Problem: Sie müssen nicht nur wissen, wie man optimiert, sondern auch, wo man ihn anwendet. Normalerweise nehmen aufgrund verschiedener Faktoren (langsame Eingabeoperationen, unterschiedliche Geschwindigkeit von Mensch und Maschine usw.) nur 10 % des Codes bis zu 90 % der Ausführungszeit in Anspruch (natürlich ist die Aussage eher spekulativ, und hat eine zweifelhafte Grundlage in Form eines Gesetzes-Pareto, sieht jedoch recht überzeugend aus bei E. Tanenbaum). Da zusätzliche Zeit für die Optimierung aufgewendet werden muss, wäre es daher besser, anstatt zu versuchen, das gesamte Programm zu optimieren, diese „kritischen“ 10 % der Ausführungszeit zu optimieren. Ein solches Stück Code wird als Engpass oder Engpass bezeichnet, und um es zu bestimmen, werden spezielle Programme verwendet - Profiler, mit denen Sie die Zeit verschiedener Teile des Programms messen können.

Tatsächlich wird die Optimierung in der Praxis oft nach der "chaotischen" Programmierphase durchgeführt (mit Dingen wie "", "das finden wir später heraus", "das machen wir sowieso"), also ist es eine Mischung aus richtig Optimierung, Refactoring und Fixing: Vereinfachung "fancy" Konstrukte wie strlen(path.c_str()), boolesche Bedingungen (a.x != 0 && a.x != 0), etc. Profiler sind für solche Optimierungen kaum geeignet. Um solche Stellen zu erkennen, können Sie jedoch Programme verwenden - Tools zum Auffinden semantischer Fehler, die auf einer gründlichen Analyse des Quellcodes basieren - schließlich kann, wie Sie am zweiten Beispiel sehen, ineffizienter Code das Ergebnis von Fehlern sein (wie z Tippfehler in diesem Beispiel - höchstwahrscheinlich a.x != 0 && a.y != 0). Ein guter erkennt einen solchen Code und zeigt eine Warnmeldung an.

Schaden und Nutzen von Optimierungen

Fast alles in der Programmierung sollte rational behandelt werden, und Optimierungen sind keine Ausnahme. Es wird angenommen, dass ein unerfahrener Assembler-Programmierer normalerweise Code schreibt, der 3-5 Mal langsamer ist als vom Compiler generierter Code (Zubkov). Es gibt einen bekannten Ausdruck über frühe Optimierungen auf niedriger Ebene (wie der Kampf um einen zusätzlichen Operator oder eine Variable), der von Knuth formuliert wurde: "Vorzeitige Optimierung ist die Wurzel aller Probleme."

Die meisten Leute haben keine Beschwerden über die vom Optimierer durchgeführten Optimierungen, und manchmal sind einige Optimierungen praktisch Standard und obligatorisch - zum Beispiel die Tail-Rekursionsoptimierung in funktionalen Sprachen (Tail-Rekursion ist eine bestimmte Art von Rekursion, die auf die reduziert werden kann Form eines Zyklus).

Es sollte jedoch verstanden werden, dass zahlreiche komplexe Optimierungen auf Maschinencodeebene den Kompilierungsprozess stark verlangsamen können. Darüber hinaus kann der Gewinn aus ihnen im Vergleich zu Optimierungen des Gesamtdesigns des Systems (Wirth) äußerst gering sein. Außerdem sollte man nicht vergessen, dass moderne, syntaktisch und semantisch „ausgefallene“ Sprachen viele Feinheiten haben und ein Programmierer, der sie nicht berücksichtigt, von den Folgen der Optimierung überrascht sein kann.

Betrachten Sie zum Beispiel die Sprache C++ und die sog. Rückgabewertoptimierung, deren Kern darin besteht, dass der Compiler keine Kopien des temporären Objekts erstellen darf, das von der Funktion zurückgegeben wird. Da der Compiler in diesem Fall das Kopieren „überspringt“, wird dieser Trick auch „Copy Elision“ genannt. Also folgender Code:

#enthalten struct C ( C() () C(const C&) ( std::cout<< "A copy was made.\n"; } }; C f() { return C(); } int main() { std::cout << "Hello World!\n"; C obj = f(); }

kann mehrere Ausgabeoptionen haben:

Hallo Welt! Es wurde eine Kopie angefertigt. Es wurde eine Kopie angefertigt. Hallo Welt! Es wurde eine Kopie angefertigt. Hallo Welt!

Ironischerweise sind alle drei Optionen zulässig, da der Sprachstandard es erlaubt, in diesem Fall auf einen Kopierkonstruktoraufruf zu verzichten, selbst wenn der Konstruktor Nebenwirkungen hat (§12.8 Kopieren von Klassenobjekten, Klausel 15).

Ergebnis

Vergessen Sie daher nicht, den Code zu optimieren, wenn möglich mit speziellen Softwaretools, aber dies sollte sorgfältig und mit Vorsicht erfolgen und sich manchmal auf Überraschungen des Compilers einstellen.

PVS-Studio

Bibliographisches Verzeichnis

  • E. Tanenbaum. Rechnerarchitektur.
  • Wirth N. Erstellen von Compilern.
  • Knut D. Die Kunst des Programmierens, Band 1. Grundlegende Algorithmen.
  • Zubkov S.V. Assembler für DOS, Windows und UNIX.
  • Wikipedia. Code-Optimierung.
  • Wikipedia.

Bei der anfänglichen Entwicklung der Website achten deren Eigentümer vor allem auf die Außenwahrnehmung und den schnellen Launch. Unmittelbar oder einige Monate nach dem Start stellt sich die Frage, wie man mehr Kunden gewinnen kann. Nach einiger Zeit arbeiten Layouter und Programmierer an der internen Optimierung der Seite, wobei sich herausstellt, dass ein Teil des geschriebenen Codes neu geschrieben werden muss. Daher werden wir in diesem Beitrag über die Optimierung des HTML-, CSS- und JS-Codes der Website während ihrer anfänglichen Entwicklung sprechen, wodurch der Kunde Geld sparen und die Entwickler auf die Nerven gehen können.

js- und CSS-Optimierung

Beginnen wir mit CSS und JS. Wozu dient die CSS- und JS-Optimierung?

Etwa 50 % der Benutzer verlassen die Website, wenn das Laden länger als 3 Sekunden dauert, und mit jeder weiteren Sekunde sinkt die Conversion der Website um 7 %. Auch die Ladegeschwindigkeit der Website ist einer der Ranking-Faktoren.

Das erste, was Sie anfangen müssen, ist, den Empfehlungen von Google zu folgen. Css- und js-Code sollten nicht im HTML-Code der Website enthalten sein, sondern in separaten Dateien abgelegt werden. Die Ausnahme sind kleine Inline-Stile mit 1-2 Werten. Die Anzahl der eingebundenen Dateien sollte so weit wie möglich reduziert werden, sodass idealerweise jeweils eine eingebundene css- und js-Datei übrig bleibt. Die Verbindung von js-Dateien sollte an das Ende der Seite verschoben werden (bevor die Seite angezeigt wird, muss der Browser sie parsen, und wenn er ein externes Skript erkennt, muss er es laden, und dies ist ein zusätzlicher Vorgangszyklus, der die Seitenanzeige.

Um das Laden von js-, CSS-Dateien und Bildern zu beschleunigen, ist es außerdem wünschenswert, Caching und Komprimierung im GZIP-Format zu verwenden.

Website-SEO-Layout: HTML-Code-Optimierung oder wie man es macht, damit man es später nicht wiederholen muss

Für die richtige zukünftige Optimierung des HTML-Codes schauen wir uns alle Tags an und wie sie sich auf SEO auswirken.

Block :

- gibt den Namen der Seite an, die auf der Registerkarte des Browsers und in Suchmaschinen platziert wird. Das wichtigste Tag, um das Ranking der Website zu beeinflussen.</p> <p><description>- ermöglicht es Ihnen, eine Beschreibung der Seite festzulegen, die in den Suchergebnissen unter dem Titel angezeigt wird. Hat einen viel geringeren Einfluss auf Rankings, hilft aber, die CTR (Click-Through-to-Impression-Ratio) der Seite zu erhöhen. Wenn das Meta-Description-Tag ausgefüllt ist, garantiert dies nicht, dass die Ergebnisse genau das zeigen, was dort geschrieben steht, da Suchmaschinen die Beschreibung aus dem Inhalt entnehmen können. Trotzdem ist es besser, die Tag-Generierung einzurichten und nicht darüber nachzudenken, welcher Teil des PS-Textes zur Beschreibung verwendet wird.</p> <p><keywords>- zeigt Suchmaschinen an, für welche Suchanfragen die relevante Seite angezeigt wird. Nach der Einführung dieses Tags wurde ihm ein großer Einfluss auf das Ranking von Seiten gegeben. Optimierer könnten problemlos eine Seite mit einem beliebigen Produkt eines Online-Shops bewerben, z. B. bei der Aufforderung „Laden Sie eine Zusammenfassung der Geschichte herunter“ oder bei anderen Themen, die Besucher auf die Website brachten, aber keine Kunden. Nun ist der Einfluss dieses Tags auf die Werbung nicht genau bekannt, und viele Leute ignorieren ihn einfach, auch um der Seite keinen Schaden zuzufügen.</p> <p><meta name="robots" content="index/noindex, follow/nofollow">(einer der Werte wird genommen, index oder noindex, follow oder nofollow) – ein Verbot der Indexierung der Seite (noindex) und ein Verbot der Indexierung ausgehender Links auf der Seite (nofollow) durch Suchmaschinen. Die Index- und Follow-Werte werden in Verbindung mit den No-Indexing-Werten verwendet, da die Seiten- und Link-Indexierung standardmäßig erlaubt ist. Sie sollten dieses Tag sorgfältig verwenden, um nicht nach einer Weile null Traffic von Suchmaschinen zu sehen.</p> <p><link rel="canonical" href="..." />- ermöglicht es Ihnen, mehrere inhaltlich identische Seiten, jedoch mit unterschiedlichen URLs, auf eine Seite zu verlinken, um deren Ranking zu verbessern. In den meisten Fällen wird es für dynamische Seiten verwendet, die denselben Inhalt enthalten, z. B. das Sortieren von Seiten in einem Produktkatalog oder bei der Arbeit mit einem Blog, wo sich ein Artikel in verschiedenen Abschnitten befinden und unterschiedliche URLs haben kann.</p> <p><link rel="prev" href="..." />Und <link rel="next" href="..."/>- Mit Tags können Sie die vorherigen und nächsten Seiten für Suchmaschinen auf Paginierungsseiten angeben, wenn das Material in mehrere Teile unterteilt ist und sich auf verschiedenen URLs befindet.</p> <h3>Block <body> :</h3> <p><h1> - <h6>- Überschriften auf der Seite. Schild <h1>sollte einmal verwendet werden, wie <title>es gibt den Hauptinhalt der Seite an, hat aber weniger Einfluss auf das Ranking in den SERPs. In der Regel für Online-Shops im Tag <h1>Die Namen dieser Kategorien und Produkte sind auf den Seiten der Kategorien und Produkte angegeben, bei Informationsseiten der Name, der den Leser interessiert, plus, wenn möglich, Schlüsselwörter.</p> <p>Stichworte <h1> - <h6>müssen einer logischen Struktur folgen. Header <h1>Kopfzeilen enthalten <h2>, in der die Überschriften <h3>usw. Es ist ratsam, sie nur im Textinhalt der Seite zu verwenden (z. B. um den Hauptinhalt der Seite zu unterbrechen, aber nicht für Blöcke, die auf allen Seiten der Website angezeigt werden). In Anbetracht dessen, dass das Tag <h1>hilft, den Wert von Wörtern im Ranking zu erhöhen, schließe den gesamten Text auf der Website darin ein und fixiere ihn mit Hilfe von Stilen, damit er gelesen werden kann, dann bringt dies keinen Vorteil, sondern schadet einer solchen Seite nur.</p> <p><strong>, <b>, <em>- entwickelt, um sich auf bestimmte Sätze und Wörter in der Beschreibung einer Seite, eines Artikels, einer Nachricht usw. zu konzentrieren. (einschließlich der Erhöhung der Bedeutung dieser Wörter beim Ranking). Sie sollten sie nicht für das Layout von Seitenelementen verwenden, die sich beispielsweise auf allen Produkten wiederholen. Dafür ist es besser, CSS zu verwenden. Obwohl nicht sicher bekannt ist, ob ein Wort oder eine Phrase, die auf allen Seiten der Website wiederholt wird, eine Wirkung hat, beispielsweise innerhalb eines Tags <strong>, aber es ist besser, Tags für ihren beabsichtigten Zweck zu verwenden. Ich denke, PS wird es zu schätzen wissen.</p> <p><table>- auch primär für die Platzierung im Textinhalt der Seite gedacht. Dadurch können Sie den Text interessanter zum Lesen machen, was die Glaubwürdigkeit der gesamten Seite von Suchmaschinen erhöht (Listen, Bilder, Videos haben die gleiche Wirkung).</p> <p><ul>, <li>, <ol>, <dl>, <dd>, <dt>- Listen, die zum Erstellen des Site-Menüs und im Hauptteil auf der Seite zum Strukturieren von Textinformationen verwendet werden.</p> <p><img>- Bilder auf der Seite. Die Bildbeschreibung sollte in den Attributen alt="..." und title="..." platziert werden, was beim Ranking in der Bildersuche hilft. Außerdem wird die Position des Bildes in den Suchergebnissen beeinflusst, wenn der Name der Bilddatei mit seiner Beschreibung übereinstimmt.</p> <p><noindex>- gibt Yandex den Inhalt des Dokuments an, der nicht indiziert werden muss, z. B. Serviceinformationen. Es muss sehr vorsichtig und in seltenen Fällen verwendet werden.</p> <p><div>- Das eigentliche Tag für das Website-Layout hat keinen Einfluss auf SEO.</p> <p>Ein Tag zum Umbrechen von Text, aber nicht zum Ändern der Platzierung von Blöcken. Dies dient jedoch eher der Gültigkeit des Layouts und nicht der Optimierung. Hat keinen Einfluss auf die Website-Optimierung.</p> <p><p>Gibt einen Textabsatz für den Hauptinhalt der Website an (z. B. Artikel- oder Produktbeschreibungen, Kategorien in einem Online-Shop). Es ist auch wünschenswert, sich hauptsächlich auf den Hauptinhalt einer einzelnen Seite zu beziehen.</p> <p>Ein Inline-Element, das keinen Einfluss auf SEO hat. In vielen Fällen nützlich, um zusammen mit CSS in Inhalten außerhalb der Hauptseite verwendet zu werden, um Hervorhebungs- und Überschriften-Tags zu ersetzen.</p> <p><header>- Website-Header.</p> <p><footer>Website-Fußzeile.</p> <p><a>- hier brauchen wir einen eigenen Artikel. Und nicht allein.</p> <p>Vielleicht habe ich ein Tag übersehen ... aber das bedeutet, dass es weniger wichtig ist. Außerdem wurden einige der neuen html5-Tags nicht berücksichtigt, wie z <article> , <aside> , <nav> , <section> .</p> <p>Wenn Sie HTML-Tags so anordnen, wie sie die Relevanz von Schlüsselwörtern beeinflussen, dann kommt das ungefähr so ​​heraus: Titel, h1-h6,stark, Beschreibung, b, em, p, Schlüsselwörter, ul->li & ol->li.</p> <p>Lassen Sie uns nun für eine bessere Präsentation versuchen, ein richtig optimiertes Seitenlayout zu erstellen.</p><p> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Seitentitel

  • Kategorie 1
  • Kategorie 2
    • Kategorie 2.1
    • Kategorie 2.2
  • Kategorie 3

Seitentitel

Hauptinhalt mit Tags

-

, , , ,
, .

Seitenblock mit Zusatzinformationen.
...


Was Sie sonst noch beim SEO-Layout der Seite beachten müssen

  • Eine große Anzahl von Validierungsfehlern kann sich negativ auf eine Seite auswirken. Es ist nicht ratsam, leere Tags und css-, js-Dateien zu verwenden, die nicht auf der Seite verwendet werden. Je leichter der Code, desto einfacher ist es für Suchmaschinen, ihn zu analysieren.
  • Sie sollten Flash und Frames nicht verwenden, da diese nicht sehr suchmaschinenfreundlich sind. Außerdem erkennen Suchmaschinen keinen Text, der mit einem Bild gezeichnet wurde.
  • Die Cross-Browser-Natur der Website wirkt sich auf das Verhalten der Benutzer aus und führt dazu, dass sie die Website verlassen, ohne die erforderlichen Informationen zu erhalten oder einen Kauf zu tätigen. Dadurch verschlechtern sich Verhaltensfaktoren, die die Optimierung der gesamten Seite beeinflussen.
  • Das Vorhandensein einer mobilen Version der Website oder ihre Anpassbarkeit ist zu einem Rankingfaktor geworden und ermöglicht es Ihnen, wie die Cross-Browser-Kompatibilität, die Absprungrate zu reduzieren und die Conversion der Website auf mobilen Geräten zu erhöhen. Google begann 2015, das Vorhandensein einer mobilen Version (für Mobilgeräte optimiert) und Yandex im Jahr 2016 zu berücksichtigen und nannte den Ranking-Algorithmus "Wladiwostok".
  • Der Hauptinhalt der Seite sollte im HTML-Code näher am Anfang platziert werden, damit er aus Sicht der Suchmaschine relevanter ist.
  • Inhalte sollten nicht mit display:none ausgeblendet werden.
  • Wenn der Einsatz von Tags die Wichtigkeit eines Keywords erhöhen kann, dann kann es zum Beispiel auch einen negativen Effekt geben, wenn sich einige Tags überschneiden
    1. h1-h6 & stark, b, em
    2. h1-h6 & a href=…
    3. stark, b, em & a href=…

Abschluss

Wenn Sie sich die Seiten von Suchmaschinen ansehen, können Sie eine Reihe von Fehlern sehen, die mit dem Layout der Website zusammenhängen, einschließlich Validierungsfehlern. Aber hier sollte verstanden werden, dass sie sich ganz andere Ziele setzen. Ein SEO-optimiertes Layout ist für Websites erforderlich, deren Hauptverkehrsquellen Suchmaschinen sind, und egal wie coole Links auf die Website verweisen, Sie können ohne gute Code-Optimierung nicht von ersten Positionen träumen.

Code-Optimierung ist eine Modifikation von Programmen, die von einem optimierenden Compiler oder Interpreter durchgeführt wird, um ihre Eigenschaften wie Leistung oder Kompaktheit zu verbessern, ohne die Funktionalität zu ändern.

Die letzten drei Wörter in dieser Definition sind sehr wichtig: Unabhängig davon, wie sehr die Optimierung die Eigenschaften des Programms verbessert, muss sie unbedingt die ursprüngliche Bedeutung des Programms unter allen Bedingungen bewahren. Deshalb gibt es beispielsweise in GCC verschiedene Optimierungsstufen
Gehen wir weiter: Es gibt Optimierungen maschinenunabhängig (hohes Level) Und maschinenabhängig (niedriges Niveau). Die Bedeutung der Klassifizierung ist aus den Namen ersichtlich, bei maschinenabhängigen Optimierungen werden Merkmale bestimmter Architekturen verwendet, bei High-Level-Optimierungen erfolgt die Optimierung auf der Ebene der Codestruktur.

Optimierungen können je nach Umfang ihrer Anwendung auch in lokale (Operator, Folge von Operatoren, Basisblock), intraprozedurale, interprozedurale, intramodulare und globale (Optimierung des gesamten Programms, „Optimierung während der Montage“) eingeteilt werden. , „Link-Time-Optimierung“).

Debuggen eines Moduls, um logische Fehler zu identifizieren

Debuggen PS ist eine Aktivität, die darauf abzielt, Fehler im PS unter Verwendung der Prozesse zur Ausführung seiner Programme zu erkennen und zu korrigieren. Testen PS ist der Prozess der Ausführung seiner Programme auf einem bestimmten Datensatz, für den das Ergebnis der Anwendung im Voraus bekannt ist oder die Regeln für das Verhalten dieser Programme bekannt sind. Der angegebene Datensatz wird aufgerufen prüfen oder einfach prüfen. Somit kann das Debugging als wiederholte Wiederholung von drei Prozessen dargestellt werden: Testen, wodurch das Vorliegen eines Fehlers in der PS festgestellt werden kann, Suchen einer Fehlerstelle in den Programmen und Dokumentationen der PS, und Editieren von Programmen und Dokumentationen, um den festgestellten Fehler zu beseitigen. Mit anderen Worten:

Debuggen = Testen + Fehler finden + Bearbeiten.

In der ausländischen Literatur wird Debugging oft nur als Prozess des Auffindens und Behebens von Fehlern (ohne Testen) verstanden, dessen Vorhandensein während des Testens festgestellt wird. Manchmal werden Testen und Debuggen synonym betrachtet. In unserem Land beinhaltet das Debugging-Konzept normalerweise Tests, also werden wir der etablierten Tradition folgen. Die gemeinsame Betrachtung dieser Prozesse in dieser Vorlesung macht diese Diskrepanz jedoch nicht so bedeutsam. Es sollte jedoch beachtet werden, dass Tests auch im Rahmen des PS-Zertifizierungsprozesses verwendet werden.



Prinzipien und Arten des Software-Debugging

Der Erfolg des PS-Debugging wird weitgehend durch die rationale Organisation des Testens vorbestimmt. Beim Debuggen des PS werden hauptsächlich solche Fehler gefunden und beseitigt, deren Vorhandensein im PS beim Testen festgestellt wird. Wie bereits erwähnt, kann das Testen nicht die Korrektheit des PS beweisen, sondern bestenfalls das Vorhandensein eines Fehlers darin nachweisen. Mit anderen Worten, es kann nicht garantiert werden, dass durch das Testen der Software mit einem praktisch durchführbaren Satz von Tests das Vorhandensein aller in der Software vorhandenen Fehler festgestellt werden kann. Daher treten zwei Probleme auf. Die erste Aufgabe besteht darin, eine solche Reihe von Tests vorzubereiten und PS darauf anzuwenden, um so viele Fehler wie möglich darin zu erkennen. Je länger jedoch der Testprozess (und das Debuggen im Allgemeinen) andauert, desto höher werden die Kosten der Software. Daher die zweite Aufgabe: Den Zeitpunkt zu bestimmen, an dem das Debuggen des PS (oder seiner einzelnen Komponenten) abgeschlossen ist. Ein Zeichen für das mögliche Ende des Debuggens ist die Vollständigkeit der Abdeckung durch die Tests, die durch das PS gelaufen sind (d. h. die Tests, auf die das PS angewendet wird), von vielen verschiedenen Situationen, die während der Ausführung von PS-Programmen auftreten, und der relativ seltene Manifestation von Fehlern im PS im letzten Abschnitt des Testprozesses. Letzteres bestimmt sich nach dem geforderten Zuverlässigkeitsgrad des PS, der in der Spezifikation seiner Qualität angegeben ist.

Um die Testsuite zu optimieren, d.h. Um eine solche Reihe von Tests vorzubereiten, die es ermöglichen würden, für eine bestimmte Anzahl von ihnen (oder für ein bestimmtes Zeitintervall, das zum Testen vorgesehen ist), eine größere Anzahl von Fehlern im PS zu erkennen, ist es notwendig, zunächst zu planen dies im Voraus festzulegen und zweitens eine rationale Strategieplanung (Gestaltung) von Tests zu verwenden. Das Testdesign kann unmittelbar nach Abschluss der Phase der externen Beschreibung des PS beginnen. Zur Entwicklung einer Testdesignstrategie gibt es unterschiedliche Ansätze, die sich bedingt grafisch zwischen den folgenden beiden extremen Ansätzen einordnen lassen. Der linke extreme Ansatz besteht darin, dass Tests nur auf der Grundlage des Studiums der PS-Spezifikationen (externe Beschreibung, Architekturbeschreibung und Modulspezifikation) entworfen werden. Die Struktur der Module wird in keiner Weise berücksichtigt, d.h. Sie werden als Black Boxes behandelt. Tatsächlich erfordert dieser Ansatz eine vollständige Aufzählung aller Eingabedatensätze, da ansonsten einige Abschnitte der PS-Programme möglicherweise nicht funktionieren, wenn irgendein Test übersprungen wird, was bedeutet, dass die darin enthaltenen Fehler nicht erscheinen werden. Das Testen des PS mit einem vollständigen Satz von Eingabedatensätzen ist jedoch praktisch unmöglich. Der rechte extreme Ansatz besteht darin, dass Tests auf der Grundlage des Studiums von Programmtexten entwickelt werden, um alle Arten zu testen, auf die jedes PS-Programm ausgeführt wird. Berücksichtigt man das Vorhandensein von Zyklen mit variabler Wiederholungszahl in Programmen, dann kann es auch eine extrem große Anzahl unterschiedlicher Möglichkeiten geben, PS-Programme auszuführen, so dass auch deren Test praktisch unmöglich sein wird.

Unit-Tests

Jedes komplexe Softwaresystem besteht aus separaten Teilen – Modulen, die als Teil des Systems eine bestimmte Funktion ausführen. Um den korrekten Betrieb des Systems als Ganzes zu überprüfen, müssen Sie zuerst jedes Modul des Systems einzeln testen. Bei Problemen können so die verursachenden Module leichter identifiziert und die entsprechenden Fehler behoben werden. Dieses individuelle Testen von Modulen wird als Unit-Test bezeichnet ( Unit-Tests).

Für jedes zu testende Modul wird eine Testumgebung entwickelt, die einen Treiber und Stubs enthält, Testanforderungen und Testpläne werden vorbereitet, die spezifische Testfälle beschreiben.

Der Hauptzweck von Unit-Tests besteht darin, zu überprüfen, ob jedes einzelne Modul des Systems die Anforderungen erfüllt, bevor es in das System integriert wird.

Gleichzeitig werden beim Unit-Testen vier Hauptaufgaben gelöst.

1. Auffinden und Dokumentieren von Abweichungen- Dies ist eine klassische Testaufgabe, die nicht nur die Entwicklung einer Testumgebung und von Testfällen umfasst, sondern auch die Ausführung von Tests, die Protokollierung der Ausführungsergebnisse und das Melden von Problemen.

2. Unterstützung für die Entwicklung und Überarbeitung von Low-Level-Systemarchitekturen und Kommunikation zwischen Modulen- Diese Aufgabe ist eher charakteristisch für "leichte" Methoden wie XP, wo das Prinzip des Testens vor der Entwicklung (testgetriebene Entwicklung) angewendet wird, bei dem die Hauptanforderungsquelle für ein Softwaremodul ein vor dem Modul selbst geschriebener Test ist. Aber auch mit dem klassischen Testschema können Unit-Tests Probleme im Systemdesign und unlogische oder verwirrende Mechanismen für die Arbeit mit einem Modul aufdecken.

3. Unterstützung für das Refactoring von Modulen- Diese Aufgabe bezieht sich auf die Unterstützung des Prozesses der Systemänderung. Nicht selten ist während der Entwicklung ein Refactoring von Modulen oder deren Gruppen erforderlich – eine Optimierung oder komplette Neugestaltung des Programmcodes, um dessen Wartbarkeit, Geschwindigkeit oder Zuverlässigkeit zu erhöhen. Unit-Tests sind jedoch ein leistungsfähiges Werkzeug, um zu überprüfen, ob die neue Version des Programmcodes genauso funktioniert wie die alte.

4. Unterstützen Sie die Fehlerbehebung und das Debugging- Diese Aufgabe ist mit Feedback verbunden, das Entwickler von Testern in Form von Problemberichten erhalten. Detaillierte Problemberichte, die während der Unit-Testphase erstellt werden, ermöglichen es, viele Fehler in einem Softwaresystem in den frühen Phasen seiner Entwicklung oder der Entwicklung seiner neuen Funktionalität zu lokalisieren und zu beseitigen.

Aufgrund der Tatsache, dass die zu testenden Module in der Regel klein sind, gilt Unit Testing als die einfachste (wenn auch ziemlich zeitaufwändige) Phase des Systemtests. Trotz seiner scheinbaren Einfachheit gibt es jedoch zwei Probleme mit Unit-Tests.

1. Es gibt keine einheitlichen Grundsätze dafür, was genau ein eigenständiges Modul ist.

2. Unterschiede in der Auslegung des Begriffs Unit-Tests an sich – sei es das separate Testen eines Moduls, dessen Betrieb nur durch die Testumgebung unterstützt wird, oder ob es darum geht, die Korrektheit des Moduls als Teil zu überprüfen eines bereits entwickelten Systems. In letzter Zeit wird der Begriff „Unit Testing“ häufiger im zweiten Sinn verwendet, obwohl wir in diesem Fall eher von Integrationstests sprechen.



Wird geladen...
Spitze