VB6: Arbeitsspeicher-'Verbrauch'

Hallo Alex,

so viele Daten, daß eine DB sinnvoll wäre sind das wohl nicht, wenn ich es richtig verstanden habe. Das soll wohl etwa so etwas wie eine gut überschaubare, transparente Ini werden.

Daß da verschiedene Datentypen hineinkommen habe ich gerade erst verstanden.

Thema Collection: Die wartet immer noch darauf, daß ich mich mal damit befasse. Damit kann ich nicht umgehen, ich bringe aus dem Kopf keinen Code zusammen, der eine Collection verwendet.

Gruß Rainer

Thema Collection: Die wartet immer noch darauf, daß ich mich
mal damit befasse. Damit kann ich nicht umgehen, ich bringe
aus dem Kopf keinen Code zusammen, der eine Collection
verwendet.

Hallo Rainer,

mal angenommen, in einer List (-box) stehen zig Einträge, etliche doppelt.
Du willst nun in einer „Liste“ alle unterschiedlichen Einträge haben.
Wie machst du das in einer Schleife?

Gruß
Reinhard

Hallo Reinhard,

darüber würde ich anfangen nachzudenken, wenn ich mehr weiß. :smile:
Ist sortieren erlaubt?

Gruß Rainer

Hallo Rainer,

darüber würde ich anfangen nachzudenken, wenn ich mehr weiß.

*hmmh* ich sehe das anders. Ich versuche über die Lösung von VB/VBA Problemen nachzudenken um auf die Lösung zu kommen.
Wenn ich das nur machen würde wenn ichh „Wissen“ hätte, wer da nie was draus geworden :smile:)

Ist sortieren erlaubt?

Von mir aus.

Ich will darauf hinaus, es existiert eine Liste mit zig Einträgen, nach EINER VB-Schleife hast du in einer anderen Liste, nennen wir sie mal eine Ansammlung, also in einer Collection jeden Eintrag nur einmal erwähnt, egal wie oft er in der Ausgangsliste vorkam.

Dazu, und nur dazu, benutze ich Collection. (Wozu die sonst noch gut ist entzieht sich meiner Kenntnis)

Ich weiß daß Collection prinzipiell langsam ist da sie mit Strings arbeitet und auch Zeitaufwand für die „innere“ Verwaltung braucht.

Für so 20.000 Einträge in einer Liste ist Collection schnell genug fürs Auge, Ergebnis ist „sofort“ vorhanden.

Z.B. so:

Sub Test()
Dim colC as new collection, C as long
On Error resume next 'wichtig
for C = 0 to List1.count
colc.add key:=list1(n), item:=list1(n)
next C
end sub

verzeih mir, ich habs nicht in VB getestet, du wirst da wahrscheinlich Anpassungen bei der Referenzierung der List1 vornehmen müssen.

Aber der Sinn kommt klar durch *denk*, so kommt man mit einer Schleife aus.
Daß innerbetrieblich die Collection in sich eine zweite Schleife startet um nachzuprüfen ob der neue Begriff schon vorhanden ist ist ja was anderes, denn da macht ja Collection genau das was du auch machst, nachprüfen in einer Schleife ob der Begriff schon enthalten ist.

Fazit, vom Code her ist es sehr einfach Collection zu benutzen um nur „Unikate“ zu ermitteln. Das geht mit einer Schleife.

Soweit ich weiß kriegt man das ohne Collection nur mit zwei Schleifen hin. Vom Code her schon aufwendiger, wenn auch halb so wild.

Fazit2, da beide Varianten nicht schwierig sind zu codieren, wäre ein Entscheidungsaspekt welche Variante man nutzt die Schnelligkeit der Codes.

Btw: Was mich auch irritiert, egal Excel-Vba-Foren, oder VB-Foren, Collections sieht man nahezu nie in den Codes.

Gruß
Reinhard

Gruß Rainer

1 Like

Hallo Reinhard,

