Effizient von Parameterübergabe

binary

Fleet Captain Special
Mitglied seit
11.11.2001
Beiträge
338
Renomée
3
Standort
NRW
Ich überlege grade was effizienter ist: Eine function manipuliert ein array und benötigt dafür die arraygrösse. Da das array schon übergeben wird kann die function die grösse selber ermitteln. Da die arraygrösse aber vorher benötigt wurde liegt sie schon im programm vor und könnte mit überrgeben werden. Welche dieser Lösungen ist im algemeinen schneller. *noahnung*

Wenn möglich bei den antworten bitte nicht zu sehr auf eine spezielle Sprache einegehen.
 
Ich habe keinen Dunst, wie eine Funktion die Größe eines übergebenen Arrays ermitteln soll, aber im anderen Fall sehe ich folgende Möglichkeiten:

1. Das Array und die Größe des Arrays sind der Funktion bekannt mittels globaler Definition. Keine Paremeter erforderlich.
2. Die Größe des Arrays ist der Funktion bekannt mittels globaler Definition. Pointer auf das Array wird übergeben.
3. Neben einem Pointer auf das Array wird der Funktion noch die Größe übergeben.
4. Du benützt kein Array, sondern eine Struktur bzw. Type, bestehend aus Array und Size. Deine Funktion erhält einen Pointer auf diese Struktur.

Die Effizienz (Codegröße und Geschwindigkeit) ist bei 1) am höchsten, Portier- und Erweiterbarkeit bei 4). Welche Variante angebracht ist, hängt davon ab, in welchem Kontext die Funktion arbeiten soll.
Der Unterschied bez. Effizienz ist auf dem PC meiner Meinung nach vernachlässigbar, bei stark beschränkten Ressourcen (z.B. Microcontroller mit wenig RAM/ROM) ist Tendenz zu 1) angebracht.

Ciao,
Ray
 
Original geschrieben von binary
Da die arraygrösse aber vorher benötigt wurde liegt sie schon im programm vor und könnte mit überrgeben werden.
Wenn die Größe des Arrays zuvor schon einmal berechnet worden ist, warum sollte man sie nun noch einmal bestimmen lassen? Das wäre höchst ineffizient ... insbesondere wenn es sich um ein großes Array handelt. Es ist somit wesentlich "billiger", der Funktion auch die Größe des Arrays mitzuteilen.
 
Ich würde die Größe auch gleich im Funktionsaufruf übergeben, da sonst eh nur erneut eine (length)-Funktion aufgerufen wird – das wird meiner Meinung dann teurer.

Du willst es zwar Sprachunabhängig wissen, aber hast du trotzdem mal ein Benchmark gemacht? Würde mich mal interessieren.
 
Original geschrieben von Ray
Ich habe keinen Dunst, wie eine Funktion die Größe eines übergebenen Arrays ermitteln soll, aber im anderen Fall sehe ich folgende Möglichkeiten:

1. Das Array und die Größe des Arrays sind der Funktion bekannt mittels globaler Definition. Keine Paremeter erforderlich.

Na, sowas macht man nicht, das widerspricht der Strukturierung und der Datenkapselung.


2. Die Größe des Arrays ist der Funktion bekannt mittels globaler Definition. Pointer auf das Array wird übergeben.

Das gleiche wie oben, globale Definitionen sollten auf ein Mindestmaß beschränkt werden. Nach Möglichkeit vermeidet man sie ganz. Zum Pointer, siehe unte.


3. Neben einem Pointer auf das Array wird der Funktion noch die Größe übergeben.
4. Du benützt kein Array, sondern eine Struktur bzw. Type, bestehend aus Array und Size. Deine Funktion erhält einen Pointer auf diese Struktur.

Zeiger sollte man nach Möglichkeit auch sparsam einsetzen, weil man sich damit eine zusätzliche Fehlerquelle ins Boot holt, die zudem auch schwer zu lokalisieren ist.

