Seite 1 von 3
Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 12:54
von mk-soft
Ich selber arbeite gerne mit Maps um die zurückgegebene ID bei Verwendung von '#PB_Any' oder von Pointer zu verwalten.
Es muss aber jedesmal erst in eine String gewandelt werden.
Dazu hatte ich heute Morgen eine Idee. Der Integer ist bei x86 immer vier byte lang und bei x64 immer acht Byte lang.
Diesen kann man auch direkt als String betrachten und als MapKey übergeben. Muss ja nicht als Mensch leserlich sein.
So geht es leider nicht!
Habe Nullbytefolge nicht bedacht und führt somit zur Kollision.
Lasse es aber zur Erinnerung stehen.
Code: Alles auswählen
Structure udtMapKeyIndex
StructureUnion
i.i
s.s{SizeOf(integer)}
EndStructureUnion
EndStructure
Define Gadget.udtMapKeyIndex
NewMap Value.i()
NewMap Value2.i()
start = ElapsedMilliseconds()
For i = 1 To 200000
Gadget\i = i
Value(Gadget\s) = i
Next
time1 = ElapsedMilliseconds() - start
start = ElapsedMilliseconds()
For i = 1 To 200000
Gadget\i = i
Value(Str(i)) = i
Next
time2 = ElapsedMilliseconds() - start
r1.s = "Zeit für kleine Zahlen" + #LF$ + "Struct: " + Str(time1) + #LF$ + "String: " + Str(time2)
ClearMap(Value())
start = ElapsedMilliseconds()
For i = 100000000 To 100200000
Gadget\i = i
Value(Gadget\s) = i
Next
time1 = ElapsedMilliseconds() - start
start = ElapsedMilliseconds()
For i = 100000000 To 100200000
Gadget\i = i
Value(Str(i)) = i
Next
time2 = ElapsedMilliseconds() - start
r1 + #LF$ + #LF$ + "Zeit für große Zahlen (Pointer, #PB_Any)" + #LF$ + "Struct: " + Str(time1) + #LF$ + "String: " + Str(time2)
MessageRequester("Result", r1)
Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 13:27
von Sicro
Coole Idee, aber es entstehen Kollisionen:
Code: Alles auswählen
Structure udtMapKeyIndex
StructureUnion
i.i
s.s{SizeOf(integer)}
EndStructureUnion
EndStructure
Define Gadget.udtMapKeyIndex
Define NewMap Collision()
;For i = 0 To 9223372036854775807 ; Max Quad-Wert
For i = 0 To 2147483647 ; Max Long-Wert
Gadget\i = i
Collision(Gadget\s) + 1
If Collision() > 1
Output$ = MapKey(Collision()) + " -- Counter: " + Str(Collision())
Break
EndIf
Next
MessageRequester("Kollision", Output$)
Ich habe nicht geprüft, warum die entstehen, aber vermutlich wegen den Null-Bytes, die zu vorzeitiger String-Terminierung führen.
Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 13:48
von mk-soft
Habe ich auch gerade festgestellt. Vermute auch das es an den Nullbytes liegt...
Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 14:18
von mk-soft
Geht also nicht...
Aber wenn man statt den Wert als String den Wert als Hex übergibt geht es schneller
Code: Alles auswählen
Define r1.s
NewMap ValueH.i()
NewMap ValueS.i()
start = ElapsedMilliseconds()
For i = 1 To 200000
ValueH(Hex(i)) = i
Next
time1 = ElapsedMilliseconds() - start
start = ElapsedMilliseconds()
For i = 1 To 200000
ValueS(Str(i)) = i
Next
time2 = ElapsedMilliseconds() - start
r1 = "Zeit für kleine Zahlen" + #LF$ + "Hex: " + Str(time1) + #LF$ + "String: " + Str(time2)
r1 + #LF$ + "Count of Map Hex: " + Str(MapSize(ValueH()))
r1 + #LF$ + "Count of Map String: " + Str(MapSize(ValueS()))
ClearMap(ValueH())
ClearMap(ValueS())
start = ElapsedMilliseconds()
For i = 100000001 To 100200000
ValueH(Hex(i)) = i
Next
time1 = ElapsedMilliseconds() - start
start = ElapsedMilliseconds()
For i = 100000001 To 100200000
ValueS(Str(i)) = i
Next
time2 = ElapsedMilliseconds() - start
r1 + #LF$ + #LF$ + "Zeit für große Zahlen (Pointer, #PB_Any)" + #LF$ + "Hex: " + Str(time1) + #LF$ + "String: " + Str(time2)
r1 + #LF$ + "Count of Map Hex: " + Str(MapSize(ValueH()))
r1 + #LF$ + "Count of Map String: " + Str(MapSize(ValueS()))
MessageRequester("Result", r1)
Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 15:44
von Sicro
Super!