*hmmh* ich sehe das anders. Ich versuche über die Lösung von
VB/VBA Problemen nachzudenken um auf die Lösung zu kommen.
Wenn ich das nur machen würde wenn ichh „Wissen“ hätte,
wer da nie was draus geworden :smile:)

*gg* Ich hatte doch nur gemeint, ich möchte das Problem kennen, bevor ich anfange, es zu lösen. :smile:

Ist sortieren erlaubt?

Von mir aus.

Dann wäre meine Lösung klar. Nicht EINE Schleife, aber … :smile:
Ab ins Array, dort sortieren, dann doppelte entfernen.

Ich weiß daß Collection prinzipiell langsam ist da sie mit
Strings arbeitet und auch Zeitaufwand für die „innere“
Verwaltung braucht.

Das habe ich auch gelesen. das ist auch der grund, warum ich mich noch nicht damit befasst habe. Ich vermute, meine Lösung wird schneller sein.

verzeih mir, ich habs nicht in VB getestet, du wirst da
wahrscheinlich Anpassungen bei der Referenzierung der
List1 vornehmen müssen.

Kein Problem, solche Kleinigkeiten bemerken wir doch gar nicht. :smile:
Ich bin auf das Ergebnis des Tests gespannt. 20 000 Zeilen ist OK, ich werde mal auch 20 000 Zeichen pro Zeile wählen.

Btw: Was mich auch irritiert, egal Excel-Vba-Foren, oder
VB-Foren, Collections sieht man nahezu nie in den Codes.

Mich wundert das nicht. Sie sind etwas schwerer zu handlen, dafür liest man immer, sie wären langsamer.

Wichtiger wäre mir, daß Collections auch Objekte aufnehmen können. ich hab’s nur noch nie benötigt, aber wenn, würde ich mich sofort mit Collections befassen … Wenn Du mir nicht schon Code geliefert hättest, weshalb ich das demnächst ohnehin tun werde. :smile: Ich will ja wissen, ob mein Code schneller ist. Am Ende habe ich dann Deinen auch verstanden und kann auch Collections verwenden.

Danke erst mal!

Gruß Rainer

Hallo Reinhard.

mal angenommen, in einer List (-box) stehen zig Einträge,
etliche doppelt.
Du willst nun in einer „Liste“ alle unterschiedlichen Einträge
haben.
Wie machst du das in einer Schleife?

Ich würde dazu einen temporären String deklarieren und bereits während des 1. Durchlaufs der Schleife den 1. Wert der Listbox in diesen String hineinschreiben mit

String = String & ListItem

Beim nächsten Durchlauf kann ich dann vorab mit der InStr-Funktion überprüfen, ob der nächste Wert vorher schon einmal existierte.

VG
Carsten

Hallo Reinhard,

ich bring’s nicht zum Laufen. Ich habe mal etwas daran herumgetippt, nur ein wenig die Syntax verändert, wie ich erwartet hätte, daß es für VB6 nötig wäre …

Private Sub Test()
 Dim colC As New Collection, C As Long
 On Error Resume Next 'wichtig
 For C = 0 to List1.ListCount - 1
 colC.add key = List1.List(n), item = List1.List(n)
 Next 
End Sub

Nein, passt so nicht. VB weiß nicht, was es mit ‚key‘ anfangen soll.
Für VB6 ist das nicht der korrekte Umgang mit der Collection.
Weil ich’s nicht verstehe, kann ich’s auch nicht freihändig ändern. :frowning:

Gruß Rainer

Hallo Rainer

ahhh, jetzt wird’s klar.

Ich war nur schreibfaul :smile:

Aber danke, über das was Du da machst habe ich mir noch nie
Gedanken gemacht. Ich hätte aus dem Hut nicht sagen können, od
das so möglich istm, hätte ich erst testen müssen.

In ein Variant-Array kann man also unterschiedliche Datentypen
gemischt schreiben. Sehr interessant …

OK, klar. Das geht dann natürlich nur mit Variant.

Das funktioniert so wirklich? Ich kann das kaum glauben, muss
ich testen. :smile: Wie weit hast Du das getestet? :Funktioniert das auch, wenn Felder leer bleiben?

Ja, das funktioniert astrein. Und es bleiben sogar eine Menge Felder frei [Arbeitsspeicherverschwendung, aber was kostet die Welt :wink:]. In der Tat speichere ich momentan nur einen einzigen Hex-Wert, habe aber dafür über 30 Long-Werte, z.B. für die ganzen Fensterpositionen der Formulare. Ich muß also immer darauf achten, daß „MainDataRows“ mit der Anzahl des am meisten verwendeten Datentyps übereinstimmt.

Wie bist Du darauf gekommen? Ich hätte mich das nicht getraut
und das anders, wohl viel komplizierter gemacht.

Ich hatte es vorher anders. Habe immer alles einzeln in die Datei geschrieben und einzeln gelesen. Das bedeutete aber auch: Jedesmal, wenn mir ein neuer Blödsinn einfiel, der gespeichert werden mußte, dann mußte auch eine neue Variable dafür deklariert werden; und ich mußte die Programmierung für das Lesen, für das Schreiben und für „Standard herstellen“ beim ersten Start der Anwendung anpassen.
Jetzt brauche ich nur noch „Standard herstellen“ anpassen und, falls notwendig, „MainDataRows“. Es erspart mir also Schreibarbeit beim Programmieren.

VG
Carsten

Hallo Carsten,

alles klar, alles verstanden.

Fazit: Du kommst um Variant nicht herum, weil Du den Datentyp bei der Deklaration noch gar nicht kennst. Eine Methode wüsste ich noch, aber die ist umständlicher und bringt Dir keine wesentlichen Vorteile.

Was die speicherverwaltung angeht … Alles klar? Oder doch noch ein beispielprogramm, das zeigt und erklärt, was VB da intern tut?

Man könnte mal ein Variant-Array erstellen, mit Werten und Strings füllen (nicht so viele, damit es übersichtlich bleibt) und dann die Speicheradressen und ihre Inhalte anzeigen, die VB für die Verwaltung verwendet.

Mit VarPtr(Variable) findet man die Adresse des Zeigers, mit StrPtr(Variable) den Inhalt dieser Adresse. Da steht dann die Adresse an der die Bytes des Strings im Speicher stehen.
Wenn man mag, kann man das mit CopyMemory in Long-Variablen kopieren und anzeigen.
Man kann also einen String an eine Variable übergeben, sich an den zeigern durch den Speicher hangeln und so die Zeichen im Speicher finden, aus dem Arbeitsspeicher in eine Variable kopieren und anzeigen.
Wenn man alles richtig verstanden hat, steht in der Anzeige wieder der ursprüngliche String. :smile:

Zum besseren Verständnis habe ich das vor ein paar Monaten mal versucht, hat funktioniert. Das ergebnis war dann eine recht flinke Sortierfunktion auf der basis von Quicksort, aber unter Verwendung einer DLL, die mir Semjon (CMБ) in Assembler geschrieben hat.
Dabei müssen Strings im Array vertauscht werden. Ich lasse die Strings dort stehen, wo sie sind, tausche aber die Zeiger im Array ‚VarPtr‘.

Eventuell hilft Dir das ja, besser zu verstehen, was VB da treibt, auch wenn Du es nicht testen kannst, weil Dir die DLL fehlt.

Gruß Rainer

Option Explicit

Private Declare Sub SwapMemoryBytewise Lib "ISWAP.dll" \_
 (ByVal pDst As Long, ByVal pSrc As Long, ByVal ByteLen As Long)

Dim Feld(0 To 1000) As String

Private Sub Command1\_Click()
 Dim X As Long
 Call QuickSort(LBound(Feld), UBound(Feld))
End Sub

Private Sub QuickSort(ByVal LB As Long, ByVal UB As Long)
 Dim P1 As Long, P2 As Long, Ref As String, TEMP As String

 P1 = LB
 P2 = UB
 Ref = Feld((P1 + P2) / 2)

 Do
 Do While (Feld(P1) Ref)
 P2 = P2 - 1
 Loop

 If P1 P2)

 If LB 

Hallo Rainer.

Was die speicherverwaltung angeht … Alles klar? Oder doch
noch ein beispielprogramm, das zeigt und erklärt, was VB da
intern tut?

Das wäre super. Vielen Dank.

VG
Carsten

während des 1. Durchlaufs der Schleife den 1. Wert der Listbox
in diesen String hineinschreiben mit

String =
String & ListItem

Beim nächsten Durchlauf kann ich
dann vorab mit der InStr-Funktion überprüfen, ob der nächste
Wert vorher schon einmal existierte.

Hallo Carsten,

okay, das geht, wenn es auch so nicht sicher wäre, sicherer ist dann sowas:

String = String & „#@“ & ListItem & „#@“

Gruß
Reinhard

Hallo Rainer,

so läuft das in VB5.

Die Form hat zwei Listbooxen und einen Button

Option Explicit
'
Private Sub Command1\_Click()
Dim colC As New Collection, C As Long
On Error Resume Next 'wichtig
For C = 0 To List1.ListCount - 1
 colC.Add Key:=List1.List(C), Item:=List1.List(C)
 If Err.Number = 0 Then List2.AddItem colC(colC.Count)
Next
End Sub
'
Private Sub Form\_Load()
Dim N As Long
For N = 1 To 10
 List1.AddItem N Mod 4
Next N
End Sub

Gruß
Reinhard

Hallo Carsten,

dann leg Dir mal eine Liste und einen Commandbutton auf die Form …

Gruß Rainer

Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias \_
 "RtlMoveMemory" \_
 (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Dim Arr() As String

Private Sub Command1\_Click()
 Dim n As Integer, i As Integer, txt As String, v As Long, w As Long, Ze As Integer

 ReDim Arr(2)

 Arr(0) = "Test"
 Arr(1) = "Versuch"
 Arr(2) = "Probe"

 For n = 0 To 2
 txt = "Inhalt: " + CStr(Arr(n))
 List1.AddItem txt
 Next

 For n = 0 To 2
 txt = "Zeigeradresse: " + CStr(VarPtr(Arr(n))) + " = " + Hex(VarPtr(Arr(n)))
 List1.AddItem txt
 Next

 For n = 0 To 2
 txt = "Zieladresse: " + CStr(StrPtr(Arr(n))) + " = " + Hex(StrPtr(Arr(n)))
 List1.AddItem txt
 Next

 List1.AddItem "Speicherinhalt der Adressen, in denen die Zeiger stehen"
 For n = 0 To 2
 CopyMemory ByVal (VarPtr(v)), VarPtr(Arr(n)), 8&
 List1.AddItem CStr(v) + " = " + Hex(v)
 Next

 List1.AddItem "Und dort steht: "

 For n = 0 To 2
 CopyMemory ByVal (VarPtr(v)), VarPtr(Arr(n)), 8&
 CopyMemory ByVal (VarPtr(w)), ByVal (v), 8&
 List1.AddItem CStr(w) + " = " + Hex(w)
 Next

 List1.AddItem "Und jetzt den speicher an der gefundenen Adresse auslesen!"

 For n = 0 To 2
 CopyMemory ByVal (VarPtr(v)), VarPtr(Arr(n)), 8&
 CopyMemory ByVal (VarPtr(w)), ByVal (v), 8&
 i = 0
 txt = ""
 Do
 CopyMemory ByVal (VarPtr(Ze)), ByVal (w + i), 2& ' 0 Then
 txt = txt + Chr(Ze)
 End If
 i = i + 2
 Loop While Ze 0
 List1.AddItem txt
 Next

End Sub