Pointer und #PB_Any direkt als MapKey verwenden

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
mk-soft
Beiträge: 3700
Registriert: 24.11.2004 13:12
Wohnort: Germany

Pointer und #PB_Any direkt als MapKey verwenden

Beitrag 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)
Zuletzt geändert von mk-soft am 26.02.2017 14:16, insgesamt 1-mal geändert.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag 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.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
mk-soft
Beiträge: 3700
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag von mk-soft »

Habe ich auch gerade festgestellt. Vermute auch das es an den Nullbytes liegt...
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3700
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag 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)
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag von Sicro »

Super! :allright:
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)
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
Bisonte
Beiträge: 2430
Registriert: 01.04.2007 20:18

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag von Bisonte »

Wo ist denn jetzt bei Map(Str(i)) und Map(Hex(i)) der unterschied ? Also weniger Schreibarbeit jedenfalls nicht...
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag von Sicro »

@Bisonte: Map(Hex(i)) ist schneller als Map(Str(i))
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
mk-soft
Beiträge: 3700
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag 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. :mrgreen:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag 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.
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6999
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Pointer und #PB_Any direkt als MapKey verwenden

Beitrag 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten