Strings aus sqlite db in listicon gadget übertragen

Für allgemeine Fragen zur Programmierung mit PureBasic.
kmais
Beiträge: 45
Registriert: 09.02.2017 13:54

Strings aus sqlite db in listicon gadget übertragen

Beitrag von kmais »

hallo und guten tag.
Ich nutze eine sqlite Tabelle mit ca. 600 Spalten und im Moment ca. 500 Zeilen (ja, ich weiß. Sie ist bereits normalisiert und eine Alternative ist leider nicht möglich :-)..)
Stelle ich die Tabelle in einem ListIcon dar, benötigt PB ca. 260 sekunden. Gambas schafft das in 6 Sekunden.
Was sich für mich etwas kurios darstellt ist folgendes:
Habe ich eine Tabelle mit 6 Spalten ist die Darstellungszeit ca. 0.03 s. Nachvollziehbar.
Wenn ich die Tabelle mit 600 Spalten verwende und in einer Schleife nur die ersten 6 Spalten einlese, benötigt PB dennoch wesentlich länger. Mehr als 3 Sekunden.
Wie kann das sein? Ich kann mir das nur mit einem Speicherproblem erklären. Liegen die Spalten einer ausgelesenen Zeile im Result nicht sequentiell vor, so dass PB jede Spalte erst suchen im Zeilen Result?
Wenn jemand eine Lösung für die Performance wüsste, dann wäre ich sehr dankbar.

Code: Alles auswählen

Enumeration
  #dbase
EndEnumeration
Procedure showData(dbName.s)
countCol.i=0
i.i=0
j.i=-1

; PureLVSORT_Disabled(#True|#False)
If OpenDatabase(#dbase,dbName,"","")
  If DatabaseQuery(#dbase, "SELECT * FROM repmittel")
    countCol=DatabaseColumns(#dbase)
    For i=0 To DatabaseColumns(#dbase)-1
      If i=0
        SetGadgetItemText(ListIcon_0,-1,DatabaseColumnName(#dbase,i),i)
      Else
        AddGadgetColumn(ListIcon_0,i,DatabaseColumnName(#dbase,i),GadgetWidth(ListIcon_0)/7)
      EndIf
    Next i
  EndIf
  time1=ElapsedMilliseconds()
  While NextDatabaseRow(#dbase)
    j+1
    AddGadgetItem(ListIcon_0,j,GetDatabaseString(#dbase,0))
    Debug DatabaseColumnName(#dbase,0)
    For i=1 To ; bzw. countCol (s.oben)
          SetGadgetItemText(ListIcon_0,j,(GetDatabaseString(#dbase,i)),i)
;       Debug GetDatabaseString(#dbase,i)
    Next i
  Wend
  FinishDatabaseQuery(#dbase)
Else
  Debug DatabaseError()
EndIf
time2=ElapsedMilliseconds()
time3.f=(time2-time1)/1000
SetGadgetText(Text_0,StrF(time3))
ProcedureReturn
EndProcedure  
__________________________________________________
Color-Tags>Code-Tags
12.02.2017
RSBasic
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Strings aus sqlite db in listicon gadget übertragen

Beitrag von mk-soft »

Hatte etwas Langeweile...

Code: Alles auswählen

;-TOP

; ***************************************************************************************

; ShowDatabaseItems by mk-soft from 12.02.2017

Procedure ClearGadgetColumns(Gadget)
  CompilerIf #PB_Compiler_Version <= 551
    ClearGadgetItems(Gadget)
    While GetGadgetItemText(Gadget, -1, 0)
      RemoveGadgetColumn(Gadget, 0)
    Wend
  CompilerElse
    RemoveGadgetColumn(Gadget, #PB_All)
  CompilerEndIf
EndProcedure

Procedure ShowDatabaseItems(Gadget, DBase, Hide = #False)
  Protected result.i, columns.i, index.i, size.i, text.s
  
  Repeat
    If GadgetType(Gadget) <> #PB_GadgetType_ListIcon
      Break
    EndIf
    If Not IsDatabase(DBase)
      Break
    EndIf
    HideGadget(Gadget, Hide)
    ClearGadgetColumns(Gadget)
    columns = DatabaseColumns(DBase)
    For index = 0 To columns - 1
      text = DatabaseColumnName(DBase, index)
      size = Len(text) * 12
      AddGadgetColumn(Gadget, index, text, size)
    Next
    While NextDatabaseRow(DBase)
      text = ""
      For index = 0 To columns - 1
        text + GetDatabaseString(DBase, index) + #LF$
      Next
      AddGadgetItem(Gadget, -1, text)
    Wend
    FinishDatabaseQuery(DBase)
    HideGadget(Gadget, #False)
    result = CountGadgetItems(Gadget)
  Until #True
  ProcedureReturn result
  
EndProcedure

; ***************************************************************************************

CompilerIf #PB_Compiler_IsMainFile
  
  ; Constant
  Enumeration ;Window
    #Main
  EndEnumeration
  
  Enumeration ; Menu
    #Menu
  EndEnumeration
  
  Enumeration ; MenuItems
    #MenuExitApplication
  EndEnumeration
  
  Enumeration ; Gadgets
    #List
    #Edit
  EndEnumeration
  
  Enumeration ; Statusbar
    #Status
  EndEnumeration
  
  ; Global Variable
  Global ExitApplication
  
  ; Functions
  
  UseSQLiteDatabase()
  
  Procedure CheckDatabaseUpdate(Database, Query$)
    Result = DatabaseUpdate(Database, Query$)
    If Result = 0
      Debug DatabaseError()
    EndIf
    
    ProcedureReturn Result
  EndProcedure
  
  Procedure CreateDummyDatabase(DBase)
    If OpenDatabase(DBase, ":memory:", "", "")
      
      CheckDatabaseUpdate(DBase, "CREATE TABLE food (recid INTEGER PRIMARY KEY ASC, name CHAR(50), weight FLOAT)")
      
      CheckDatabaseUpdate(DBase, "INSERT INTO food (name, weight) VALUES ('apple', '10.005')")
      CheckDatabaseUpdate(DBase, "INSERT INTO food (name, weight) VALUES ('pear', '5.9')")
      CheckDatabaseUpdate(DBase, "INSERT INTO food (name, weight) VALUES ('banana', '20.35')")
    Else
      Debug "Can't open database !"
    EndIf
  EndProcedure
  
  Procedure UpdateWindow()
    
    Protected x, y, dx, dy, menu, status
    
    menu = MenuHeight()
    If IsStatusBar(#Status)
      status = StatusBarHeight(#Status)
    Else
      status = 0
    EndIf
    x = 0
    y = 0
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - menu - status
    ResizeGadget(#List, x, y, dx, dy)
    
  EndProcedure
  
  ; Main
  Procedure Main()
    
    Protected event, style, dx, dy
    
    style = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget
    dx = 800
    dy = 600
    
    If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, dx, dy, "Main", style)
      
      ; Enable Fullscreen
      CompilerIf #PB_Compiler_OS = #PB_OS_MacOS 
        Protected NewCollectionBehaviour
        NewCollectionBehaviour = CocoaMessage(0, WindowID(#Main), "collectionBehavior") | $80
        CocoaMessage(0, WindowID(#Main), "setCollectionBehavior:", NewCollectionBehaviour)
        ; Mac default menu
        If Not IsMenu(#Menu)
          CreateMenu(#Menu, WindowID(#Main))
        EndIf
        MenuItem(#PB_Menu_About, "")
        MenuItem(#PB_Menu_Preferences, "")
      CompilerEndIf
      
      ; Menu
      CreateMenu(#Menu, WindowID(#Main))
      MenuTitle("Ablage")
      MenuItem(#MenuExitApplication, "Be&enden")
      ; Gadgets
      ListIconGadget(#List, 0, 0, dx, dy, "recid", 100)
      
      ; Statusbar
      CreateStatusBar(#Status, WindowID(#Main))
      AddStatusBarField(#PB_Ignore)
      
      UpdateWindow()
      
      ;-Test database
      CreateDummyDatabase(0)
      If DatabaseQuery(0, "SELECT * FROM food WHERE weight > 0")
        count = ShowDatabaseItems(#List, 0, #True)
        StatusBarText(#Status, 0, "Items: " + count)
      EndIf
      
      ; Main Loop
      Repeat
        event = WaitWindowEvent()
        Select event
          Case #PB_Event_Menu
            Select EventMenu()
                CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
                  
                Case #PB_Menu_About
                  
                Case #PB_Menu_Preferences
                  
                Case #PB_Menu_Quit
                  ExitApplication = #True
                  
                CompilerEndIf
                
              Case #MenuExitApplication
                ExitApplication = #True
                
            EndSelect
            
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #List
                
              Case #Edit
                
            EndSelect
            
          Case #PB_Event_SizeWindow
            Select EventWindow()
              Case #Main
                UpdateWindow()
                
            EndSelect
            
          Case #PB_Event_CloseWindow
            Select EventWindow()
              Case #Main
                ExitApplication = #True
                
            EndSelect
            
        EndSelect
        
      Until ExitApplication
      
    EndIf
    
  EndProcedure : Main()
  
  End
  
CompilerEndIf
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Kiffi
Beiträge: 10621
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Strings aus sqlite db in listicon gadget übertragen

Beitrag von Kiffi »

@kmais: 600 Spalten * 500 Zeilen sind natürlich schon 'ne Hausnummer.

Dass diese Menge an Daten ein wenig Zeit brauchen, bis sie im ListIconGadget eingetragen sind, sollte klar sein. Andere Programmiersprachen (Du erwähntest Gambas) sind da vielleicht ein wenig flotter. Mit dem (angepassten) Code von mk-soft oben dauert's bei mir knapp 10 Sekunden. Aber auch wenn die Daten im ListIconGadget sind, ist das Scrollen durch selbige keine wahre Freude.

Vielleicht schaust Du Dir auch mal den Code von edel an: http://www.purebasic.fr/german/viewtopi ... 61#p336561

Hier werden die Daten in ein Array eingetragen und das ListIconGadget holt sie sich bei Bedarf (wenn sie sich im sichtbaren Bereich befinden). Weiß allerdings nicht, wie man diesen Code für 600 Spalten umschreiben kann. Überdies ist der Code nur für Windows-Systeme geeignet.

Oder aber Du überdenkst noch einmal Dein Konzept zur Anzeige der Daten...

Grüße ... Peter
Hygge
Benutzeravatar
Kiffi
Beiträge: 10621
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Strings aus sqlite db in listicon gadget übertragen

Beitrag von Kiffi »

Hygge
kmais
Beiträge: 45
Registriert: 09.02.2017 13:54

Strings aus sqlite db in listicon gadget übertragen, 2te

Beitrag von kmais »

Hei,

Ich bin noch recht neu in PB, daher kommen wohl öfter ein paar blöde Fragen von mir. Sorry.
Ich habe die Frage schon vor ein paar Tagen gestellt, mache es jetzt wieder da meine Tests kuriose Ergebnisse haben. Vielleicht kann mir das jemand erklären.

Ich nutze eine sqlite Tabelle mit ca. 600 Spalten und im Moment ca. 500 Zeilen (ja, ich weiß. Sie ist bereits normalisiert und eine Alternative ist leider nicht möglich :-)..)
Stelle ich die Tabelle in einem ListIcon dar, benötigt PB ca. 260 sekunden. Gambas schafft das in 6 Sekunden.

Code: Alles auswählen

Procedure.s showData(dbName.s,sqlQuery.s)
Protected countCol.i=0, i.i=0, j.i=-1,text.s=""
    
If OpenDatabase(#dbase,dbName,"","")
  If DatabaseQuery(#dbase, sqlQuery)
    countCol=DatabaseColumns(#dbase)
    If countCol<8 
      size = GadgetWidth(ListIcon_0)/countCol
    Else
      size = GadgetWidth(ListIcon_0)/8
    EndIf
     
    HideGadget(ListIcon_0,1)
    ClearGadgetColumns(ListIcon_0)

    For i=0 To DatabaseColumns(#dbase)-1
      text = DatabaseColumnName(#dbase, i)
      AddGadgetColumn(ListIcon_0,i,text,size)
    Next i
  EndIf
  
  HideGadget(ListIcon_0,0)
  time1=ElapsedMilliseconds()
  While NextDatabaseRow(#dbase)
    text.s=""
    For i=0 To countCol
      text=text + GetDatabaseString(#dbase,i) + #LF$
    Next i
    AddGadgetItem(ListIcon_0,-1,Trim(text))
  Wend

  FinishDatabaseQuery(#dbase)

EndIf
Was sich für mich etwas kurios darstellt ist folgendes:

Also, wie schon gesagt, unter Linux (64 wie 32 bit) braucht das Listicon zum füllen bei der genannten Datenmenge, vor allem bei 600 Spalten, rund 4 Minuten.
Ich habe den unveränderten Quelltext jetzt mal unter Win7, 32 bit, mit PB 5.1 kompiliert und ausgeführt.
Hier braucht das Listicon lediglich 1,8 Sekunden zum Füllen all der Daten !!!!
Wie kann das sein?
Werden hier unterschiedliche GTK Libraries verwendet und könnte ich in der Richtung unter Linux eine bessere Performance herstellen?
Wenn euch direkt dazu etwas einfällt oder wie ich an weitere Infos kommen könnte, wäre das super.

Schönen Tach noch :-)

Klaus-Peter

__________________________________________________
Code-Tags hinzugefügt
17.02.2017
RSBasic


__________________________________________________
Beitrag zusammengeführt
Strings aus sqlite db in listicon gadget übertragen, 2te>Strings aus sqlite db in listicon gadget übertragen
Allgemein>Allgemein
17.02.2017
RSBasic
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Strings aus sqlite db in listicon gadget übertragen, 2te

Beitrag von ts-soft »

Es macht sich nicht so gut, 2x fast dieselbe Frage zu stellen, da wäre eine Ergänzung des ersten Beitrags besser.
Desweiteren gehört es sich nicht, Crosspostings zu veranstallten, das sind Postings mit gleichen Inhalt in verschiedenen
Foren, z.B. im engl. Forum sowie im deutschen Forum!

Könnte ein Mod/Admin dies bitte an den ersten Beitrag anhängen?

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten