|
Online
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.339 Beiträge Delphi 12 Athens |
#1
Es ist ja wohl bekannt, daß bei vielen Änderungen der Arraygröße eine Menge Zeit draufgeht.
Dagegen gibt es eigentlich nur ein Mittel > die Anzahl der Änderungen muß verringert werden, so daß nicht gleich bei jeder kleinen Änderung der gesamte Arrayinhalt hin- und herkopiert wird. Als Erstes könnte man es mal mit einem anderem Memory-Manager versuchen (z.B. ![]() allerdings ist es da nicht möglich das Verhalten an eigene Bedürfnisse anzupassen. Also wäre es wohl nicht schlecht, wenn selber das Verhalten geändert wird. 1.) Verwendete und tatsächliche Größe unabhängig verwalten: Wozu noch eine extra Variable für den verwendeten Bereich nötig wäre.
Code:
[b][color=blue]// Definition[/color][/b]
[b]Var[/b] MyArray: [b]Array of[/b] XXX; MyArray_Length: Integer; [b][color=blue]// SetLength(MyArray, NewLength);[/color][/b] MyArray_Length := NewLength; SetLength(MyArray, [color=green](NewLength + $1FFF) [b]and not[/b] $1FFF[/color]); [b][color=blue]// Length(MyArray)[/color][/b] MyArray_Length [b][color=blue]// High(MyArray)[/color][/b] MyArray_Length - 1 [b][color=blue]// MyArray[Index][/color][/b] MyArray[Index] 2.) Verwendete Größe mit Array speichern: z.B. am Ende/nach den Array-Daten Keine weitere Variable nötig, somit wären die Funktionen auf mehrere Arrays anwendbar.
Code:
Dieses Beispiel ist nur für SizeOf(XXX) >= 4,
[b][color=blue]// Definition[/color][/b]
[b]Type[/b] TMyArray = [b]Array of[/b] XXX; [b]Var[/b] MyArray: TMyArray; [b]Function[/b] Length_(Const A: TMyArray): Integer; [b]Begin[/b] [b]If[/b] A = nil [b]Then[/b] Result := 0 [b]Else[/b] Result := PInteger(@A[High(A)])^; [b]End[/b]; [b]Function[/b] High_(Const A: TMyArray): Integer; [b]Begin[/b] Result := Length_(A) - 1; [b]End[/b]; [b]Procedure[/b] SetLength_([b]Var[/b] A: TMyArray; i: Integer); [b]Begin[/b] [b]If[/b] A <> nil [b]Then[/b] PInteger(@A[High(A)])^ := 0; [b]If[/b] i > 0 [b]Then[/b] [b]Begin[/b] SetLength(A, ([color=green](i + $1FFF) [b]and not[/b] $1FFF[/color]) + 1); PInteger(@A[High(A)])^ := i; [b]End Else[/b] A := nil; [b]End[/b]; [b][color=blue]// SetLength(MyArray, NewLength);[/color][/b] SetLength_(MyArray, NewLength); [b][color=blue]// Length(MyArray)[/color][/b] Length_(MyArray) [b][color=blue]// High(MyArray)[/color][/b] High_(MyArray) [b][color=blue]// MyArray[Index][/color][/b] MyArray[Index] wenn SizeOf(XXX) kleiner als SizeOf(Integer) ist, dann muß natürlich mehr als nur ein Feld für die zu speichernde Größenangabe verwendet werden.
Code:
[b]Function[/b] Length_(Const A: TMyArray): Integer;
[b]Begin[/b] [b]If[/b] A = nil [b]Then[/b] Result := 0 [b]Else[/b] Result := PInteger(@A[[color=red]Length(A) - 2{4}[/color]])^; [b]End[/b]; [b]Procedure[/b] SetLength_([b]Var[/b] A: TMyArray; i: Integer); [b]Begin[/b] [b]If[/b] A <> nil [b]Then[/b] PInteger(@A[[color=red]Length(A) - 2{4}[/color]])^ := 0; [b]If[/b] i > 0 [b]Then[/b] [b]Begin[/b] SetLength(A, ([color=green](i + $1FFF) [b]and not[/b] $1FFF)[/color] + [color=red]2{4}[/color]); PInteger(@A[[color=red]Length(A) - 2{4}[/color]])^ := i; [b]End Else[/b] A := nil; [b]End[/b]; [b][color=blue]// 2 für SizeOf(XXX)=2, oder SizeOf(XXX)=3 // 4 für SizeOf(XXX)=1[/color][/b] 3.) Größenangabe direkt im Array ändern: Vorteil zum vorherigen (2) Vorgehen wäre, daß hier nur SetLength geändert werden muß.
Code:
[b][color=blue]// Definition[/color][/b]
[b]Type[/b] TMyArray = [b]Array of[/b] XXX; [b]Var[/b] MyArray: TMyArray; [b]Procedure[/b] SetLength_([b]Var[/b] A: TMyArray; i: Integer); [b]Begin[/b] [b]If[/b] A <> nil [b]Then[/b] PInteger(Integer(A) - SizeOf(Integer))^ := [color=green](PInteger(Integer(A) - SizeOf(Integer))^ + $1FFF) [b]and not[/b] $1FFF[/color]; SetLength(A, [color=green](i + $1FFF) [b]and not[/b] $1FFF[/color]); [b]If[/b] A <> nil [b]Then[/b] PInteger(Integer(A) - SizeOf(Integer))^ := i; [b]End[/b]; [b][color=blue]// SetLength(MyArray, NewLength);[/color][/b] SetLength_(MyArray, NewLength); [b][color=blue]// Length(MyArray)[/color][/b] Length(MyArray) [b][color=blue]// High(MyArray)[/color][/b] High(MyArray) [b][color=blue]// MyArray[Index][/color][/b] MyArray[Index] 4.) Wer nicht direct im Array "rumpfuschen" möchte, könnte es auch mit einer Klasse versuchen. Allerdings wird hierfür dann zusätzlich noch der Constructor und Destructor benötigt.
Code:
[b]Type[/b] TMyArrayClass = [b]Class[/b]
Private A: [b]Array of[/b] XXX; ALen: Integer; [b]Function[/b] GetField(i: Integer): XXX; [b]Procedure[/b] SetField(i: Integer; Value: XXX); Public [b]Procedure[/b] SetLen(i: Integer); [b]Function[/b] Len: Integer; [b]Property[/b] LenX: Integer [b]Read[/b] Len [b]Write[/b] SetLen; [b]Property[/b] Field[i: Integer]: XXX [b]Read[/b] GetField [b]Write[/b] SetField; [b]Default[/b]; [b]End[/b]; [b]Function[/b] TMyArrayClass.GetField(i: Integer): XXX; [b]Begin[/b] Result := A[i]; [b]End[/b]; [b]Procedure[/b] TMyArrayClass.SetField(i: Integer; Value: XXX); [b]Begin[/b] A[i] := Value; [b]End[/b]; [b]Procedure[/b] TMyArrayClass.SetLen(i: Integer); [b]Begin[/b] SetLength(A, [color=green](i + $1FFF) [b]and not[/b] $1FFF[/color]); ALen := i; [b]End[/b]; [b]Function[/b] TMyArrayClass.Len: Integer; [b]Begin[/b] Result := ALen; [b]End[/b]; Var MyArray: TMyArrayClass; [b][color=blue]// Initialisieren[/color][/b] MyArray := TMyArrayClass.Create; [b][color=blue]// SetLength(MyArray, NewLength);[/color][/b] MyArray.SetLen(NewLength); [b][color=blue]{oder}[/color][/b] MyArray.LenX := NewLength; [b][color=blue]// Length(MyArray)[/color][/b] MyArray.Len [b][color=blue]{oder}[/color][/b] MyArray.LenX [b][color=blue]// High(MyArray)[/color][/b] MyArray.High [b][color=blue]// MyArray[Index][/color][/b] MyArray[Index] [b][color=blue]{oder}[/color][/b] MyArray.Field[Index] [b][color=blue]// Finalisieren[/color][/b] MyArray.Free; Fazit: Aus OOP-Sicht wäre 4. zu bevorzugen, auch wenn da vieles zu beachten und zu verändern ist. Bei 1. ist zwar guz zu sehn was gemacht wird, allerdings mu da jedes SetLength, Length und High geändert werden. 2. ist im Grunde nicht zu empfehlen, da dort das Array besser mit SelLength_(MyArray, 0) freigegeben werden sollte, vorallem wenn im Typ dynamische Stukturen enthalten sind, welche von FinalizeArray behandelt werden (z.B. Strings), da es sonst Probleme mit dem Typ-Fremden Integer (der Längenangabe am Ende) geben könnte. Schließlich wird aus gutem Grund die Größenangabe aus dem Array gelöscht, bevor die Größe geändert wird. ![]() Ich selber verwende gerne 3., da hierbei nur SetLength ersetzt werden muß und alles andere unverändert bleibt. Außerdem kann dieses Array überall so verwendet werden, als wäre es ein ganz normalles Array. ![]() Manchmal auch 1., da es ja im Grunde genau das Selbe wie 2. ist, nur halt etwas schneller. Schrittweite: In den Beispielen wird die Arraygröße jeweils in Schritten von 1024 geändert. Es sind natürlich auch andere Werte möglich, aber im allgemeinen sind 2er-Potenzen idealer, da dort binär (mit AND) gerechnet werden kann, wärend sonst mathematische Rechnungen (mit MOD und *) nötig sind. Also einmal ein "schnelles" AND (das NOT wird mit einkopiliert), oder zweimal "langsame" DIV/MUL.
Code:
[b][color=blue]// binär (nur bei 2er-Potenzen)[/color][/b]
[color=green](i + (AllocSize - 1)) [b]and not[/b] (AllocSize - 1)[/color] [b][color=blue]{=}[/color][/b] [color=green](i + $*****) [b]and not[/b] $*****[/color] [b][color=blue]// matematisch[/color][/b] [color=darkgreen]((i + (AllocSize - 1)) [b]div[/b] AllocSize) * AllocSize[/color]
Ein Therapeut entspricht 1024 Gigapeut.
|
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |