Angenommen, ich implementiere etwas Einfaches wie das Durchsuchen einer sortierten Liste / eines Arrays. Die Funktion (in c #) würde ungefähr so aussehen:
static int FindIndex(int[] sortedList, int i);
Ich könnte dies in Bezug auf die Funktionalität implementieren und testen, aber aus offensichtlichen Gründen würde ich normalerweise eine binäre Suche einer linearen Suche vorziehen oder etwas absichtlich Dummes.
Meine Frage lautet also: Sollten wir versuchen, Tests zu schreiben, die die Leistung in Bezug auf die algorithmische Komplexität garantieren, und wenn ja, wie?
Ich habe angefangen, Argumente auf beiden Seiten des "sollten Sie" -Teils dieser Frage vorzubringen, aber ich würde gerne sehen, was die Leute sagen, ohne meine Argumente, um sie dazu aufzufordern.
In Bezug auf "wie" wird das sehr interessant :) Sie können sehen, wie der Vergleichsoperator parametrisiert wird und ein Test durchgeführt wird, dessen Vergleichsoperator Vergleiche oder ähnliches zählt. Aber nur weil du kannst, heißt das nicht, dass du ...
Hat jemand dies (wahrscheinlich) in Betracht gezogen? Vielen Dank.
quelle
Antworten:
Algorithmische Komplexität ist ein theoretisches Konstrukt und daher am besten mit Bleistift und Papier "getestet". Es kann nicht sinnvoll mechanisch getestet werden.
Die absolute Leistung kann mechanisch getestet werden und nützliche Komponententests durchführen. Wenn es auf die Leistung ankommt, können Sie einen Schwellenwert angeben: "Diese Abfrage sollte nicht länger als 50 ms dauern, um mit 10 6 Zahlen und nicht länger als 60 ms mit 10 7 Zahlen ausgeführt zu werden." Dafür kannst du einen Komponententest aufbauen.
Dem Endbenutzer ist es egal, ob Ihr Algorithmus linear oder logarithmisch ist. Sie kümmern sich darum, ob ihre Benutzeroberfläche immer noch sofort reagiert, selbst wenn die App Daten für ein Jahr enthält.
quelle
Obwohl ich nicht sicher bin, ob dieses Tool für Unit-Tests besonders nützlich sein wird, beschreibt die Arbeit "Empirical Computational Complexity" von Goldsmith, Aiken und Wilkerson eine Methode, um Code zu instrumentieren und sein dynamisches Verhalten an einer Reihe verschiedener Eingaben empirisch zu beobachten leiten ihre asymptotische Komplexität ab. Das in dem Artikel beschriebene Programm ist Open Source und steht hier zur Verfügung .
Hoffe das hilft!
quelle
Die Hauptsache ist, es mit Big Data zu versuchen und zu sehen, ob es zu lange dauert.
In meiner Erfahrung mit der Leistungsoptimierung, wie in diesem Beispiel , passiert Folgendes: Wenn ein Algorithmus (zum Beispiel) O (n ^ 2) ist, ist dies möglicherweise in Ordnung, solange der Prozentsatz der Zeit, die dafür benötigt wird, nie auf das Radar gelangt.
Wenn jedoch ein Datensatz mit einer Größe angegeben wird, die möglicherweise nur einmal im Jahr angezeigt wird, kann der von diesem Algorithmus beanspruchte Teil der Gesamtzeit katastrophal dominant werden.
Wenn Sie dies beim Testen erreichen können, ist dies eine sehr gute Sache, da es äußerst einfach ist, das Problem zu finden, als wäre es eine tatsächliche Endlosschleife.
quelle
Ich glaube nicht, dass Sie Unit Testing machen wollen.
AFAIK, Unit-Tests sollen nur sicherstellen, dass der Code das tut, was er tun soll, und sich nicht auf die Leistung konzentrieren.
Es gibt andere Arten von Werkzeugen und Mustern, um die Leistung zu messen. Eines, an das ich mich jetzt erinnern kann, ist das Abnahmetesten, das sich auf nicht-funktionale Anforderungen konzentriert.
Es gibt nur wenige andere wie Leistungstests (die Stresstests, Lasttests usw. verwenden).
Sie können auch einige Stress-Tools zusammen mit einem Build-Tool (ant, automatic build studio) als Teil Ihrer Bereitstellungsschritte verwenden (das ist, was ich tue).
Die kurze Antwort lautet also nein, Sie sollten sich darüber keine Gedanken machen, wenn Sie einen Code testen.
quelle
Das Übergeben des Komparators und das Verfolgen der Häufigkeit, mit der der Komparator aufgerufen wird, funktioniert aus einfachen Gründen, z. B. um zu überprüfen, ob die Anzahl der Vergleiche bei einer Suche in einer festen Eingabe (beispielsweise
new int[] { 1,2,3, ... , 1024 }
) unter 10 bleibt Machen Sie Ihre Absichten klar, wie sich der Algorithmus verhalten soll.Ich denke nicht, dass Unit-Tests der richtige Weg sind, um zu überprüfen, ob Ihr Algorithmus O (log n) ist. Das würde eine Menge zufälliger Datenerzeugung, eine gewisse Kurvenanpassung und wahrscheinlich knifflige Statistiken erfordern, um festzustellen, ob eine Reihe von Datenpunkten zur erwarteten Laufzeit passt. (Für diesen Algorithmus ist es wahrscheinlich machbar, aber wenn Sie anfangen zu sortieren, wird es schwierig, die Worst-Case-Szenarien wiederholt zu treffen.)
quelle