Wie größere Dateien laden?

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

bmurray

Betreff: Wie größere Dateien laden?

BeitragMi, Jun 10, 2020 16:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Sagen wir in meinem Spiel gibt es 200 Länder, etwa 5.000 Regionen (Bundesländer, Kantone, Staaten, etc., also kleinere Verwaltungseinheiten) und 50.000 Städte. Jede Stadt hat 12 Attribute (Name, Land, Region, Einwohnerzahl, Längen- und Breitengrad, etc.). In meinen Programmen hatte ich bisher alles immer in eigenen Dateien gespeichert (also laender.dat, regionen.dat und staedte.dat). Wenn ich diese Dateien nun in meinem Spiel lade, dann dauert das ziemlich lange, etwa 13 Sekunden. Die Dateien sind nicht groß, zusammen etwa 3 MB. Die Laderoutine sind dann so aus:

Code: [AUSKLAPPEN]
 
Local datei:TStream = OpenFile("datenbank\staedte.dat")
Local wstadt:tStadt
   While Eof(datei) <> 1
      wstadt = New tStadt
      wstadt.name = ReadStringBB(datei)
      wstadt.id = ReadInt(datei)
      wstadt.land = ReadInt(datei)
      wstadt.gebiet = ReadInt(datei)
      wstadt.sprache = ReadInt(datei)
      wstadt.attraktivitaet = ReadInt(datei)
      wstadt.einwohner = ReadInt(datei)
      wstadt.einwohnerKat = ReadInt(datei)
      wstadt.breitengrad = ReadFloat(datei)
      wstadt.laengengrad = ReadFloat(datei)
      wstadt.hoehe = ReadInt(datei)
      wstadt.wetter = ReadInt(datei)            
      listeStaedte.AddLast(wstadt)
   Wend
        CloseFile(datei)


Ziemlich simpel, ich weiß. Gibt es einen schnelleren und besseren Weg, größere Daten zu laden?

count-doku

BeitragDo, Jun 11, 2020 7:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe schon länger nichts mehr mit BlitzMax gemacht (zum Glück), könnte mir aber vorstellen, dass es schneller wäre entweder a) die ganze Datei auf einmal in den RAM zu laden und von dort weiter zu zerstückeln oder b) zumindest immer eine ganze Stadt auf einmal zu laden.

a)
Du benutzt direkt nach dem öffnen der Datei CopyStream (oder ähnliches) und kopierst die komplette Datei in einen RAM Stream oder Bank Stream (natürlich vorher die Bank erstellen oder Speicher reservieren). Danach benutzt du die gleiche Funktion wie jetzt um die Daten aus dem RAM zu lesen (dürfte schneller sein).

b)
Ich weiß nicht, was dein ReadStringBB macht, aber abgesehen von dem vermutlich variable length string am Anfang ist die Größe deiner Stadtinfo ja fest gegeben (4Byte pro Int und Float), also kannst du z.B. erst nur den Namen lesen (ReadString) und dann CopyBytes benutzen um die restlichen Infos in einen RAM Stream oder Bank Stream zu kopieren.

Natürlich kann man a&b auch kombinieren. Dein Ziel sollte es jedenfalls sein, viele kleine Lesezugriffe auf die HDD durch wenige größere abzulösen. Und 3MB kannst du problemlos vollständig in den RAM laden.

bmurray

BeitragDo, Jun 11, 2020 11:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank, ich habe es mir Variante a) probiert. Allerdings habe ich noch nie mit tBank programmiert. Mein erster Versuch sieht so aus:

Code: [AUSKLAPPEN]
Local bank:TBank = CreateBank()
   Local bankstream:TBankStream = CreateBankStream(bank)
   CopyStream(datei, bankstream)

   While Eof(bankstream) <> 1
      
      wstadt = New tStadt
      wstadt.name = ReadStringBB(bankstream)
      wstadt.id = ReadInt(bankstream)
      wstadt.land = ReadInt(bankstream)
      wstadt.gebiet = ReadInt(bankstream)
      wstadt.sprache = ReadInt(bankstream)
      wstadt.attraktivitaet = ReadInt(bankstream)
      wstadt.einwohner = ReadInt(bankstream)
      wstadt.einwohnerKat = ReadInt(bankstream)
      wstadt.breitengrad = ReadFloat(bankstream)
      wstadt.laengengrad = ReadFloat(bankstream)
      wstadt.hoehe = ReadInt(bankstream)
      wstadt.wetter = ReadInt(bankstream)
      stadt:+[wstadt]            
      listeStaedte.AddLast(wstadt)
   Wend


Allerdings funktioniert dann EoF nicht, bzw. er liest die Daten nicht aus. In der Hilfe steht ja, dass man tBankStreams auch dort verwenden könne, wo tStreams erwartet werden, weswegen ich gerade unsicher bin, wie tBankStreams in meinem Fall gelesen werden können.


count-doku hat Folgendes geschrieben:
Ich weiß nicht, was dein ReadStringBB macht
. Der liest einfach nur den String und die Länge des Strings (was ReadString wohl braucht, und mit dem Pendant WriteStringBB gespeichert wird):

Code: [AUSKLAPPEN]
Function ReadStringBB:String(f:TStream)
   Local n:Int = ReadInt(f)
   Return ReadString(f, n)
End Function


count-doku hat Folgendes geschrieben:
Ich habe schon länger nichts mehr mit BlitzMax gemacht (zum Glück)


Darf ich fragen, wieso? Ich als Amateur-Hobby-Programmierer finde BlitzMax genial, gerade weil es so simpel ist. Immerhin konnte ich mein erstes Spiel auf Steam veröffentlichen, mit einer "komplexeren" Sprache hätte ich dies mangels ausreichender Programmierkenntnisse wohl nicht geschafft. Oder gibt es - unabhängig von den eigenen Programmierfähigkeiten - einen triftigen Grund, BlitzMax nicht mehr zu nutzen? (Ich frage deswegen, weil ich mir überlege, C++ zu lernen, bin allerdings nicht sicher, ob sich der Zeitaufwand lohnt, in Anbetracht dessen, dass ich mit BlitzMax eigentlich sehr gut klar komme)

count-doku

BeitragDo, Jun 11, 2020 19:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Allerdings funktioniert dann EoF nicht, bzw. er liest die Daten nicht aus. In der Hilfe steht ja, dass man tBankStreams auch dort verwenden könne, wo tStreams erwartet werden, weswegen ich gerade unsicher bin, wie tBankStreams in meinem Fall gelesen werden können.

Dein Code sieht schon gut aus. Du musst nur bedenken, dass nach CopyStream der Stream Zeiger am Ende vom Stream steht (daher ist EOF sofort true). Du musst also nach dem CopyStream mit SeekStream wieder an den Anfang von der Bank springen.

Zitat:
count-doku hat Folgendes geschrieben:
Zitat:
Ich weiß nicht, was dein ReadStringBB macht

. Der liest einfach nur den String und die Länge des Strings (was ReadString wohl braucht, und mit dem Pendant WriteStringBB gespeichert wird)

Ok.

Zitat:
count-doku hat Folgendes geschrieben:
Zitat:
Ich habe schon länger nichts mehr mit BlitzMax gemacht (zum Glück)

War vielleicht etwas negativ. Im Prinzip ist BlitzMax (wie alle Blitzsprachen) für manche Sachen recht einfach. (3D Grafik bei B3D z.B., OpenGL mit BMax). Aber in anderen Sachen hat es keine Chance gegen Sprachen wie Java, C++ oder C#.
Dein Dateien laden ist ein prima Beispiel. In C# könnte ich die Instanzen der TStadt Klasse mit wenigen Zeilen Code direkt in ein XML oder Json serialisieren oder wieder laden. Ohne mir Gedanken über den Rest zu machen. Wenn es klein sein soll gibts den BinarySerializer, der genau das macht was du gerade per Hand programmierst. Auch ganze Objekte per Netzwerk (mit Verschlüsselung) zu übertragen ist mit Dingen wie Windows Communication Foundation (WCF) sehr einfach und flexibel. Außerdem wäre ich vorsichtig, wie lange die Blitz Sprachen noch laufen (auch wenn da BMax vermutlich besser dran ist).
Für kleinere 2D Spiele, stimme ich dir aber zu, ist BMax immer noch geeignet.

Zurück zu deinem Problem:
Ich habe mal ein Testprogramm geschrieben, wo ich die unterschiedlichen Ansätze probiert habe. (Siehe unten).
Leider dauert alles ca. gleich lang. Ich denke nochmal drüber nach, aber momentan kenne ich auch keinen schnelleren weg.

Meine Testdatei war am Ende ungefähr 28MB groß, und das Laden dauert:
BlitzMax: [AUSKLAPPEN]
'
' Old approach:
' Generating took: 497ms
' Saving took:1246ms
' Loading took: 9086ms
'
' New approach Bank:
' Generating took: 504ms
' Saving took: 1233ms
' Getting file took: 7762ms
' New loading (total) took: 9337ms
'
' New approach Ram
' Generating took: 493ms
' Saving took: 1237ms
' Getting file took: 7632ms
' New loading total took: 8885ms


BlitzMax: [AUSKLAPPEN]
SuperStrict
Framework brl.blitz
Import brl.filesystem
Import brl.stream
Import brl.linkedlist
Import brl.random
Import brl.standardio
Import brl.ramstream

'
' Old approach:
' Generating took: 497ms
' Saving took:1246ms
' Loading took: 9086ms
'
' New approach Bank:
' Generating took: 504ms
' Saving took: 1233ms
' Getting file took: 7762ms
' New loading (total) took: 9337ms
'
' New approach Ram
' Generating took: 493ms
' Saving took: 1237ms
' Getting file took: 7632ms
' New loading total took: 8885ms




' Define TStadt Type for sample data
Type TStadt
Global list:TList = CreateList()

Field name:String
Field id:Int
Field land:Int
Field gebiet:Int
End Type

Local time:Long = MilliSecs()

' Generate 5 sample cities
For Local i:Int = 0 To 1000000
Local stadt:TStadt = New TStadt

stadt.name = "Stadt " + Rand(0, 10000000)
stadt.id = i
stadt.land = i / 2
stadt.gebiet = i * 2

TStadt.list.AddLast(stadt)
Next