Variante 4 ist wahrscheinlich am schönsten zu benutzen, aber es geht auch mit zwei Parametern beim Funktionsaufruf. Wenn möglich, übergib das Array und die Größe als Referenzen, damit sparst du dir zusätzliche Kopien. Das ist dann von der Geschwindigkeit nahezu genauso schnell, wie globale Definitionen, nur wesentlich sauberer.
 
Das gleich mit zu übergeben dürfte imho auch das schnellste sein. Wenn es sinnvoll erscheint kannst du das natürlich auch global speichern bzw. fest verdrahten.
 
Original geschrieben von PuckPoltergeist
Na, sowas macht man nicht, das widerspricht der Strukturierung und der Datenkapselung.

Das gleiche wie oben, globale Definitionen sollten auf ein Mindestmaß beschränkt werden. Nach Möglichkeit vermeidet man sie ganz. Zum Pointer, siehe unte.

Zeiger sollte man nach Möglichkeit auch sparsam einsetzen, weil man sich damit eine zusätzliche Fehlerquelle ins Boot holt, die zudem auch schwer zu lokalisieren ist.

Variante 4 ist wahrscheinlich am schönsten zu benutzen, aber es geht auch mit zwei Parametern beim Funktionsaufruf. Wenn möglich, übergib das Array und die Größe als Referenzen, damit sparst du dir zusätzliche Kopien. Das ist dann von der Geschwindigkeit nahezu genauso schnell, wie globale Definitionen, nur wesentlich sauberer.

Mann bist Du doof! )((
Es ging um Effizienz. 4 Beispiele, von "sehr effizient" bis "strukturiert", um die Unterschiede zu verdeutlichen. Und Du zerhackst mein Posting, um allen zu zeigen, was für ein geballtes Wissen in die steckt.
Die Effizienz ist bei meinen Beispielen bei 1) am größten, ob das Dein Hirn nun begreift oder nicht, ob Du nur der Lehre der "Strukturierung und der Datenkapselung" hinterher hecheln kannst, ist dabei völlig egal.
Weiterhin ist nicht bekannt, in welchem Kontext die Funktion sich befindet. Unter Umständen handelt es sich um eine Implementierung einer Klasse, welche auf private Membervariablen zugreifen kann... und alles ist sauber gekapselt.
 
Original geschrieben von Ray
Mann bist Du doof! )((
Es ging um Effizienz. 4 Beispiele, von "sehr effizient" bis "strukturiert", um die Unterschiede zu verdeutlichen. Und Du zerhackst mein Posting, um allen zu zeigen, was für ein geballtes Wissen in die steckt.
Die Effizienz ist bei meinen Beispielen bei 1) am größten, ob das Dein Hirn nun begreift oder nicht, ob Du nur der Lehre der "Strukturierung und der Datenkapselung" hinterher hecheln kannst, ist dabei völlig egal.
Weiterhin ist nicht bekannt, in welchem Kontext die Funktion sich befindet. Unter Umständen handelt es sich um eine Implementierung einer Klasse, welche auf private Membervariablen zugreifen kann... und alles ist sauber gekapselt.

Reg dich nicht auf, inzwischen kennen wir das ja. Und bis zu deinem Quote hab ich nur wahrgenommen, dass Puck hier irgendwas geschrieben hat (aber nicht was ;D).
 
Original geschrieben von Ray
Mann bist Du doof! )((
Es ging um Effizienz. 4 Beispiele, von "sehr effizient" bis "strukturiert", um die Unterschiede zu verdeutlichen. Und Du zerhackst mein Posting, um allen zu zeigen, was für ein geballtes Wissen in die steckt.

Ich "zerhacke" dein Posting, um zu zeigen, welche Nachteile man sich sich mit den Varianten einfängt. Das hättest du auch selber machen können, wenn du schon Sachen vorschlägst, die man in der praktischen Programmierung besser läßt.


Die Effizienz ist bei meinen Beispielen bei 1) am größten, ob das Dein Hirn nun begreift oder nicht, ob Du nur der Lehre der "Strukturierung und der Datenkapselung" hinterher hecheln kannst, ist dabei völlig egal.

Und weil sich alles nur um Effizienz dreht, schmeißen wir die Strukturierung gleich komplett über den Haufen, und schreiben wieder in Assembler. Falls es dir noch nicht aufgefallen ist, auch die Optimierung hat ihre Grenzen, und gewisse Sachen läßt man dabei einfach sein.


Weiterhin ist nicht bekannt, in welchem Kontext die Funktion sich befindet. Unter Umständen handelt es sich um eine Implementierung einer Klasse, welche auf private Membervariablen zugreifen kann... und alles ist sauber gekapselt.

Dann brauch auch nichts übergeben werden, und die ganze Diskussion ist von vornherein hinfällig.
 
Ich glaub Ray hat so deutlich mehr Progger-Stunden auf dem Zähler als du. Ich sicherlich auch *wenigerbescheidensei;D*
 
Original geschrieben von intel_hasser
Ich glaub Ray hat so deutlich mehr Progger-Stunden auf dem Zähler als du. Ich sicherlich auch *wenigerbescheidensei;D*

Na klasse, und deshalb wird auf saubere Programmierung verzichtet? Mag ja sein, dass Ray schon lange genug programmiert, und deshalb auf Grund der Erfahrung schon von vornherein sauber strukturiert, nur zu viele Leute machen das nicht. Da wird dann auf Teufel komm raus "optimiert", um auch die letzte Nachkommastelle an Geschwingigkeitszuwachs heraus zu quetschen, mit dem Resultat von unwartbaren Codemonstern.
Wenn man solche Ratschläge in offenen Foren gibt, wo das jeder lesen kann, sollte man auch auf die Risiken und Probleme hinweisen. Aufzeigen kann man die Möglichkeiten immer, aber es gehört auch dazu, zu sagen, was man davon besser läßt, für diejenigen, die es halt noch nicht wissen.
 
@PuckPoltergeist

Mit Deinem Schulprogrammieren kommst Du aber mehr als nur sehr oft an Grenzen!

Sieht ein Programm im Struktogramm wunderbar übersichtlich aus, wird es ohne Sprünge (wie break, return oder z.T. auch noch GoTo) sehr schnell sehr unübersichtlich.
Wen interessiert Datenkapselung wenn ich ein kleines eigenständiges Programm aus 5 - 6 Funktionen schreibe?
Da lege ich fast alles Global an um mit riesen Programmköpfe zu sparen.

Wärend meiner Ausbildung hörte ich auch so Sprüche wie "Nie mehr als 2 DinA4 Seiten pro Funktion, immer schön Strukturiert..."
Es hat keine 2 Wochen gedauert bis die ersten "realen" Funktionen mehr als nur weit über die 2 Seiten hinausquollen.
 
Original geschrieben von Devastators
Mit Deinem Schulprogrammieren kommst Du aber mehr als nur sehr oft an Grenzen!

Es gibt sicherlich Ausnahmen, aber die sollten nicht zur Regel erhoben werden.

Functions should be short and sweet, and do just one thing. They should
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
as we all know), and do one thing and do that well.

The maximum length of a function is inversely proportional to the
complexity and indentation level of that function. So, if you have a
conceptually simple function that is just one long (but simple)
case-statement, where you have to do lots of small things for a lot of
different cases, it's OK to have a longer function.

However, if you have a complex function, and you suspect that a
less-than-gifted first-year high-school student might not even
understand what the function is all about, you should adhere to the
maximum limits all the more closely. Use helper functions with
descriptive names (you can ask the compiler to in-line them if you think
it's performance-critical, and it will probably do a better job of it
than you would have done).

Another measure of the function is the number of local variables. They
shouldn't exceed 5-10, or you're doing something wrong. Re-think the
function, and split it into smaller pieces. A human brain can
generally easily keep track of about 7 different things, anything more
and it gets confused. You know you're brilliant, but maybe you'd like
to understand what you did 2 weeks from now.

Linus erzählt auch viel Schrott, aber hierbei stimme ich ihm zu.
 
Original geschrieben von PuckPoltergeist
Es gibt sicherlich Ausnahmen, aber die sollten nicht zur Regel erhoben werden.


Richtig, aber wenn 100% Performance erfordert wird denke ich das es genug Grund ist für eine Ausnahme :)
 
Och jetzt regt euch alle wieder ab.

Ray ist auch nicht gerade freundlich gewesen und Eure privaten Streitereien könnte sicher auch per PN klären, oder?
 
So, nochmal: Es ging um Effizienz! Und nicht um einen Diskurs über Software Engineering.
Eine parameterlose Funktion Doit() dürfte wohl unstrittig die effizienteste Methode darstellen.
Natürlich sollen die Entwickler saubere und strukturierte Methoden anwenden, das dürfte ebenso unstrittig sein. Als erster Ansatz würde mein Beispiel 3.) wohl der natürlichste im Sinne sauberer Programmierung sein.
Aber wie ich schon andeutete, kommt es auf den Kontext und die tatsächliche Programmierumgebung an.
Wenn die Aufgabe besteht, eine API für eine allgemein verwendbare Library zu definieren, werden Funtionen zur Bearbeitung von Arrays selbstverständlich das Array und dessen Größe als Parameter bekommen (oder eine entspr. Struktur).
Wird ähnliche Funktionalität (die Array-Funktion) in einem System mit begrenzten Ressourcen benötigt, kann ich unter Umständen auf Parameter verzichten.
Zum Beispiel:
Man stellt heute fest, daß der Programmcode nicht mehr ins Flash paßt, gestern war alles noch im Lot. Was ist passiert? Kollege X hat die letzten Features implementiert, das Fass ist übergelaufen. Die Durchsicht der letzten Änderung zeigt nichts besonderes, muß wohl so sein. Aber eigentlich wurde abgeschätzt, daß wir mit der Codesize hinkommen.
Also wird der Sourcebaum nach Funktionensaufrufen mit hoher Häufigkeit und gleichzeitig vielen Parametern geparst. Zum Vorschein kommt, daß jene Array-Funktion zig hundertmal mit immer demselben Size-Parameter und gar demselben Array aufgerufen wird.
Der Fall liegt eindeutig auf der Hand, hier läßt sich ein Vielfaches an Code alleine durch Verzicht der Parameteraufbereitung für die zig hundert Calls einsparen.
Mindestens eine parameterlose Wrapperfunktion (für den parameterbehafteten Original-Aufruf) kommt nun zum Einsatz oder die Original-Funktion wird modifiziert, wenn es sich anbietet. Programmierer entwickeln halt unterschiedlich strukturierten/optimierten Code...

Mit solchen und ähnlichen Maßnahmen habe ich schon manches SW-Projekt in der Vergangenheit gerettet. Das kann sich in bare Münze auszahlen, wenn die Hardware mit kleineren Speichergrößen für Flash/ROM/RAM auskommt, dadurch Kosten und/oder Platinengröße spart.
Das bedeutet noch lange nicht, daß eine so optimierte Software unstrukturiert oder gar chaotisch ist. Im Gegenteil, mit der Zeit bekommt man eine andere Sichtweise und strukturiert/modularisiert gleich von vorne weg, sodaß Optimiermaßnahmen dieser Kategorie gegen Projektende nicht mehr notwendig sind (es macht auch keinen Spaß, im Code anderer Leute zu wühlen ;)) und trotzdem eine saubere Lösung vorliegt.

@Puck: Meine unfreundlichen Ausdrücke nehme ich zurück, meine Meinung zum Thema natürlich nicht.


BTW: Es ist schon erstaunlich, was ein paar Zeilen Posting so bewirken können... *kopfkratz :( ;)

Dabei hat binary doch nur eine einfache Frage gestellt.

Ciao,
Ray
 
Wie bereits gesagt geht es mir bei der Frage primär um den möglichen performance-gewinn. Das bei starker Optimierung die Codeübersichtlichkeit leidet ist klar. Ich habe die Frage auch mit Absicht ohne Bezug zu einem konkreten Projekt gestellt, weil ich (algemein) wissen wollte ob man seinen "Programierstiel" auf effizienz optimieren kann (zB durch änderungen der functionsaufrufe wie in Rays letztem Beispiel). Das Beispiel eines Functionsaufrufes hat mich besonders interessiert da bei vielen functionen eine kleine Änderung im Aufruf unter umständen schon einen messbaren Performanceschub geben kann.
Wenn man wie Devastators 100% Performance will ist das sicher ein Grund Abstriche bei der Strukturierung und Übersictlichkeit in kauf zu nehmen, dann werden aber sicher auch spezielle optimierungsmöglichkeiten der verwendeten Sprache benutzt, was ja über das Thema meiner eigentliche Frage hinausgeht.

@Orkomike Nein ich habe nicht gebrencht, da das ja wieder Sprachabhängig wäre und es bestimmt jemanden gegeben hätte der den Brenchmark anders(und natürlich besser *nein* ) gemacht hätte.
 
Original geschrieben von intel_hasser
Überleg mal, du willst uns hier vorschreiben wie man ordentlich programmiert und hast selber nur einen Bruchteil so viel Code geschrieben.
Wieso sollte er deshalb keine Ahnung haben?
Könnte ja sein dass Du seit Jahren "falsch" und "unsauber" programmierst, er jedoch erst seit kurzer Zeit, aber dank gutem Lehrmeister und schneller Auffassungsgabe einen saubereren Code hinlegt als Du (was ich jetzt in diesem Fall nicht behaupten will, kann aber diese allgemein gültige Aussage nicht stehen lassen).

Geschwindigkeit ist nicht alles. Lesbarkeit und Strukturierung ist gerade in großen Projekten wichtig.
Und Datenkapselung hat auch was mit Sicherheit zu tun!
Grundsätzlich hat Puk also nicht ganz unrecht, wobei er in diesem Fall vielleicht etwas über das Ziel hinausgeschossen ist.



Original geschrieben von intel_hasser
Ich merk schon, es war ein Fehler sich deine Beiträge anzugucken - tja, Gutmütigkeit wird bestraft.

Ach ja, vergiss nicht - hier im Progger Forum bin ich Mod...
also so nen Spruch hätte ich jetzt von einem Mod nicht erwartet :o
 
Original geschrieben von culix

also so nen Spruch hätte ich jetzt von einem Mod nicht erwartet :o


Oah, stimmt.. laut Forum ist er als Mod eingetragen. Erkennt man garnicht!
Ich gebe Dir aber Recht, als Mod sollte man jeder Zeit die Fassung bewahren und die eigenen Beiträge vielleicht 3x lesen... :]

Aber Datenkapselung und Datensicherheit ist IMHO noch Diskussionswürdig.
Ich habe es bis jetzt nicht wirklich benötigt und sehe auch nicht den 100% Grund dies zu tun.
Compilierter Code (obj-Files) ist kaum recompilierbar und sofern man den Quellcode sieht ist es mit der Datenkapselung eh hinüber (sofern man böses plant)

Die Gefahr der Programmierfehler steigt m.E.

Also klärt mich dann bitte mal auf wieso Datenkapselung (und der daraus scheinbar entstehende Schutz) so wichtig ist?
Meine Lehrer konnten das nicht wirklich gut erklären :-/
 
Sicherheit mein ich jetzt bezüglich Sicherheit von "Innen" (deine Variablen, Objekte... sind nicht "aus Versehen" veränderbar, sprich nicht jeder kann daran herumpfuschen und sie dabei ungewollt modifizieren)
War vielleicht nen bißchen blöd ausgedrückt.
 
jep, schon klar.

Aber wer ist dabei "jeder" ?

jemand der meine OBJs oder gar meinen Quellcode legal benutzt?
Gut, das sage ich ja auch das dies im Bereich zu Minderung von Fehlerquellen zählt.

Ich finde auch die Datenkapselung und die privaten Elemente einer Klasse (OO) relativ überflüssig, da man anhand der Header Datei doch 1A erkennen kann welche Variablen in der Klasse genutzt werden.
Und eine Variable in einer Klasse überschreibt man doch schon aus technischen Gründen kaum aus versehen...?!?
Wo ist meine Wissenslücke oder mein Denkfehler?
 
Also ich arbeite hier in einem Projekt mit 11 anderen Programmierern.
Diese 11 sind "jeder" ;)
 
Original geschrieben von Devastators
Also klärt mich dann bitte mal auf wieso Datenkapselung (und der daraus scheinbar entstehende Schutz) so wichtig ist?
Meine Lehrer konnten das nicht wirklich gut erklären :-/

Wenn du nicht alleine an einem Projekt arbeitest, müssen andere deinen Code lesen können. Je weniger strukturiert der ist, desto schwieriger wird das. Bei 10 Quellcode-Dateien im Projekt mag das vielleicht noch nicht das Problem sein, aber wenn mit hunderten oder tausenden von Dateien gearbeitet wird, hast du keine Chance mehr.
Selbst wenn du alleine arbeitest wird das dann zum Problem. Der letzte Satz im Zitat von Linus bringt das sehr schön auf den Punkt: You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now.
Bei einem sauber strukturierten Code siehst du sofort, was er macht und auch wieso du das auf diese Weise realisiert hast, und nicht anders. Musst du dich erst durch zehn Dateien wühlen, um zu verstehen was eine Funktion macht, kommst du zu keinem Ende.

PS: Das unstrukturierte Vorgehen ist jetzt ziemlich extrem dargestellt, sollte aber verdeutlichen, wieso man in seinem Programmcode Ordnung halten soll.


Jay:

Ich widerspreche dir da ja auch nicht. Allerdings habe ich die Erfahrunge gemacht, das es in (sehr) vielen Projekten drunter und drüber geht, weshalb ich bei solchen Optimierungsvorschlägen sehr vorsichtig bin. Die enden dann sehr häufig mit einem Schuss in den Fuß. Ok, ich hätte das auch weniger offensiv bei der Antwort auf dein Posting schreiben können, mein Fehler. :] Es sollte halt nur eine Warnung sein, dass man mit zu viel Optimierung auch das Gegenteil erreichen kann und das ganze vor die Wand fährt.
 
hmmm, also momentan habe ich das Problem das ich in vielen Funktionen viele Labels und Buttons brauche die bereits allokiert sind.
Ich habe absolut keine Lust 50 Variablen zu übergeben damit ich die Buttons und Labes überall benutzen kann.
Auch sträubt mich der Gedanke alle Buttons in ein Feld zu legen und dieses dann per index anzusprechen, denn dann ist es aus mit Lesbarkeit der Variablen.

zumindest C bietet ja die Möglichkeit der statischen Globalen Variablen, die dann dem Linker nicht weiter bekannt sind. Ich finde damit kann man schon ganz gut leben.
Ansonsten sehe ich kaum einer praktizierbare Lösung als Globale Variablen, wenn es darum geht allgemeine und wichtige Daten überall verfügbar zu haben.

Klar, dass nur lokale Variablen nur lokal angelegt werden, darüber brauchen wir nicht streiten...
 
War vielleicht ein bisschen hart, aber unter normalen Umständen hätte ich das so auch nicht losgelassen.

Sucht euch mal durch das Forum (insbesondere 128bit Thread und ISA Thread im CPU Forum) zu was Diskussionen mit Puck ausarten können. Daher wohl auch Rays Reaktion...


Im CPU Forum kann ich dagegen nix machen, aber hier fangen wir solche Endlosdiskussionen um nix erst garnicht an.
 
Zurück
Oben Unten