Array in mehreren Etappen erzeugen [ERLEDIGT]

Konzeptionelles, Technisches, Termine, Fragen zum Hersteller usw.

Moderator: Moderatoren

Antworten
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21200
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von Manfred »

Moin,

da ich die DB Strukturen meiner DB in einem Array festverdrahtet im Code habe und in jeder DB 6 gleiche Felder sind, stellt sich mir folgende Frage:

Ist es ohne Probleme machbar, im 1.Schritt an einer zentralen Stelle die besagten Felder in das Strukturarray zu schreiben und dann im 2.Schritt die restlichen, jeweils verschiedenen Felder nachzutragen? Oder ist es immer besser sofort alle Felder in ein Array einzutragen? Bringt das eine oder andere Speicherprobleme, Tempoprobleme, oder irgendwas, was zur Laufzeit negative Auswirkungen haben könnte? Oder ist dabei sonst irgendwas zu beachten?
Zuletzt geändert von Manfred am Do, 25. Jun 2009 13:45, insgesamt 1-mal geändert.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array in mehreren Etappen erzeugen

Beitrag von brandelh »

Hallo Manfred,

die Reihenfolge im Array bestimmt die Reihenfolge der Felder in der DBF.
Wenn dir das egal ist, dann kannst du die anderen Felder "vorladen".

Zu der Auswirkung der Array Erzeugung, natürlich ist es etwas langsamer
100 aadd() + Daten aufzurufen, als einmal ARRAY(100) und 100 Zuweisungen,
aber in dieser Größenordnung wird man das kaum messen können.

Erst bei deutlich mehr als 1000 Einträgen (hängt auch von Hardware ab) wird
man Unterschiede feststellen können.
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Array in mehreren Etappen erzeugen

Beitrag von AUGE_OHR »

Manfred hat geschrieben:und in jeder DB 6 gleiche Felder sind, stellt sich mir folgende Frage:
em ... äh ... 6 "ID" Felder ? und überall steht das selbe in den DBF´s in den 6 "ID" Feldern ?
leicht irritiert, deshalb weiss ich nicht genau worauf du raus willst.

ich habe verstanden das du ein Array hast wo du "zur Laufzeit" etwas befürchtest... aber was ?

wenn in deinem Array alle Feldnamen von allen DBF´s stehen ... angenommen 100 DBF a 250
Felder dann sind wir ja "nur" bei 25000 Elementen a 10 Zeichen -> 250Kb ... also kein Problem mit Array.

oder meinst du das dadurch der RAM Speicher "zerstückelt" wird wenn du es "nacheinander" lädt ?
Das "sollte" der CG für dich "erledigen" und "aufräumen" ... wenn du ihm Zeit lässt.
Manfred hat geschrieben:die DB Strukturen meiner DB in einem Array festverdrahtet im Code
Frage : warum nicht in einer DBF alle Strukturen ?

... und die nächste Frage wäre dann : und wenn ich die aus der DBF in ein Array lade ...
im Stück oder nacheinander oder mittels Thread im Hintergrund ...
gruss by OHR
Jimmy
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21200
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Re: Array in mehreren Etappen erzeugen

Beitrag von Manfred »

Hi,

es ist das Feld für die ID und 5 Felder für Sperrvorgänge zur Info. Diese 6 Felder sind in jeder DB und es wäre Blödsinn, die jedesmal immer wieder zu schreiben. Wenn ich ein weiteres Feld hinzufügen oder entfernen, oder ändern möchte, dann wird das jetzt zentral gemacht und vereinfacht den Vorgang immens.

Die Lösung mit dem Array habe ich gewählt, weil es m.E. einfacher ist EINE Dll nachzuliefern, als x-DB mit Struktur. Außerdem ist es einfacher eine DB zu löschen oder zu verändern aus Usersicht, als eine DLL. Bei der DLl wird es sofort gemerkt, wenn die fehlt.

Und wie Du richtig erwähntest, meine Frage zielte darauf, ob es irgendwas schlechtes verursachen kann im Speicher usw. wenn es während der Laufzeit in 2-3 Vorgängen vollzogen wird. Aber so wie ich Hubert verstanden habe, trifft es für mich nicht zu, weil die Arrays nicht so groß werden.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Re: Array in mehreren Etappen erzeugen

Beitrag von Dieter »

Hallo Hubert,

du hast geschrieben:
Zu der Auswirkung der Array Erzeugung, natürlich ist es etwas langsamer
100 aadd() + Daten aufzurufen, als einmal ARRAY(100) und 100 Zuweisungen,
aber in dieser Größenordnung wird man das kaum messen können.
Deine Aussage gilt nur, wenn man die Anzahl der Elemente nicht ermitteln muss
oder die Daten nicht auf einem Netzwerkserver liegen.
Ich war selber überrascht wie viel Zeit ein

Code: Alles auswählen

COUNT TO nAnzahl FOR <Bedingung>
// oder alternativ
DbEval({|| ++nAnzahl},,{|| .NOT. EOF()},,,.T.)
 
in Anspruch nehmen, wenn die Daten auf einem Netzwerkserver liegen.
Sie benötigen ungefähr soviel Zeit, wie das Schreiben der Daten in das Array.
Somit sollte man grundsätzlich die AADD()-Funktion zur Array-Erstellung nutzen
(fast doppelt so schnell).
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array in mehreren Etappen erzeugen

Beitrag von brandelh »

Hallo Dieter,

wenn die Daten von einer lahmen Netzwerkverbindung eingelesen werden, spielt natürlich das einzelne AADD keine große Rolle mehr ;-)

Bei Alaska habe ich aber z.B. ein Beispiel gesehen, das neben dem normalen Daten beschaffen, das Array immer nur jeden 100. Satz (oder 500) um jeweils 500 Sätze erweitert hat. Ganz am Ende wurde es dann mit aSize() auf die tatsächlich nötige Länge gekürzt. Das war um einiges schneller, als jedesmal ein AADD() und hat jeden Datensatz in der DBF nur einmal gelesen.
Das Problem bei vielen AADD() Aufrufen ist die Speicherverteilung und das Speichermanagement, das einige Zeit mehr kostet.

ABER natürlich kommt es immer darauf an, ob dieser "Zeitverlust" tatsächlich relevant ist.
Ein EXTRA COUNT Lauf nur für die Ermittlung der Arraygröße ist Zeitverschwendung, da hast du völlig recht. ;-)
Gruß
Hubert
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von Dieter »

Hallo Hubert,

du hast geschrieben:
Bei Alaska habe ich aber z.B. ein Beispiel gesehen, das neben dem normalen Daten beschaffen, das Array immer nur jeden 100. Satz (oder 500) um jeweils 500 Sätze erweitert hat. Ganz am Ende wurde es dann mit aSize() auf die tatsächlich nötige Länge gekürzt. Das war um einiges schneller, als jedesmal ein AADD() und hat jeden Datensatz in der DBF nur einmal gelesen.
Ich habe deinen Hinweis aufgegriffen und versucht ohne AADD() mit obengenannter Vorgehensweise meine Array-Erstellung zu beschleunigen. Leider bekomme ich nach dem ersten ASIZE() die Fehlermeldung "Parameter hat falschen Typ".

Code: Alles auswählen

n=500
aFi:=ARRAY(n,FI_SPALTEN)
i=0
DO WHILE !EOF()
  ++i
  //AADD(aFI,ARRAY(FI_SPALTEN))
  IF i>n
    n=n+500
    ASIZE(aFi,n)
  ENDIF
  aFi[i,FI_BELEG_NR]=fin->BELEG_NR      // in dieser Zeile entsteht der Fehler 
  ...
Warum bekomme ich ab i=501 die vorgenannte Fehlermeldung? Der Debugger zeigt mir, dass zu diesem Zeitpunkt LEN(aFi)=1000 ist. Weiterhin zeigt er an:

Code: Alles auswählen

oError:args         :
          -> VALTYPE: U VALUE: NIL
          -> VALTYPE: N VALUE: 1
Es scheint so, als wenn der 1.Parameter, also i den Fehler erzeugt, aber erst nach dem ersten ASIZE-Aufruf. Ich kann keinen Fehler im Code entdecken und bin etwas ratlos. :(
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von brandelh »

Hi,

Code: Alles auswählen

aFi:=ARRAY(n,FI_SPALTEN)
erstellt ein zweidimensionales Array an:

{ { NIL, NIL, .... },; // bis FI_SPALTEN
{ NIL, NIL, .... } }

aSize() fügt am ENDE aber nur eindimensional NIL an ...

Code: Alles auswählen

{ { NIL, NIL, .... },;  // bis FI_SPALTEN
   { NIL, NIL, .... },;
   NIL,;
   NIL,; ...
 }
Du musst also ein lokales Array mit den Werten einer Zeile füllen und dann dieses ZeilenArray als Ganzes hineinkopieren.
Ohne Zweifel wird das natürlich etwas den eventuellen Vorteil auffressen ...
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von brandelh »

Hallo,

hier mein kleines Testbeispiel, ohne DBF, aber das ist ja egal ;-)

Code: Alles auswählen

#define FI_SPALTEN 5

proc main
  local n  := 500
  local aFi:= ARRAY(n,FI_SPALTEN)
  local aZei
  local i  := 0

  DO WHILE i < 1000  // ! EOF() ich habe keine DBF
     ++i
     ? "Anfang I=",i
     //AADD(aFI,ARRAY(FI_SPALTEN))
     IF i > n
        ? "ADD 500, VORHER=",len(aFi)," NACHHER= "
        n += 500
        ASIZE(aFi,n)
        ?? len(aFi)
        inkey(1)
     ENDIF
     ? "Zuweisung ... nach ",i
     // zuerst Zeilenarray bilden
     aZei := { 1, 2, 3, 4, 5 }
     aFi[i] := aZei
     ? aFi[i]
  ENDDO
return
Gruß
Hubert
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von Martin Altmann »

Hallo Hubert,
wobei Du da jetzt aber den gleichen Fehler drin hast...
:oops: ich sehe gerade, dass Du unten ja anders zuweist, als Dieter.
Vergiss meinen Einwand - ist schon zu spät am Abend...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von Dieter »

Hallo Hubert,

vielen Dank für den Hinweis, dass ASIZE() in mehrdimensionalen Arrays nur ein NIL pro Zeile anfügt. Ich hab den Code jetzt wie folgt geändert:

Code: Alles auswählen

n=500
aFi:=ARRAY(n,FI_SPALTEN)
//aZei:=ARRAY(FI_SPALTEN)
i=0
DO WHILE !EOF()
  ++i
  //AADD(aFI,ARRAY(FI_SPALTEN))
  IF i>n
    n=n+500
    ASIZE(aFi,n)
    FOR j=i TO n
      aFi[j]:=ARRAY(FI_SPALTEN)
      //aFi[j]=aZei   //Fehler, da die Referenz von aZei kopiert wird
    NEXT
  ENDIF
  aFi[i,FI_BELEG_NR]=fin->BELEG_NR
  ...
Dieser Code funktioniert einwandfrei. :)
Leider ist er in unserem Netzwerk nicht schneller als das einfache AADD(). :(

@Martin
Dein Gefühl am späten Abend hat dich nicht getäuscht.
aFi := aZei ist nicht koscher
Trotzdem gilt mein Dank Hubert, der meinen Denkfehler bei ASIZE() aufgezeigt hat.
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von brandelh »

@Martin
Dein Gefühl am späten Abend hat dich nicht getäuscht.
aFi := aZei ist nicht koscher


das stimmt so nicht ;-)

da das Array aZei jeweils NEU gebildet wird, und danach nur für die Zuweisung herhalten muss,
ist gegen diese Zeile nichts einzuwenden ...

Code: Alles auswählen

// zuerst Zeilenarray bilden
     aZei := { 1, 2, 3, 4, 5 }
     aFi[i] := aZei
außer, dass sie umständlicher als deine neue ist :-)
Gruß
Hubert
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von Dieter »

Hallo Hubert,

da aZei ein Array ist, speichert aFi immer nur die Referenz von aZei. Deshalb überschreiben die nachfolgenden
aZei-Arrays die schon in aFi gespeicherten Zeilen. Es kommt zu unerwünschten Seiteneffekten, wobei die
ersten 500 Datensätze nicht betroffen sind. Deshalb sollte man Array-Anweisungen wie aFi := aZei immer ein
gesundes Mißtrauen entgegen bringen und diese möglichst vermeiden.
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von brandelh »

Hallo Dieter,

hast du das jetzt ausprobiert ?
Ich hatte im Beispiel ja immer den gleichen Inhalt,
Aber da in jedem Durchlauf mit aZei := {...} aZei ein neues Array zugewiesen wird,
werden keine Arrays doppelt verwendet.
Die Referenzen der Zeilen in aFi werden beim neuen Zuweisen freigegeben ...

Sicherlich hast du Recht, dass man mit Arrays und den enthaltenen Referenzen aufpassen muss,
aber das habe ich hier ja auch getan ;-)
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von brandelh »

Ich habe mal schnell den Quellcode abgeändert in der Zeile in der das Array gebildet wird:

Code: Alles auswählen

#define FI_SPALTEN 5

proc main
  local n  := 500
  local aFi:= ARRAY(n,FI_SPALTEN)
  local aZei
  local i  := 0

  DO WHILE i < 1000  // ! EOF() ich habe keine DBF
     ++i
     ? "Anfang I=",i
     //AADD(aFI,ARRAY(FI_SPALTEN))
     IF i > n
        ? "ADD 500, VORHER=",len(aFi)," NACHHER= "
        n += 500
        ASIZE(aFi,n)
        ?? len(aFi)
        inkey(1)
     ENDIF
     ? "Zuweisung ... nach ",i
     // zuerst Zeilenarray bilden
     aZei := { i, 10+i, 100+i, 1000+i, 10000+i }      // NUN mit eindeutigen Werten
     aFi[i] := aZei
     ? aFi[i]
  ENDDO
return
Hier das Ergebnis:

Code: Alles auswählen

...
{       992,       1002,       1092,       1992,      10992}
Anfang I=        993
Zuweisung ... nach         993
{       993,       1003,       1093,       1993,      10993}
Anfang I=        994
Zuweisung ... nach         994
{       994,       1004,       1094,       1994,      10994}
Anfang I=        995
Zuweisung ... nach         995
{       995,       1005,       1095,       1995,      10995}
Anfang I=        996
Zuweisung ... nach         996
{       996,       1006,       1096,       1996,      10996}
Anfang I=        997
Zuweisung ... nach         997
{       997,       1007,       1097,       1997,      10997}
Anfang I=        998
Zuweisung ... nach         998
{       998,       1008,       1098,       1998,      10998}
Anfang I=        999
Zuweisung ... nach         999
{       999,       1009,       1099,       1999,      10999}
Anfang I=       1000
Zuweisung ... nach        1000
{      1000,       1010,       1100,       2000,      11000}
Wäre eine Verkettung mit einem Array, müssten alle Zeilen gleich sein.

ABER deine Lösung mit array(...) ist natürlich eleganter !
Gruß
Hubert
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Re: Array in mehreren Etappen erzeugen [ERLEDIGT]

Beitrag von Dieter »

Hallo Hubert,
du machst dir aber immer ein Mühe... =D> =D>

In meinem Code wäre es tatsächlich zu den gefürchteten Seiteneffekten gekommen. Da du aber jeweils ein neues Array
für jede neue aFi-Zeile bildest, hast du wohl Recht. In der Praxis weiß man aber meistens nicht, wieviel Spalten das Array
haben wird. Deshalb werden festverdrahtete Arrays in der Form { } eher die Ausnahme bleiben.

Nochmals herzlichen Dank für deinen Tip mit ASIZE(), da hab ich mal wieder was dazu gelernt.
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Antworten