Print "Generating took: " + (MilliSecs() - time) + "ms"

time = MilliSecs()
' Save sample data
Local file:TStream = WriteStream(".\testdata.dat")
For Local stadt:TStadt = EachIn TStadt.list
WriteStringBB(file, stadt.name)
file.WriteInt(stadt.id)
file.WriteInt(stadt.land)
file.WriteInt(stadt.gebiet)
Next
file.Close()

Print "Saving took: " + (MilliSecs() - time) + "ms"

' Clear all data in city list
TStadt.list.Clear()

' only use one at a time and always regenerate testdata to not use memory caching
'OldLoad()
'NewLoadBank()
NewLoadRam()



Function NewLoadBank()
Local time:Long = MilliSecs()

Local file:TStream = ReadStream(".\testdata.dat")
Local bank:TBank = CreateBank(file.Size()) ' Init bank in filesize this prevents us from having to do resizing later on (although bank should auto resize)
Local bankStream:TBankStream = CreateBankStream(bank)
CopyStream(file, bankStream) ' This puts us at the end of the stream!
file.Close()

Print "Getting file took: " + (MilliSecs() - time) + "ms"

' So remember to use seek to get to the beginning again
bankStream.Seek(0)

While Not Eof(bankStream)
Local stadt:TStadt = New TStadt

stadt.name = ReadStringBB(bankStream)
stadt.id = bankStream.ReadInt()
stadt.land = bankStream.ReadInt()
stadt.gebiet = bankStream.ReadInt()

TStadt.list.AddLast(stadt)
Wend

bankStream.Close()

Print "New loading total took: " + (MilliSecs() - time) + "ms"
End Function

Function NewLoadRam()
Local time:Long = MilliSecs()

Local file:TStream = ReadStream(".\testdata.dat")
Local buf:Byte[] = New Byte[file.Size()]
Local ramStream:TRamStream = CreateRamStream(buf, file.Size(), 1, 1)
CopyStream(file, ramStream) ' This puts us at the end of the stream!
file.Close()

Print "Getting file took: " + (MilliSecs() - time) + "ms"

' So remember to use seek to get to the beginning again
ramStream.Seek(0)

While Not Eof(ramStream)
Local stadt:TStadt = New TStadt

stadt.name = ReadStringBB(ramStream)
stadt.id = ramStream.ReadInt()
stadt.land = ramStream.ReadInt()
stadt.gebiet = ramStream.ReadInt()

TStadt.list.AddLast(stadt)
Wend

ramStream.Close()

Print "New loading total took: " + (MilliSecs() - time) + "ms"
End Function



Function OldLoad()
Local time:Long = MilliSecs()

Local file:TStream = ReadStream(".\testdata.dat")

While Not Eof(file)
Local stadt:TStadt = New TStadt

stadt.name = ReadStringBB(file)
stadt.id = file.ReadInt()
stadt.land = file.ReadInt()
stadt.gebiet = file.ReadInt()

TStadt.list.AddLast(stadt)
Wend

file.Close()

Print "Old loading took: " + (MilliSecs() - time) + "ms"

End Function



Function ReadStringBB:String(f:TStream)
Local n:Int = f.ReadInt()
Return f.ReadString(n)
End Function
Function WriteStringBB(f:TStream, str:String)
Local n:Int = str.Length
f.WriteInt(n)
f.WriteString(str)
End Function

bmurray

BeitragSa, Jun 13, 2020 9:42
Antworten mit Zitat
Benutzer-Profile anzeigen
count-doku hat Folgendes geschrieben:
Zitat:
Allerdings funktioniert dann EoF nicht, bzw. er liest die Daten nicht aus. In der Hilfe steht ja, dass man tBankStreams auch dort verwenden könne, wo tStreams erwartet werden, weswegen ich gerade unsicher bin, wie tBankStreams in meinem Fall gelesen werden können.

Dein Code sieht schon gut aus. Du musst nur bedenken, dass nach CopyStream der Stream Zeiger am Ende vom Stream steht (daher ist EOF sofort true). Du musst also nach dem CopyStream mit SeekStream wieder an den Anfang von der Bank springen.


Ohhhh, danke dir! Ja, jetzt klappt's!

Zitat:

War vielleicht etwas negativ. Im Prinzip ist BlitzMax (wie alle Blitzsprachen) für manche Sachen recht einfach. (3D Grafik bei B3D z.B., OpenGL mit BMax). Aber in anderen Sachen hat es keine Chance gegen Sprachen wie Java, C++ oder C#.
Dein Dateien laden ist ein prima Beispiel. In C# könnte ich die Instanzen der TStadt Klasse mit wenigen Zeilen Code direkt in ein XML oder Json serialisieren oder wieder laden. Ohne mir Gedanken über den Rest zu machen. Wenn es klein sein soll gibts den BinarySerializer, der genau das macht was du gerade per Hand programmierst. Auch ganze Objekte per Netzwerk (mit Verschlüsselung) zu übertragen ist mit Dingen wie Windows Communication Foundation (WCF) sehr einfach und flexibel. Außerdem wäre ich vorsichtig, wie lange die Blitz Sprachen noch laufen (auch wenn da BMax vermutlich besser dran ist).
Für kleinere 2D Spiele, stimme ich dir aber zu, ist BMax immer noch geeignet.


Meine größte Sorge ist auch, dass BMax auf künftigen Betriebssystemen nicht mehr läuft. Kann man da abschätzen, wie da die Chancen stehen werden? Ich arbeite gerade am Nachfolger meines Spiels, wenn es absehbar ist, dass das mit BMax irgendwann nicht mehr läuft, würde ich früher auf eine modernere Sprache umsteigen (wohl C++).

Zitat:

Zurück zu deinem Problem:
Ich habe mal ein Testprogramm geschrieben, wo ich die unterschiedlichen Ansätze probiert habe. (Siehe unten).
Leider dauert alles ca. gleich lang. Ich denke nochmal drüber nach, aber momentan kenne ich auch keinen schnelleren weg.


Ok, dann muss ich wohl akzeptieren, dass es nicht schneller geht. Vielen Dank für Deine Hilfe!
 

CO2

ehemals "SirMO"

BeitragSa, Jun 13, 2020 14:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallöchen,

Ein kurzer Hinweis noch, einfach weil es bisher nicht explizit genannt wurde: Kommen die 13 Sekunden aus einem Debug, oder einem Release-Build? Ich frage mich, weil ich damals, als ich mein Spiel noch in BlitzMax programmiert hatte, eine Tilemap hatte, die unoptimiert gespeichert wurde. Die Datei war etwa 100 MB groß, da dauerte das Laden der Daten auch so 15 bis 20 Sekunden im Debug (Dabei wurden 5000 x 5000 Tile-Objekte zusammengebaut, bestehend jeweils aus mehreren Ints, Strings und einem Stringarray). Im Release-Modus war die ganze Aktion dann schon nach etwa 1 bis 5 Sekunden abgeschlossen. Ich habe den Code gerade nicht zur Hand, der ist auf der Platte von meinem alten PC, aber ich habe das Laden ähnlich wie Du gemacht.

Ich habe die BlitzMax-Syntax nicht mehr auf dem Schirm, aber was macht die Zeile stadt:+[wstadt]? Embarassed Very Happy
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti

DAK

BeitragSo, Jun 14, 2020 10:11
Antworten mit Zitat
Benutzer-Profile anzeigen
bmurray hat Folgendes geschrieben:

Meine größte Sorge ist auch, dass BMax auf künftigen Betriebssystemen nicht mehr läuft. Kann man da abschätzen, wie da die Chancen stehen werden? Ich arbeite gerade am Nachfolger meines Spiels, wenn es absehbar ist, dass das mit BMax irgendwann nicht mehr läuft, würde ich früher auf eine modernere Sprache umsteigen (wohl C++).


BMax schaut da besser aus als BB. Es verwendet zumindest DirectX 9 und OpenGL 2.1. Beides schon schwer veraltet, aber beides noch akzeptabel unterstützt (im Gegensatz zu dem DirectX 7 von BB).
OpenGL ist generell sehr gut im Supporten von alten Versionen (Open Source sei Dank), da kann man sich noch ein paar Jahre drauf verlassen.

Ein anderer großer Vorteil von BMax über BB ist, dass die Engine nicht fix mit der Sprache verdrahtet ist, und sich dank dem Modulsystem vergleichsweise leicht austauschen lässt. Das heißt, selbst wenn DX9/OGL2.1 nicht mehr unterstützt wird, sollte es machbar sein, BMax weiter zu verwenden.

Solange man BMax hauptsächlich auf Windows verwenden will, ist der Compiler auch noch eine Weile mit Windows kompatibel. Was ich mitbekommen hab, schaut es mit Linux nicht so rosig aus. Mac hab ich keine Ahnung.

BMax NG ist auch gut dabei, die Sprache kompatibel zu halten.

Was BMax eher sterben lässt, ist die mangelnde Community. Für einen Hobbyprogrammierer der hauptsächlich Kleinzeug macht, ist das noch ok. Aber wenn man mal was Größeres oder Komplizierteres vor sich hat, dann ist BMax einfach nicht die richtige Wahl.

Das fängt bei der Menge der Leute die Fragen beantworten können an, und hört bei den Modulen und Bibliotheken auf.

Wenn du eine Frage in BMax hast, kannst du sie im Grunde nur hier stellen und kriegst dann potentiell von 10 ehemaligen BMax-Programmierern eine Antwort alla "Hab ich schon seit 10 Jahren nicht mehr verwendet, aber eventuell könnte es grob so gehen".

Wenn du zu Python/Java/C++/... eine Frage hast, dann stellst du sie auf Stackoverflow, und 5 Minuten später ist deine Frage als Duplikat geschlossen, weil sie schon fünf Mal beantwortet wurde Wink

Was die Bibliotheken angeht: Wenn du was Komplexeres brauchst, dann kannst du mal in alten Forenbeiträgen nach noch nicht toten Links graben und vielleicht kriegst du etwas, was vor 5-10 Jahren geschrieben wurde und wo der Autor nicht mehr auffindbar ist.

