Dateierstellung und Füllung ziemlich langsam

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Delle
Beiträge: 1144
Registriert: 10.05.2005 22:48

Dateierstellung und Füllung ziemlich langsam

Beitrag von Delle »

Hallo,

ich habe eine Datei "Wörter.txt" mit ca. 1,5 Millionen Wörtern.

Ich will in dieser Datei jetzt zeilenweise jedes Wort auslesen, den Anfangsbuchstaben ermitteln und dementsprechend in [Anfangsbuchstabe].txt alle Wörter mit diesem Anfangsbuchstaben schreiben.

Das hier funktioniert einwandfrei, ist aber selbst nach einer Stunde gerade mal beim Buchstaben F angekommen:

Code: Alles auswählen

Enumeration
  
  #Fenster
  #Start
  #Name
  
EndEnumeration

InitNetwork()

OpenWindow(#Fenster,0,0,490,510,"...",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)

ButtonGadget(#Start,10,440,470,30,"Umwandlung starten")

TextGadget(#Name,10,480,470,20,"",#PB_Text_Center)


  Repeat 

		
		EventID = WaitWindowEvent()
     
		If EventID=#PB_Event_CloseWindow:End:EndIf
		
		If EventID=#PB_Event_Gadget And EventGadget()=#Start
		  
		  
 		  If ReadFile(1,"Wörter.txt")
 		    
 		    While Eof(1)=0
          
          aktuell$=ReadString(1)
          
          first$=Left(aktuell$,1)
          
          OpenFile(99,Left(aktuell$,1)+".txt",#PB_File_Append)
          WriteStringN(99,aktuell$,#PB_Ascii)
          CloseFile(99)
          
            
          aktuell$=""
            
          While WindowEvent():Wend
           
        Wend
        
     CloseFile(1)
     
     
   EndIf
		  
	EndIf
     
ForEver
Wieso ist das so langsam? Sollten vielleicht gleich 26 Dateien mit den jeweiligen Anfangsbuchstaben erstellt und auch offen gehalten werden?

Danke!
PB 6.21 | Win 11
matbal
Beiträge: 261
Registriert: 30.03.2011 20:53

Re: Dateierstellung und Füllung ziemlich langsam

Beitrag von matbal »

Das ständige Öffnen und Schließen der Datei bremst stark.

Ich würde einmal erstellte Dateien geöffnet lassen und mir merken, welche Dateien schon geöffnet sind. Das sollte das Geschwindigkeitsproblem beseitigen.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8820
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Dateierstellung und Füllung ziemlich langsam

Beitrag von NicTheQuick »

Lies alle Wörter in eine LinkedList, sortiere sie und schreibe dann erst alle Wörter mit A in die erste Datei, dann B in die zweite, usw. Durch die Sortierung kommen sie alle der Reihe nach dran und du musst nicht zwischendurch die Dateien wechseln.
Ansonsten ist es natürlich auch eine gute Idee alle 26 Dateien einfach offen zu halten. Denn ständiges Öffnen und Schließen macht alles sehr langsam.
Benutzeravatar
Rudi
Beiträge: 143
Registriert: 22.04.2010 18:28
Wohnort: #PB_Any

Re: Dateierstellung und Füllung ziemlich langsam

Beitrag von Rudi »

Außerdem würde ich eine so große Datei mittels "ReadData()" in den Speicher lesen...
Win7 (x64)PB 5.4x (x86)5,7 Windows-LeistungsindexSuche
Benutzeravatar
Bisonte
Beiträge: 2474
Registriert: 01.04.2007 20:18

Re: Dateierstellung und Füllung ziemlich langsam

Beitrag von Bisonte »

Da ich annehme, daß Du am Ende mit den einzelnen Wörtern in den Dateien später noch was vorhast,
würde ich glatt sagen, das die Wörter in eine Datenbank gehören.

Dort kann man dann bequem und relativ performant die einzelnen Wörter suchen...

Nur mal so als Anregung...
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
xdes
Beiträge: 57
Registriert: 13.08.2016 12:53

Re: Dateierstellung und Füllung ziemlich langsam

Beitrag von xdes »

hi,

hemm meine idee ist wenn die festplatte schnell genug das das ganze in zwei bis 3 treads zu teilen...

und wie schon genant so wenig wie möglich die Datei neu inialitzieren...

dabei würde ich thread 1 zum lesen machen tread 2 zum bearbeiten und thread 3bis x zum ausgeben und speichern

beispiel:
thread 1 die lese datei gelesen(nur einmal öffnen) in
thread 2 so was wie left() gemacht
thread 3-x das schrieben in die datei (ein thread/aktion)

wenn es dabei stärker Überschneidungen gibt würde ich vermutlich ein array als cache verwenden (dabei kommt es aber auf die zu lesenden Größen an )

wenn du es nicht direkt ein File System brauchst und noch andere Parameter brauchst ist dabei evtl auch eine db interessant...
desweiteren kann auch das eine oder andere AV und ähnliches deine Festplatte langsamer machen oder die Zugriffs Geschwindigkeit verlangsamen (evtl hilft da ein blick mal (in Windows) in den perfmon und dann zu gucken wie viel das dann wirklich nutzt...


mit freundlichen grüßen
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8820
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Dateierstellung und Füllung ziemlich langsam

Beitrag von NicTheQuick »

Bei Festplatteninteraktion sind Threads ziemlich überflüssig und wahrscheinlich sogar eher kontraproduktiv. Die Festplatte ist da schließlich immer noch der Flaschenhals. Damit wird also nichts schneller. Und solche kleinen Aufgaben auf verschiedene Threads aufzuteilen und diese dann zu synchronisieren, macht es vermutlich langsamer als wenn man es direkt in einem Thread macht.
matbal
Beiträge: 261
Registriert: 30.03.2011 20:53

Re: Dateierstellung und Füllung ziemlich langsam

Beitrag von matbal »

Jetzt war ich doch mal neugierig, wie lange das aussortieren dauert. Das einzige, was ich anders mache, ist, ich lasse alle Zieldateien geöffnet.
Auf meinem Computer (Dual-Core Celeron) dauert es bei einer Größe von 1500000 Pseudo-Wörtern ca. 2 Sekunden.

Das ist der Code, mit dem ich die Wörter aufteile.

Code: Alles auswählen

Define InFile$ = "c:\temp\test.txt"
Define OutPath$ = "c:\temp\"

Global NewMap fn()            ; Dateinummern 
Define zeile$, a$ 


If ReadFile(0, InFile$)
   While Not Eof(0)
      zeile$ = ReadString(0)           ; Wort lesen
      
      a$ = Left(zeile$, 1)             ; Anfangsbuchstabe
      
      If fn(a$) = 0
         fn(a$) = CreateFile(#PB_Any, OutPath$ + a$ + ".txt")
      EndIf
      
      WriteStringN(fn(a$), zeile$)     ; Wort in Datei schreiben
   Wend
   CloseFile(0)
   
   
   ForEach fn()                   ; Alle Dateien schließen
      CloseFile(fn())
   Next
EndIf

Und hier noch der Code zum Erstellen der Test-Datei mit den 1500000 Pseudo-Wörtern.

Code: Alles auswählen

Define File$ = "c:\temp\test.txt"

Define maxlen = 20
Define minlen = 3
Define wortanz = 1500000

Define wort$, rndlen, *c.character, i, n 


wort$ = Space(maxlen)            

If CreateFile(0, File$)
   
   For i = 1 To wortanz
      rndlen = Random(maxlen, minlen)    
      
      *c = @wort$                         
      For n = 1 To rndlen
         *c\c = Random('z', 'a')          
         *c + SizeOf(character)           
      Next n
      *c\c = 0                            
      
      WriteStringN(0, wort$)              
   Next i
   
   CloseFile(0)
EndIf
Antworten