AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Procedure vs Function, Vor- und Nachteile
Thema durchsuchen
Ansicht
Themen-Optionen

Procedure vs Function, Vor- und Nachteile

Ein Thema von KodeZwerg · begonnen am 15. Apr 2018 · letzter Beitrag vom 23. Apr 2018
Antwort Antwort
Seite 6 von 10   « Erste     456 78     Letzte »    
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#51

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 16:38
sondern lokal ein neuer mutable String erzeugt. Ansonsten würde man ja die übergebene Instanz modifizieren können - was definitiv unerwünscht ist.
Bei WideString stimmt das, da ohne Referenzzählung, aber die LongStrings im Delphi haben eine Referenzzählung.

Referenz wird direkt übergeben (die auf den String und nicht auf die Variable) und verwendet, aber mit RefCount+1 ... beim Schreibzugriff kommt dann ein CopyOnWrite da kein UniqueString.
Jap, aufpassen muss man hier aber schon. Also ganz egal welche Art der Übergabe man verwendet, ist es ja dann nicht.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
482 Beiträge
 
Delphi 11 Alexandria
 
#52

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 16:51
Bei WideString stimmt das, da ohne Referenzzählung, aber die LongStrings im Delphi haben eine Referenzzählung.
Wie? Echt jetzt? WideStrings haben KEIN Refcounting?
Dennis
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
482 Beiträge
 
Delphi 11 Alexandria
 
#53

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 16:59
Hier muss man schon aufpassen. Im Falle eines nicht-const/var/out Strings wird keine direkte Referenz übergeben, sondern lokal ein neuer mutable String erzeugt. Ansonsten würde man ja die übergebene Instanz modifizieren können - was definitiv unerwünscht ist. Auch im Falle von Record stimmt es NICHT, dass immer Referenzen übergeben werden. Das hängt mitunter z.B. von der Record-Größe ab. Selbst ein const garantiert hier nicht zu 100% Referenzen! Musste ich selbst noch die Tage nachlesen.
Schick mir bitte einen Link, wo du dazu infos findest. Denn das DocWiki liefert hierzu nämlich nichts verwertbares. Ich versuche schon seit Jahren, dahinter zu kommen, WIE genau const den Parameterzugriff wann optimiert. Und zu den Referenzen: Das DicWiki sagt tatsächlich auch hier nur, dass es so ist, wie ich beschrieb. Ob es da Ausnahmen gibt, keine Ahnung. Auch hier wäre ich für mein Selbstsstudium um eine Informationsquelle sehr dankbar!
Dennis
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#54

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 17:24
ShortString bzw. String[LEN] .... der alte/erste "String" als Record

LongString > AnsiString, RawByteString, UTF8String, UnicodeString und alle anderen Ableitungen von AnsiString

AnsiString und AnsiString(CP) ... ein aufgemotztes dynamisches Array mit Referenzzählung und ANSI-Codepage
UnicodeString ... ein aufgemotztes dynamisches Array mit Referenzzählung und WideChar
UCS4String ... ein echt schrottiges "array of UCS4Char"