Bei Python/Java/C++/... gibt es entweder eine Appstore-Artige Paketverwaltung in der du tausende aktuelle Module mit einem Befehl runterladen und installieren kannst, oder es gibt zumindest auf Github irrsinnig viele Pakete. Wenn man z.B. sowas simples wie HTTPS mit einer modernen TLS-Version auf BlitzMax haben will, kann man schon schnell daran stecken bleiben.

C++ würde ich btw. nur dann lernen, wenn du einen ganz spezifischen Grund dafür hast. Wenn du "einfach so" entwickeln willst, dann würd ich dir eher zu Java oder Python für General Purpose Programming raten, oder zu Unity für Spieleentwicklung.
Gewinner der 6. und der 68. BlitzCodeCompo

Trust

BeitragSo, Jun 14, 2020 11:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich würde dir zumindest empfehlen auf Blitzmax NG umzusteigen. Da bekommst du einige Features dazu, die in anderen Sprachen schon lange Standard sind. Methodenüberladung, eine vernünftige Konstruktor Syntax, Interfaces etc. . Dazu ist C++ das Backend, dh. du kannst dir den Output anschauen bzw. leichter Änderungen vornehmen. Besonders beim Erstellen von dlls praktisch.
Gleich auf C++ umzusteigen würde ich vielleicht nicht empfehlen, zumindest nicht als kleiner Indi- /Hobbyentwickler. Würde da wenn eher noch sowas wie Haxe empfehlen, hat mehrere Backends (dadurch Plattform unabhängig), ist beliebt und die Sprache ist recht einfach (ähnelt C#). Oder, wenn es nicht auf eine Sprache beschränkt ist, vielleicht komplett ein Authorensystem verwenden wie Godot oder Unity.

Und ein kleiner Hinweis:
BlitzMax: [AUSKLAPPEN]
While Eof(datei) <> 1

Das geht zwar, ist aber vom Style her nicht schön.
IdR. liefert Eof einen Bool (in Bmax zwar einen Int da es Bool nicht gibt Rolling Eyes ) dh. boolsche Werte gegen eine "magic number" zu Überprüfen ist schlechter Stil... und geht auch nur in BMax da es Bool nicht gibt (alles was nicht 0 ist, ist True)
Besser wäre es entweder auf True/False zu prüfen, besser aber noch:
BlitzMax: [AUSKLAPPEN]
While Not Eof(datei)


Das macht hier vielleicht nicht so viel unterschied, allerdings erleichtert das, wenn man sich an so kleine Codingstyles hält, enorm die Lesbarkeit des Codes. Wenn ich den Code nicht kenne, würde ich mich sofort fragen: "Was für Werte kann Eof noch liefern außer 1? 2, 3 ...5...?" Mit "Not Eof" ist sofort klar: "Es handelt sich um einen Bool"...
Bei "Eof" zwar ohnehin klar dass es sich um einen Bool handelt, aber wenn es eigene Methoden sind ist es nicht mehr sofort ersichtlich.
Es gibt 10 Gruppen von Menschen: diejenigen, die das Binärsystem verstehen, und die anderen.
 

sinjin

BeitragDi, Jun 16, 2020 11:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielleicht geht es etwas schneller wenn du statt lauter Ints, mal nen Short oder Byte verwendest. Du hast ja "nur" 200 Länder, warum dann 4 Bytes speichern/laden?
Für Ints habe ich mal nen Mini-Compressor geschrieben, allerdings bei sehr grossen Zahlen verbraucht es Maximal 5 Bytes auf der Platte.
Code: [AUSKLAPPEN]

function readpint%(f:tstream)
  local ret%,a%,c%
  repeat
    a=readbyte(f)
    ret:+(a&$7f) shl c
    c:+7
  until not(a&$80)
  return ret
endfunction

function writepint(f:tstream,src%)
  repeat
    writebyte f,(src&$7f) + ((src shr 7<>0) shl 7)
    src:shr 7
  until not src
endfunction

function skippint(f:tstream)
  repeat
  until not(readbyte(f)&$80)
endfunction

bmurray

BeitragDi, Jun 16, 2020 15:49
Antworten mit Zitat
Benutzer-Profile anzeigen
CO2 hat Folgendes geschrieben:
Hallöchen,

Ein kurzer Hinweis noch, einfach weil es bisher nicht explizit genannt wurde: Kommen die 13 Sekunden aus einem Debug, oder einem Release-Build?


Das war tatsächlich ein Release-Build, aber auf meinem älteren Laptop. Auf meinem Desktop-PC waren es nur noch 4 Sekunden, was ich trotzdem noch zu lang finde.

CO2 hat Folgendes geschrieben:

Ich habe die BlitzMax-Syntax nicht mehr auf dem Schirm, aber was macht die Zeile stadt:+[wstadt]? Embarassed Very Happy


Ups, das sollte eigentlich gar nicht rein. Ich habe einfach ein Array erstellt:
Code: [AUSKLAPPEN]
Global stadt:tstadt[]


in dem alle Städte noch einmal gespeichert werden (also neben der Liste). Über die ID, die jede Stadt hat, kann ich so ganz einfach die betreffende Stadt ansprechen. Etwa mit: "stadt[5].einwohner:+100" oder ähnliches. Die Zeile stadt:+[wstadt] fügt dem Array einfach die aktuell geladene Stadt hinzu.



DAK hat Folgendes geschrieben:
bmurray hat Folgendes geschrieben:

Meine größte Sorge ist auch, dass BMax auf künftigen Betriebssystemen nicht mehr läuft. Kann man da abschätzen, wie da die Chancen stehen werden? Ich arbeite gerade am Nachfolger meines Spiels, wenn es absehbar ist, dass das mit BMax irgendwann nicht mehr läuft, würde ich früher auf eine modernere Sprache umsteigen (wohl C++).


BMax schaut da besser aus als BB. Es verwendet zumindest DirectX 9 und OpenGL 2.1. Beides schon schwer veraltet, aber beides noch akzeptabel unterstützt (im Gegensatz zu dem DirectX 7 von BB).
OpenGL ist generell sehr gut im Supporten von alten Versionen (Open Source sei Dank), da kann man sich noch ein paar Jahre drauf verlassen.

Ein anderer großer Vorteil von BMax über BB ist, dass die Engine nicht fix mit der Sprache verdrahtet ist, und sich dank dem Modulsystem vergleichsweise leicht austauschen lässt. Das heißt, selbst wenn DX9/OGL2.1 nicht mehr unterstützt wird, sollte es machbar sein, BMax weiter zu verwenden.

Solange man BMax hauptsächlich auf Windows verwenden will, ist der Compiler auch noch eine Weile mit Windows kompatibel. Was ich mitbekommen hab, schaut es mit Linux nicht so rosig aus. Mac hab ich keine Ahnung.

BMax NG ist auch gut dabei, die Sprache kompatibel zu halten.

Was BMax eher sterben lässt, ist die mangelnde Community. Für einen Hobbyprogrammierer der hauptsächlich Kleinzeug macht, ist das noch ok. Aber wenn man mal was Größeres oder Komplizierteres vor sich hat, dann ist BMax einfach nicht die richtige Wahl.

Das fängt bei der Menge der Leute die Fragen beantworten können an, und hört bei den Modulen und Bibliotheken auf.

Wenn du eine Frage in BMax hast, kannst du sie im Grunde nur hier stellen und kriegst dann potentiell von 10 ehemaligen BMax-Programmierern eine Antwort alla "Hab ich schon seit 10 Jahren nicht mehr verwendet, aber eventuell könnte es grob so gehen".

Wenn du zu Python/Java/C++/... eine Frage hast, dann stellst du sie auf Stackoverflow, und 5 Minuten später ist deine Frage als Duplikat geschlossen, weil sie schon fünf Mal beantwortet wurde Wink

Was die Bibliotheken angeht: Wenn du was Komplexeres brauchst, dann kannst du mal in alten Forenbeiträgen nach noch nicht toten Links graben und vielleicht kriegst du etwas, was vor 5-10 Jahren geschrieben wurde und wo der Autor nicht mehr auffindbar ist.

Bei Python/Java/C++/... gibt es entweder eine Appstore-Artige Paketverwaltung in der du tausende aktuelle Module mit einem Befehl runterladen und installieren kannst, oder es gibt zumindest auf Github irrsinnig viele Pakete. Wenn man z.B. sowas simples wie HTTPS mit einer modernen TLS-Version auf BlitzMax haben will, kann man schon schnell daran stecken bleiben.

C++ würde ich btw. nur dann lernen, wenn du einen ganz spezifischen Grund dafür hast. Wenn du "einfach so" entwickeln willst, dann würd ich dir eher zu Java oder Python für General Purpose Programming raten, oder zu Unity für Spieleentwicklung.


Vielen Dank für deine Anmerkungen. Ja, ich bin ein Hobbyprogrammierer, ich habe weder Informatik studiert, noch irgendetwas in der Richtung gelernt. BlitzMax gefällt mir wegen OOP und der Einfachheit. Ein Beispiel: Der Befehl Graphics. Ich habe keine Ahnung, wie man etwa eine simple 2D-Anwendung mit C++ programmieren kann (so etwas wie ein simples "Graphics" scheint es nicht zu geben). Ich bin eher der learning-by-doing Typ und in der Konsole programmieren finde ich dermaßen langweilig, dass ich es nicht geschafft habe, bei C++ dran zu bleiben.

Wie definiert man eigentlich ein größeres Projekt? Mein Game hat jetzt etwas mehr als 100.000 Zeilen Code. Ich weiß, es hängt nicht nur an der Zeilenanzahl, aber trotzdem: BlitzMax scheint mir - im Moment - für meine Zwecke ausreichend, und da höre ich natürlich gerne, dass es wohl noch einige Zeit auf modernen Rechnern laufen wird.

Trust hat Folgendes geschrieben:
Ich würde dir zumindest empfehlen auf Blitzmax NG umzusteigen.

Vielen Dank für den Hinweis. Kennst du eine gute IDE für NG? Falls ich richtig liege, funktioniert Blide nicht mit der NG-Version, aber Blide gefällt mir eigentlich ganz gut.

Danke wegen EoF. Werd ich beherzigen.

sinjin hat Folgendes geschrieben:
Vielleicht geht es etwas schneller wenn du statt lauter Ints, mal nen Short oder Byte verwendest. Du hast ja "nur" 200 Länder, warum dann 4 Bytes speichern/laden?
Für Ints habe ich mal nen Mini-Compressor geschrieben, allerdings bei sehr grossen Zahlen verbraucht es Maximal 5 Bytes auf der Platte.


Ja, Shorts könnte ich natürlich machen und werde ich wohl auch. Die Floats könnte man auch in Ints umwandeln und dann einfach "neu deklarieren" (also 12345 in einem Zwischenschritt laden, aber der Variable dann 123,45 zuweisen, oder so). Als ich aber mit Shorts programmiert habe, waren da so viele Fehler drin (da sie ja nicht in den Minusbereich gehen). Das hat mich jedes Mal wahnsinnig gemacht, wenn ich einen BUg nicht gefunden habe, und dann am Ende gemerkt habe, dass es an den Shorts lag.

Interessant, dein Compressor, den schau ich mir mal genauer an, danke

DAK

BeitragDi, Jun 16, 2020 18:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Vielen Dank für deine Anmerkungen. Ja, ich bin ein Hobbyprogrammierer, ich habe weder Informatik studiert, noch irgendetwas in der Richtung gelernt. BlitzMax gefällt mir wegen OOP und der Einfachheit. Ein Beispiel: Der Befehl Graphics. Ich habe keine Ahnung, wie man etwa eine simple 2D-Anwendung mit C++ programmieren kann (so etwas wie ein simples "Graphics" scheint es nicht zu geben). Ich bin eher der learning-by-doing Typ und in der Konsole programmieren finde ich dermaßen langweilig, dass ich es nicht geschafft habe, bei C++ dran zu bleiben.

Wie definiert man eigentlich ein größeres Projekt? Mein Game hat jetzt etwas mehr als 100.000 Zeilen Code. Ich weiß, es hängt nicht nur an der Zeilenanzahl, aber trotzdem: BlitzMax scheint mir - im Moment - für meine Zwecke ausreichend, und da höre ich natürlich gerne, dass es wohl noch einige Zeit auf modernen Rechnern laufen wird.


Ja, C++ ist nur für professionelle Entwicklung wirklich sinnvoll und dort auch nur wo man entweder tiefen Hardware-Access (z.B. für Treiber oder Engines schreiben) oder extreme Performance braucht.

BlitzMax ist deutlich besser für größere Projekte geeignet als BB. Eben auch wegen der Modularisierung, besserer Typisierung usw.
100k Zeilen sind definitiv schon ein größeres Projekt. Da du (nehme ich an) alleine dran bist, ist es aber noch überschaubarer.
Was dir andere Sprachen da helfen (z.B. Java oder Python) ist, dass es für vieles einfach fertige Bibliotheken bzw. mehr Features in der Standarbibliothek gibt.

Für dein aktuelles Problem könntest du z.B. in Java oder Python einfach den eingebauten Serializer verwenden, der genau das sehr effizient und schnell machen kann. Java hilft dir u.A. sehr mit Multithreading (etwas was hingegen Python kaum kann). Wenn du also mehr Zeug gleichzeitig machen willst, dann ist Java die passende Sprache.

Wenn es um bessere Datenstrukturen oder Datenbanken geht (bei der Menge Daten wäre das eventuell schon zu überlegen), dann bieten dir beide Sprachen sehr viel Hilfe.

Weder Java noch Python haben von Haus aus groß was an Grafikengines eingebaut, aber beide haben genügend einfaches und tolles zum Installieren. Hab z.B. vor vielen Jahren die JMonkey-Engine unter Java verwendet, damit kann man sehr einfach sehr schöne Sachen machen. Schatten? Dynamisches Wasser? Physik? Alles kein Thema und mit ein paar Zeilen gemacht. Und es gibt inzwischen schon bei weitem Besseres.
Unter Python hab ich die 2D-Engine PyGame verwendet. Außer dass man sie erst installieren muss, ist die nicht komplizierter als Blitz.

Dazu kommen mit Netbeans, IntelliJ, PyCharm usw. IDEs, die weit mehr können und weit komfortabler sind als alles was es für Blitz-Sprachen je gegeben hat.
Gewinner der 6. und der 68. BlitzCodeCompo

Trust

BeitragMi, Jun 17, 2020 13:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Kennst du eine gute IDE für NG? Falls ich richtig liege, funktioniert Blide nicht mit der NG-Version, aber Blide gefällt mir eigentlich ganz gut.


Ja, Blide ist auch alt und wird nicht mehr weiterentwickelt.
Würde dir da VS Code mit BlitzMax Extension empfehlen.
Ich entwickle mittlerweile nur noch in VS Code (Python, C#, C, JS, Lua, GO, BlitzMax ...) und bin echt zufrieden.

Und zu dem Problem mit den Ladezeiten:
Der Flaschenhals ist hier die Stringkopiererei der Städtenamen und die TList, diese ist in BMax nicht die schnellste.

Versuche das ganze mal mit arrays. Bei den Strings ist das Problem, dass ja intern für jeden string nochmals ein array angelegt wird mit länge n wobei n=str.Length.


Alle Tests wurden im debugmodus mit einer einer Städteanzahl von 1000000 durchgeführt.

Test mit TList ganz normal:
Code: [AUSKLAPPEN]
Generating took: 1998ms
Saving took: 4875ms
Getting file took: 99ms
New loading total took: 5097ms


Test mit array:
Code: [AUSKLAPPEN]
Generating took: 1084ms
Saving took: 4276ms
Getting file took: 61ms
New loading total took: 4080ms


Test mit array ohne Städtenamen
Code: [AUSKLAPPEN]
Generating took: 214ms
Saving took: 2508ms
Getting file took: 22ms
New loading total took: 2442ms


Code ist nicht viel neues außer das TList mit einem array ausgetauscht wurde:
BlitzMax: [AUSKLAPPEN]
SuperStrict
Framework brl.blitz
Import brl.filesystem
Import brl.stream
Import brl.linkedlist
Import brl.random
Import brl.standardio
Import brl.ramstream


' Define TStadt Type for sample data
Type TStadt
Global list:TStadt[] = New TStadt[1000000]

Field name:String
Field id:Int
Field land:Int
Field gebiet:Int
End Type

Local time:Long = MilliSecs()

' Generate sample cities
For Local i:Int = 0 Until 1000000
Local stadt:TStadt = New TStadt

stadt.name = "Stadt " + Rand(0, 10000000)
stadt.id = i
stadt.land = i / 2
stadt.gebiet = i * 2
TStadt.list[i] = stadt
Next

Print "Generating took: " + (MilliSecs() - time) + "ms"

time = MilliSecs()
' Save sample data
Local file:TStream = WriteStream(".\testdata.dat")
For Local i:Int = 0 Until TStadt.list.Length
WriteStringBB(file, TStadt.list[i].name)
file.WriteInt(TStadt.list[i].id)
file.WriteInt(TStadt.list[i].land)
file.WriteInt(TStadt.list[i].gebiet)
Next
file.Close()

Print "Saving took: " + (MilliSecs() - time) + "ms"

NewLoadRam()

Function NewLoadRam()
Local time:Long = MilliSecs()

Local file:TStream = ReadStream(".\testdata.dat")
Local buf:Byte[] = New Byte[file.Size()]
Local ramStream:TRamStream = CreateRamStream(buf, file.Size(), 1, 1)
CopyStream(file, ramStream) ' This puts us at the end of the stream!
file.Close()

Print "Getting file took: " + (MilliSecs() - time) + "ms"

' So remember to use seek to get to the beginning again
ramStream.Seek(0)

Local i:Int = 0

While Not Eof(ramStream)
Local stadt:TStadt = New TStadt

stadt.name = ReadStringBB(ramStream)
stadt.id = ramStream.ReadInt()
stadt.land = ramStream.ReadInt()
stadt.gebiet = ramStream.ReadInt()

TStadt.list[i] = stadt
i :+ 1
Wend

ramStream.Close()

Print "New loading total took: " + (MilliSecs() - time) + "ms"
End Function


Function ReadStringBB:String(f:TStream)
Local n:Int = f.ReadInt()
Return f.ReadString(n)
End Function
Function WriteStringBB(f:TStream, str:String)
Local n:Int = str.Length
f.WriteInt(n)
f.WriteString(str)
End Function
Es gibt 10 Gruppen von Menschen: diejenigen, die das Binärsystem verstehen, und die anderen.

bmurray

BeitragSa, Jun 20, 2020 18:51
Antworten mit Zitat
Benutzer-Profile anzeigen
So, ich habe jetzt Python, Pygame und Visual Studio Code ausprobiert... Ich bin fassungslos! Es fühlt sich an wie eine Zeitreise vom Mittelalter in die Neuzeit (ok, vielleicht nicht ganz so krass), aber ich absolut fasziniert. Die IDE ist ja der Hammer, es ist alles viel "smoother" als mit Blide, Python gefällt mir und die Pygame-Bibliothek ist genau das richtige für mich. Ich kannte Python zwar, aber habe mich nie mit beschäftigt. Ein großer Fehler, wie ich jetzt sehe. Vielen Dank an alle, die mir das empfohlen haben!!! Dass man allerdings Variablen nicht deklarieren kann (oder muss?) irritiert mich etwas. Wie erstelle ich globals, die ich nicht sofort, aber eben später brauche? Naja, ich hab noch nicht alle Tutorials durch, das find ich schon raus.

Trust hat Folgendes geschrieben:
Der Flaschenhals ist hier die Stringkopiererei der Städtenamen und die TList, diese ist in BMax nicht die schnellste.


Danke für Deine Test. Stimmt, Strings brauchen natürlich länger, aber ich denke, auf die kann ich nicht verzichten. Dass Listen so langsam sind, war mir gar nicht bewusst. Schade, ich finde Listen sehr bequem.
 

bonajkukoj

BeitragSo, Jun 21, 2020 0:14
Antworten mit Zitat
Benutzer-Profile anzeigen
bmurray hat Folgendes geschrieben:
Wie erstelle ich globals, die ich nicht sofort, aber eben später brauche?


Du kannst, wenn du eine Variable zum Beispiel im normalen Modul-Scope deklariert hast und du sie dann später innerhalb einer Funktion brauchst, dort mit der Zeile
Code: [AUSKLAPPEN]
Global variablenName
die vorher definierte Variable quasi global machen, bzw eben auf diese außerhalb definierte Variable verweisen.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group