Accès lent à une collection pour les Items de fin

Résolu
Signaler
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
-
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
-
Violent Ken
Salut, à tous ;)
J'ai un petit problème : l'accès aux objets d'une collection est très lent pour les objets dont l'index est élevé...

Exemple : code 1, on accède à 30000 objets, 1000 fois les 30 premiers
Le temps d'accès est très rapide (phase de récupération avec .Item)

Private Sub Command1_Click()
Dim o As Collection
Dim x As Long
Dim y As Long
Dim k As Object
   
   Set o = New Collection
   Debug.Print "adding..."
   For x = 1 To 30000
       o.Add k
   Next x
   Debug.Print "retrieving..."
   For x = 1 To 30
       For y = 1 To 1000
           Set k = o.Item(x)
       Next y
   Next x
   Debug.Print "done"
   
   Set k = Nothing
   Set o = Nothing

End Sub , ----
By Renfield

Exemple : code 2, on accède à 30000 objets, mais cette fois les 30000 de la collection ==> TRES lent...
Private Sub Command1_Click()
Dim o As Collection
Dim x As Long
Dim y As Long
Dim k As Object
   
   Set o = New Collection
   Debug.Print "adding..."
   For x = 1 To 30000
       o.Add k
   Next x
   Debug.Print "retrieving..."
   For x = 1 To 30000
       'For y = 1 To 1000
           Set k = o.Item(x)
       'Next y
   Next x
   Debug.Print "done"
   
   Set k = Nothing
   Set o = Nothing

End Sub , ----
By Renfield

Une idée pour remédier à çà ??

Merci, @+

Hex Editor VB

12 réponses

Messages postés
15814
Date d'inscription
jeudi 8 août 2002
Statut
Modérateur
Dernière intervention
4 mars 2013
131
normal, la collection est bien connue pour être lente dès que le nombre d'objet devient important (je me demande comment c'est implémenté, mais c'est sûrement une liste chaînée).

La solution ? Pourquoi ne pas essayé d'éclater ta collection en 10 ou 100 : l'accès aux objets pourrait être bien plus rapide je pense.
Messages postés
17288
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
27 septembre 2021
71
tout dépend de combien d'octets tu décale la chose...

si ca ne crashes pas, c'est deja bon signe
ensuite, j'ignore s'il aime bien bien lire et ecrire sur des zones mémoires qui se chevauchent, m'enfin....

au pire, tu peux te faire un tableau de pointeurs vers tes objets, mais là, pareil, faudrait que la recherche par clé soit relativement rapide...
peut etre avec un hash....
a voir, quoi ^^ sujet très vaste.

y'a quelques années, j'etais tombé sur un code sur le net, qui faisait des sortes de power collections, je cite (presque) "super rapides", "super pratiques", etc

Renfield
Admin CodeS-SourceS- MVP Visual Basic
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Salut, la source dont tu parlais ne serait-elle pas celle ci  : http://www.vbaccelerator.com/home/vb/Code/Techniques/A_Fast_Index-Based_Object_Collection/article.asp ??
Cà va peut être me sauver la vie en tout cas !
@+

Hex Editor VB
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
Salut,

peut-être en faisant une classe objet, en implémentant For Each aux objets :

Tuto de ShareVB

Et si tu veux un exemple simple d'utilisation, je l'utilise (bien que pas beaucoup d'objets) dans ma source pour le suivi des actions.
Indice : regarde le membre caché d'une collection dans l'explorateur d'objet : _NewEnum

@++

<hr size="2" width="100%" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~

( Nouveau forum : Exclusivement Office & VBA )
..................................................................
<hr size="2" width="100%" />
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Salut, merci pour la réponse rapide ;)

Mais en fait j'ai simplifié l'énoncé de mon problème... j'ai déjà une classe objet (contenant la collection) qui implémente For Each...

For Each est bien pour parcourir tous les objets, mais mon vrai problème c'est que je veux parcourir par exemple les 50 derniers objets de la collection et le temps est beaucoup plus élevé que pour les 50 premiers...

Concrêtement, dans l'espèce de ListView que je code, le scroll se met à ramer à mort quand on passe vers les Items situé à la fin de la liste, à cause du temps d'accès à la collection.

Merci, @+







Hex Editor VB
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
J'ai du mal à comprendre, comment tu fais ici :

   Set o = New Collection
   Debug.Print "adding..."
   For x = 1 To 30000
       o.Add k     ' là tu ajoutes k, alors qu'il n'est instancié dans l'autre boucle
   Next x
   Debug.Print "retrieving..."

   For x = 1 To 30000
       'For y = 1 To 1000
           Set k = o.Item(x)
       'Next y
   Next x
   Debug.Print "done"

@++

<hr size ="2" width="100%" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~

( Nouveau forum : Exclusivement Office & VBA )
..................................................................
<hr size="2" width="100%" />
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Merci pour l'info sur la lenteur de la collection.

Pour l'éclatement de la collection, sûr que c'est une solution, mais çà me semble difficile à mettre en oeuvre. Sachant que je code une sorte de ListView, avec l'objet vkListItem et l'objet collection vkListItems. C'est pour çà que je vois pas trop comment je pourrais subdiviser la ListItems en plusieurs collections ?

Mortalino ==> pas besoin d'instancier, c'est à Nothing par défaut. Alors j'affecte un objet vide, mais peu importe, c'est la récupération qui m'intéresse dans cet exemple.
Note :
Private Sub Command1_Click()
Dim obj As Object
   MsgBox (obj Is Nothing)
End Sub , ----
By Renfield
@+

Hex Editor VB
Messages postés
17288
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
27 septembre 2021
71
Tu pourrais utiliser un simple tableau pour stocker tes objets...


en désactivant les controles sur les tableaux (options de compilation) ca devrait le faire...


la chose étant que le .Item des collection est lent... il doit regarder ce que tu transmet (clé ou index) et faire la recherche en interne... j'ignore la structure de la chose, reste que c'est connu comme étant lent.

Renfield
Admin CodeS-SourceS- MVP Visual Basic
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Salut Renfield !

En fait j'utilise déjà des tableaux (notamment pour les propriétés Checked et Selected de mon objet), mais le problème est l'insertion d'un Item avec un index différent du nombre total d'items (en gros, si je veux pouvoir ajouter un item au millieu, je dois reclasser tout le tableau). Avec un collection (donc sûrement une liste chaînée), il n'y avait pas le problème.
Je vais voir ce soir, merci pour l'info en tout cas.

@+

Hex Editor VB
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Re, en fait j'ai eu une idée mais je ne sais pas si c'est réalisable : serait-il possible de pouvoir déplacer les Items d'un tableau sans passer par des boucles For, mais plutôt par l'instruction CopyMemory ? (on décale des bytes en mémoire et on peut après insérer le nouvel Item au milieu).
@+
Hex Editor VB
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Salut tout le monde, j'ai presque réussi à trouver une parade : je passe par une liste et un copymemory pour pouvoir éviter de faire des For pour le décalage (quand on ajoute un Item au milieu de la liste).

Seul problème, je n'arrive pas à trouver une erreur dans mon code :(
Elle se situe dans la sub RemoveItem, mais j'ai beau avoir cherché pendant 1h, j'ai pas trouvé...

Est-ce que quelqu'un manie avec facilité les CopyMemory et pourrait m'aider à fixer ce léger bug ? (pour voir le bug, ajouter des items à index=2, puis enlever des items à index=2, un "décalage" apparait)

Merci d'avance, @+

Petit code qui plante : http://www.badongo.com/file/3177771

Hex Editor VB
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Salut, j'ai réussi à régler le problème et j'en ai fait une classe que je viens de poster :  http://www.vbfrance.com/code.aspx?ID=42861.

La lecture est ULTRA rapide ;)
@+ et merci pour votre aide

Hex Editor VB