CListCtrl - Erfahrungsaustausch virtuelle Tabellen mit CListCtrl



  • Hi,

    war irgendwie überrascht als ich nach der Implementation einer virtuellen Tabelle mit CListCtrl folgendes feststellte:

    Basis war eine Tabelle mit Wertpapierkursdaten auf einem lokalen MySQL-Server.
    300.000 Zeilen mit 8 Spalten, alles varchar. 31,2 MB auf der Platte.
    Dann 2 Dialoge gemacht. Ein Dialog ruft die Tabelle konventionell auf, der andere Dialog als virtuelle Tabelle mit OnLvnGetdispinfo.
    Folgende Zeitmessungen bis zum vollständigen Aufbau und Darstellung der Tabelle gemessen:

    Zeilen Konventionell Virtuell
    5000 10,5 sec 5,8 sec (freu)
    10000 21,1 sec 12 sec (freu weiter)
    30000 32,1 sec 38 sec (Schock !!!)
    100000 83,3 sec kein Bock mehr zu warten, Prozessmanager

    Nach jedem Dialog natürlich das Programm neu gestartet, um unfaire Speicherhinterlassenschaften auszuschliessen.
    Das ganze ist reproduzierbar und liegt weder an der Tabelle noch am Rechner.
    Habs auf einem anderen Client probiert.
    Der Speicherbedarf zur Ausführzeit steigt bei beiden Verfahren in etwa gleich schnell an und ist auch nach Darstellung der Tabelle ziemlich gleich.

    Wie kommt denn das? Laut MSDN wird vollmundig der virtuelle Ansatz empfohlen, wenns um grosse Tabellen geht.
    Kennt das Phänomen jemand ???
    Im übrigen frag ich mich jetzt schon, wie ich solche Tabellenmonster in angemessener Zeit auf den Schirm bekomme ohne gleich ein limit einzubauen wie es bei vielen Datenbank-frontends der Fall ist.

    Gruss
    koreson



  • Irgendwas machst du falsch 🙂
    eiver virtuelles ListControl fragt normalerweise nur die sichtbaren Einträge ab, geht also rasend schnell. Das "Aufbauen" beschränkt sich also auf das Setzen der endgültigen Länge und di Abfrage+Darstellung der sichtbarein Einträge.

    Checkliste:

    - LVS_OWNERDATA in der Resource bzw. beim Erzeugen des Controls
    - einmal LVM_SETITEMCOUNT, um die Anzahl der elemente zu setzen
    - LVN_GETDISPINFO: testet item.mask, welche Daten angefordert werden



  • koreson schrieb:

    Zeilen Konventionell Virtuell
    5000 10,5 sec 5,8 sec (freu)
    10000 21,1 sec 12 sec (freu weiter)
    30000 32,1 sec 38 sec (Schock !!!)
    100000 83,3 sec kein Bock mehr zu warten, Prozessmanager

    wird da mit bubble-sort oder insertion-sort was sortiert?



  • Hi,

    Hab den Übeltäter gestern Nacht noch lokalisiert:

    CString element;	
    	while ((mRecord = mysql_fetch_row(mTabelle)) != NULL)
    	{
    		m_database.push_back(vector<CString>());
    
    		for (int j=0;  j < max_cols;  j++)
    		{
    		element = mRecord[j];
    		m_database.back().push_back(element);
    		}
    	i++;
    	}
    

    Das Kopieren der Daten in diesen 2-dim vector ist alles andere als performant.
    Wenn ich das weglasse, gehts rasend schnell, allerdings stürzt das Progi dann ab, weil ich nicht weiss, wie man nur die sichtbaren records aus der mTabelle-Struktur rausholt.

    D.h ich weiss nicht, wie ich das Ergebnis mTabelle in der der OnLvnGetdispinfo-Methode verarbeiten kann ohne while(mysql_fetch_row...) zu verwenden, die zZt. noch so aussieht und auch funktioniert:

    void CTestDlg::OnLvnGetdispinfoList1(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    LV_ITEM* pItem= &(pDispInfo)->item;
    lstrcpyn(pItem->pszText, m_database[pItem->iItem][pItem->iSubItem], pItem->cchTextMax);
    *pResult = 0;
    }
    

    Wenn da jemand vielleicht ne Idee hat, wie's ohne das Kopiere in den vector funzt, könnte mir das den Sonntag nachmittag retten 🙂
    Wäre fast geneigt, für ne Lösung was zu bieten, ist nämlich für mein Projekt ziemlich wichtig.

    gruss
    koreson



  • So, Sontag nachmittag gerettet. Hier die Lösung:

    Ohne das Zwischenkopieren in den vector.

    void CTestDlg::OnLvnGetdispinfoList1(NMHDR *pNMHDR, LRESULT *pResult)
    	{
    	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
             LV_ITEM* pItem= &(pDispInfo)->item;
       	mysql_data_seek (mTabelle, pItem->iItem); 	  
       	mRecord = mysql_fetch_row(mTabelle);
       	lstrcpyn(pItem->pszText, mRecord[pItem->iSubItem], pItem->cchTextMax);
    	*pResult = 0;
    	}
    

    Zeigt die 300.000 in ca 3 sec an. Scrollt recht schnell und stürtzt nicht ab.
    😃 😃 😃
    Wäre das nicht was für die FAQ?

    Gruss
    koreson


Anmelden zum Antworten