Dann nehme ich in zukünftigen Codes die Hex-Variante.
Hier noch ein umfangreicherer Test:
Code: Alles auswählen
Define r1.s
NewMap ValueH.i()
NewMap ValueS.i()
start = ElapsedMilliseconds()
For i = 1 To 200000
ValueH(Hex(i)) = i
Next
ForEach ValueH()
a = Val("$"+MapKey(ValueH()))
Next
time1 = ElapsedMilliseconds() - start
start = ElapsedMilliseconds()
For i = 1 To 200000
ValueS(Str(i)) = i
Next
ForEach ValueS()
a = Val(MapKey(ValueS()))
Next
time2 = ElapsedMilliseconds() - start
r1 = "Zeit für kleine Zahlen" + #LF$ + "Hex: " + Str(time1) + #LF$ + "String: " + Str(time2)
r1 + #LF$ + "Count of Map Hex: " + Str(MapSize(ValueH()))
r1 + #LF$ + "Count of Map String: " + Str(MapSize(ValueS()))
ClearMap(ValueH())
ClearMap(ValueS())
start = ElapsedMilliseconds()
For i = 100000001 To 100200000
ValueH(Hex(i)) = i
Next
ForEach ValueH()
a = Val("$"+MapKey(ValueH()))
Next
time1 = ElapsedMilliseconds() - start
start = ElapsedMilliseconds()
For i = 100000001 To 100200000
ValueS(Str(i)) = i
Next
ForEach ValueS()
a = Val(MapKey(ValueS()))
Next
time2 = ElapsedMilliseconds() - start
r1 + #LF$ + #LF$ + "Zeit für große Zahlen (Pointer, #PB_Any)" + #LF$ + "Hex: " + Str(time1) + #LF$ + "String: " + Str(time2)
r1 + #LF$ + "Count of Map Hex: " + Str(MapSize(ValueH()))
r1 + #LF$ + "Count of Map String: " + Str(MapSize(ValueS()))
MessageRequester("Result", r1)
Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 18:47
von Bisonte
Wo ist denn jetzt bei Map(Str(i)) und Map(Hex(i)) der unterschied ? Also weniger Schreibarbeit jedenfalls nicht...
Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 19:27
von Sicro
@Bisonte: Map(Hex(i)) ist schneller als Map(Str(i))
Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 19:33
von mk-soft
In meiner ersten Idee war leider ein Gedankenfehler.
Weniger Schreibarbeit hat man so leider auch nicht mehr. Es spart aber ein paar Micro-Sekunden.

Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 20:46
von #NULL
Bisonte hat geschrieben:Wo ist denn jetzt bei Map(Str(i)) und Map(Hex(i)) der unterschied ? Also weniger Schreibarbeit jedenfalls nicht...
Hex() ist zwar etwas langsamer als Str() aber der für i resultierende string ist bei Hex kürzer, besonders je grösser i ist. und bei kürzerem map-key geht das hashing schneller schätze ich mal.
Re: Pointer und #PB_Any direkt als MapKey verwenden
Verfasst: 26.02.2017 20:48
von STARGÅTE
@All:
Bei euer großen Maps solltet ihr vielleicht die Anzahl der Slots vergrößern, sonst sind das ehr Listen (von der Suchgeschwindigkeit)
@mk-soft:
Tut mir leider das ist nachfragen muss, aber mir erschließt sich der Sinn nicht ganz.
Du speicherst die ID/Pointer in einem MapElement unter dem Key ID/Pointer? Warum?
Wenn du die ID kennst, warum dann über die Map die ID ermitteln?
Vielleicht ist ja das Beispiel einfach nur unglücklich gewählt, aber dann wäre ein "sinnvolleres" Beispiel interessant.