WideString ... eine Kapselung des BSTR der OleAuth32.dll, um die APIs ala MSDN-Library durchsuchenSysAllocString
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (16. Apr 2018 um 17:26 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#55

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 17:27
Schick mir bitte einen Link, wo du dazu infos findest. Denn das DocWiki liefert hierzu nämlich nichts verwertbares. Ich versuche schon seit Jahren, dahinter zu kommen, WIE genau const den Parameterzugriff wann optimiert. Und zu den Referenzen: Das DicWiki sagt tatsächlich auch hier nur, dass es so ist, wie ich beschrieb. Ob es da Ausnahmen gibt, keine Ahnung. Auch hier wäre ich für mein Selbstsstudium um eine Informationsquelle sehr dankbar!
Puh, das sind alles Informationen, die ich im Laufe der Jahre aus verschiedenen Quellen und durch Beobachtung zusammengetragen habe. Also insbesondere zum const kann ich dir sagen, dass Records bis 4/8 Byte (je nach 32- bzw. 64-bit) direkt übergeben werden (da die Werte ja dann direkt in ein Register bzw. auf den Stack passen) und erst danach werden (meistens) Referenzen verwendet. Dazu steht im Wiki:
Zitat:
Constant parameters may be passed to the function by value or by reference, depending on the specific compiler used. To force the compiler to pass a constant parameter by reference, you can use the [Ref] decorator with the const keyword.

Bezüglich Strings habe ich mal ein paar Tests gemacht:

Testfunktionen:
Delphi-Quellcode:
procedure Test1(S: String);
begin
  ShowMessage(S);
end;

procedure Test2(const S: String);
begin
  ShowMessage(S);
end;

procedure Test3(var S: String);
begin
  ShowMessage(S);
end;
Aufrufe (alles Referenzen):
Code:
Unit2.pas.45: Test1(S);
005CE35C 8B45F8           mov eax,[ebp-$08]
005CE35F E85CFFFFFF      call Test1
Unit2.pas.46: Test2(S);
005CE364 8B45F8           mov eax,[ebp-$08]
005CE367 E89CFFFFFF      call Test2
Unit2.pas.47: Test3(S);
005CE36C 8D45F8           lea eax,[ebp-$08]
005CE36F E8A8FFFFFF      call Test3
Test1:
Code:
Unit2.pas.26: begin
005CE2C0 55               push ebp
005CE2C1 8BEC            mov ebp,esp
005CE2C3 51               push ecx
005CE2C4 8945FC          mov [ebp-$04],eax
005CE2C7 8B45FC          mov eax,[ebp-$04]
005CE2CA E891BAE3FF      call @UStrAddRef
005CE2CF 33C0             xor eax,eax
005CE2D1 55               push ebp
005CE2D2 68FBE25C00       push $005ce2fb
005CE2D7 64FF30           push dword ptr fs:[eax]
005CE2DA 648920           mov fs:[eax],esp
Unit2.pas.27: ShowMessage(S);
005CE2DD 8B45FC          mov eax,[ebp-$04]
005CE2E0 E8BB9DF7FF      call ShowMessage
Unit2.pas.28: end;
005CE2E5 33C0             xor eax,eax
005CE2E7 5A              pop edx
005CE2E8 59               pop ecx
005CE2E9 59               pop ecx
005CE2EA 648910           mov fs:[eax],edx
005CE2ED 6802E35C00       push $005ce302
005CE2F2 8D45FC          lea eax,[ebp-$04]
005CE2F5 E882B9E3FF      call @UStrClr
005CE2FA C3               ret
005CE2FB E998AFE3FF      jmp @HandleFinally
005CE300 EBF0             jmp $005ce2f2
005CE302 59               pop ecx
005CE303 5D              pop ebp
005CE304 C3               ret
Test2:
Code:
Unit2.pas.31: begin
005CE308 55               push ebp
005CE309 8BEC            mov ebp,esp
005CE30B 51               push ecx
005CE30C 8945FC          mov [ebp-$04],eax // danke dafür :D
Unit2.pas.32: ShowMessage(S);
005CE30F 8B45FC          mov eax,[ebp-$04] // danke dafür :D
005CE312 E8899DF7FF      call ShowMessage
Unit2.pas.33: end;
005CE317 59               pop ecx
005CE318 5D              pop ebp
005CE319 C3               ret
Test3:
Code:
Unit2.pas.36: begin
005CE31C 55               push ebp
005CE31D 8BEC            mov ebp,esp
005CE31F 51               push ecx
005CE320 8945FC          mov [ebp-$04],eax
Unit2.pas.37: ShowMessage(S);
005CE323 8B45FC          mov eax,[ebp-$04]
005CE326 8B00             mov eax,[eax]
005CE328 E8739DF7FF      call ShowMessage
Unit2.pas.38: end;
005CE32D 59               pop ecx
005CE32E 5D              pop ebp
005CE32F C3               ret
Hier sieht man schon ganz schön, wie viel Overhead man hat, wenn kein const/var/out verwendet wird. Ref-Counter, SEH, etc. Jetzt modifiziere ich mal Test1 und Test3 , so dass geschrieben statt gelesen wird.

Testfunktionen:
Delphi-Quellcode:
procedure Test1(S: String);
begin
  S := '123';
end;

procedure Test3(var S: String);
begin
  S := '123';
end;
Aufrufe (weiterhin alles Referenzen):
Code:
Unit2.pas.50: Test1(S);
005CE350 8B45F8           mov eax,[ebp-$08]
005CE353 E840FFFFFF      call Test1
Unit2.pas.51: Test3(S);
005CE358 8D45F8           lea eax,[ebp-$08]
005CE35B E898FFFFFF      call Test3
Test1:
Code:
Unit2.pas.26: begin
005CE298 55               push ebp
005CE299 8BEC            mov ebp,esp
005CE29B 51               push ecx
005CE29C 8945FC          mov [ebp-$04],eax
005CE29F 8B45FC          mov eax,[ebp-$04]
005CE2A2 E8B9BAE3FF      call @UStrAddRef
005CE2A7 33C0             xor eax,eax
005CE2A9 55               push ebp
005CE2AA 68D8E25C00       push $005ce2d8
005CE2AF 64FF30           push dword ptr fs:[eax]
005CE2B2 648920           mov fs:[eax],esp
Unit2.pas.27: S := '123';
005CE2B5 8D45FC          lea eax,[ebp-$04] // hier beginnt der copy-on-write Teil
005CE2B8 BAF0E25C00       mov edx,$005ce2f0
005CE2BD E8E2BDE3FF      call @UStrLAsg
Unit2.pas.28: end;
005CE2C2 33C0             xor eax,eax
005CE2C4 5A              pop edx
005CE2C5 59               pop ecx
005CE2C6 59               pop ecx
005CE2C7 648910           mov fs:[eax],edx
005CE2CA 68DFE25C00       push $005ce2df
005CE2CF 8D45FC          lea eax,[ebp-$04]
005CE2D2 E8A5B9E3FF      call @UStrClr // Kopie freigeben
005CE2D7 C3               ret
005CE2D8 E9BBAFE3FF      jmp @HandleFinally
005CE2DD EBF0             jmp $005ce2cf
005CE2DF 59               pop ecx
005CE2E0 5D              pop ebp
005CE2E1 C3               ret
Test3:
Code:
Unit2.pas.36: begin
005CE2F8 55               push ebp
005CE2F9 8BEC            mov ebp,esp
005CE2FB 51               push ecx
005CE2FC 8945FC          mov [ebp-$04],eax
Unit2.pas.37: S := '123';
005CE2FF 8B45FC          mov eax,[ebp-$04]
005CE302 BA1CE35C00       mov edx,$005ce31c
005CE307 E850BDE3FF      call @UStrAsg
Unit2.pas.38: end;
005CE30C 59               pop ecx
005CE30D 5D              pop ebp
005CE30E C3               ret
Auch hier ist die Funktion mit const deutlich kompakter.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
482 Beiträge
 
Delphi 11 Alexandria
 
#56

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 19:06
ShortString bzw. String[LEN] .... der alte/erste "String" als Record

LongString > AnsiString, RawByteString, UTF8String, UnicodeString und alle anderen Ableitungen von AnsiString

AnsiString und AnsiString(CP) ... ein aufgemotztes dynamisches Array mit Referenzzählung und ANSI-Codepage
UnicodeString ... ein aufgemotztes dynamisches Array mit Referenzzählung und WideChar
UCS4String ... ein echt schrottiges "array of UCS4Char"

WideString ... eine Kapselung des BSTR der OleAuth32.dll, um die APIs ala MSDN-Library durchsuchenSysAllocString
Ahh... ja, es schimmert mir allmählich... da war was. Stimmt, danke. Genau das war der unterschied zwischen WideString und UnicodeString.

Klar, dass es bei Strings einen Unterschied macht sagte ich ja bereits. Das geht ja auch (als einzig brauchbare Erklärung) aus dem DocWiki-Eintrag hervor: "Using const allows the compiler to optimize code for structured - and string-type parameters."
Nur wüsste ich halt gern, was bei anderen Typen passiert. Wann bzw. ob diese referenziert werden. Und das steht nirgendwo vernünftig erklärt. Danke zumindest an dieser Stelle für die Records. Ich gehe mal davon aus, dass es bei Integern und arrays entsprechen ähnlich zu statten geht.
Dennis
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.685 Beiträge
 
Delphi 11 Alexandria
 
#57

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 21:03
Das ist heftig was man hier so alles erfährt, vor allem mag ich Zacherl Danken für die "Einsicht" was da tatsächlich intern passiert und himitsu's Weisheiten darüber, das ist sehr Informativer Input, nur weiter so Jungs und Mädels, Ihr seid Top!!!
Hoffentlich wird Thread nicht geschlossen weil es ein wenig von meinem Titel "Procedure vs Function, Vor- und Nachteile" abweicht, ich liebe etwas über Interna zu lernen!
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#58

AW: Procedure vs Function, Vor- und Nachteile

  Alt 16. Apr 2018, 21:33
Nur wüsste ich halt gern, was bei anderen Typen passiert. Wann bzw. ob diese referenziert werden. Und das steht nirgendwo vernünftig erklärt. Danke zumindest an dieser Stelle für die Records. Ich gehe mal davon aus, dass es bei Integern und arrays entsprechen ähnlich zu statten geht.
Triviale Typen wie Integer werden immer direkt in ein Register geschoben oder auf den Stack gepusht. Vollkommen egal, ob du const verwendest oder nicht. Dynamische Arrays verhalten sich eigentlich 1 zu 1 wie Strings (Ref-Count Mechanik, Copy on Write, etc). Statische Arrays (array[n..m] of Integer ) wie folgt:

Ohne const :
Code:
Unit2.pas.29: begin
005CE298 55               push ebp
005CE299 8BEC            mov ebp,esp
005CE29B 83C4A0           add esp,-$60 // Speicher für Elemente auf dem Stack reservieren
005CE29E 56               push esi
005CE29F 57               push edi
005CE2A0 8BF0             mov esi,eax
005CE2A2 8D7DA0           lea edi,[ebp-$60]
005CE2A5 B918000000       mov ecx,$00000018
005CE2AA F3A5             rep movsd // Elemente kopieren
Unit2.pas.31: end;
005CE2AC 5F              pop edi
005CE2AD 5E              pop esi
005CE2AE 8BE5             mov esp,ebp
005CE2B0 5D              pop ebp
005CE2B1 C3               ret
Mit const :
Code:
Unit2.pas.34: begin
005CE2B4 55               push ebp
005CE2B5 8BEC            mov ebp,esp
005CE2B7 51               push ecx
005CE2B8 8945FC          mov [ebp-$04],eax
Unit2.pas.36: end;
005CE2BB 59               pop ecx
005CE2BC 5D              pop ebp
005CE2BD C3               ret
Übergabe erfolgt auch hier erstmal immer als Referenz. Wie man sieht wird aber direkt zu Begin der Funktion eine lokale Kopie erzeugt - obwohl ich die Werte des Arrays nichtmal modifiziere. Meine Testfunktion ist komplett leer.

Als Faustregel verwende ich const ausnahmslos immer, wenn ich Strings, Arrays (egal welcher Art) oder Records übergebe. "Pass by reference" ist schon deutlich performanter als "pass by value" - in Delphi besonders (z.B. aufgrund des Ref-Count Overheads). Bei Objekten (die in Delphi ja eh immer Zeiger auf einen Speicherbereich auf dem Heap darstellen) und allen trivialen Datentypen lasse ich das const konsequent weg. "Richtige" const-correctness - wie z.B. in C++ - unterstüzt Delphi für Objekte eh nicht und bei den trivialen Typen macht es schlicht und einfach eh keinen Unterschied. Die sind ja immer konstant, solange man kein var/out verwendet.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.380 Beiträge
 
Delphi 11 Alexandria
 
#59

AW: Procedure vs Function, Vor- und Nachteile

  Alt 17. Apr 2018, 07:59
Ich versuche schon seit Jahren, dahinter zu kommen, WIE genau const den Parameterzugriff wann optimiert.
Echt jetzt? Wozu? Also wenn Du das als Hobby machst ok.
Wenn Ihr aber professionell programieren wollt dann lasst den ...
Macht lieber schönen lesbaren code der sich schnell verstehen lässt und das tut was der Anwender will. Die Optimierungen hier sind marginal und merkt der Anwender nicht. Ich behaupte nicht mal in 1% der Fälle spielt das eine Rolle. Selbst wenn es mal ein Geschwindigkeitsproblem gibt, dann liegt das meist woanders. (Ich selber habe früher viel mit Assembler gemacht.) Und wenn Ihr schönen Code habt dann kann man viel leichter mal einen Cache o.a. dazwischenschieben wenn es nötig ist. Das bringt dann z.B. Faktor 5 und nicht nur 5%.
Es es hat schon seinen Grund warum EMB da (fast) nichts dokumentiert - sie würden sich ja selbst einen Klotz für künftige Optimierungen ans Bein binden.
http://clean-code-developer.de/die-g..._Optimierungen
  Mit Zitat antworten Zitat
Benutzerbild von bernau
bernau

Registriert seit: 1. Dez 2004
Ort: Köln
1.268 Beiträge
 
Delphi 11 Alexandria
 
#60

AW: Procedure vs Function, Vor- und Nachteile

  Alt 17. Apr 2018, 08:24
Ich versuche schon seit Jahren, dahinter zu kommen, WIE genau const den Parameterzugriff wann optimiert.
Echt jetzt? Wozu? Also wenn Du das als Hobby machst ok.
Wenn Ihr aber professionell programieren wollt dann lasst den ...
Macht lieber schönen lesbaren code der sich schnell verstehen lässt und das tut was der Anwender will. Die Optimierungen hier sind marginal und merkt der Anwender nicht. Ich behaupte nicht mal in 1% der Fälle spielt das eine Rolle. Selbst wenn es mal ein Geschwindigkeitsproblem gibt, dann liegt das meist woanders. (Ich selber habe früher viel mit Assembler gemacht.) Und wenn Ihr schönen Code habt dann kann man viel leichter mal einen Cache o.a. dazwischenschieben wenn es nötig ist. Das bringt dann z.B. Faktor 5 und nicht nur 5%.
Es es hat schon seinen Grund warum EMB da (fast) nichts dokumentiert - sie würden sich ja selbst einen Klotz für künftige Optimierungen ans Bein binden.
http://clean-code-developer.de/die-g..._Optimierungen
Also der Code wird m.M nach nicht unleserlicher, wenn man const verwendet.

Macht sich auch nicht immer bemerkbar. Wenn man aber eine Procedure hat, die Millionen mal aufgerufen wird, dann bekommt man schon einen merkbaren Geschwingkeitsschub.

Ich bin seit ein paar Jahren mit Refactoring beschäftigt, um meinen Code von meinem Altprojekt leserlicher zu machen. Manchmal gehört es auch dazu ein fehlendes const einzufügen. Mit Ctrl-Alt-Shift-P ist die Änderung auch ganz schnell in die Impelemtation oder in das Interface übertragen.
Gerd
Kölner Delphi Usergroup: http://wiki.delphitreff.de
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 6 von 10   « Erste     456 78     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz