Face à de très grands ensembles de données & juste à temps de chargement
J'ai un .NET application écrite en C# (.NET 4.0). Dans cette application, nous avons à lire un grand jeu de données à partir d'un fichier et d'afficher le contenu dans une structure en grille. Donc, pour ce faire, j'ai placé un DataGridView sur la forme. Il dispose de 3 colonnes, toutes les données de la colonne vient du fichier. D'abord, le fichier avait environ 600 000 enregistrements, correspondant à 600.000 lignes dans le DataGridView.
J'ai rapidement découvert que, DataGridView s'effondre avec une telle un grand ensemble de données, j'ai donc dû basculer en Mode Virtuel. Pour ce faire, j'ai d'abord lu le fichier complètement en 3 différents tableaux (correspondant à 3 colonnes), puis le CellValueNeeded événement se déclenche, je fournis les valeurs correctes dans les tableaux.
Cependant, il peut y avoir une énorme (ÉNORME!) nombre d'enregistrements de ce fichier, comme nous l'avons rapidement découvert. Lorsque la taille est très grande, la lecture de toutes les données dans un tableau ou une Liste<>, etc, semble ne pas être faisable. Nous exécuter rapidement dans l'allocation de la mémoire des erreurs. (De mémoire exception).
Nous nous sommes plantés là, mais alors réalisé, pourquoi lire toutes les données en tableaux premier, pourquoi ne pas lire le fichier sur demande CellValueNeeded événement se déclenche? Donc, c'est ce que nous faisons maintenant: Nous ouvrir le fichier, mais ne pas lire quoi que ce soit, et que CellValueNeeded événements feu, nous avons d'abord Chercher() à la position correcte dans le fichier, et ensuite de lire les données correspondantes.
C'est le mieux que nous pouvions venir avec, mais, tout d'abord, c'est assez lent, ce qui rend l'application lente et pas convivial. Deuxièmement, nous ne pouvons pas aider mais pense qu'il doit y avoir une meilleure façon de l'accomplir. Par exemple, certains binaire éditeurs (comme HXD) sont absolument rapide pour toute la taille du fichier, donc j'aimerais savoir comment cela peut être réalisé.
Oh, et pour ajouter à nos problèmes, en mode virtuel de la DataGridView, lorsque nous avons fixé le nombre de lignes pour le nombre de lignes dans le fichier (disons 16.000.000), il faut un certain temps pour le DataGridView à même de s'initialiser. Tous les commentaires de ce "problème" serait appréciée.
Grâce
OriginalL'auteur SomethingBetter | 2011-01-26
Vous devez vous connecter pour publier un commentaire.
Si vous ne pouvez pas répondre à l'ensemble de votre jeu de données en mémoire, alors vous avez besoin d'un schéma de mise en mémoire tampon. Plutôt que de lire simplement la quantité de données nécessaires pour remplir le
DataGridView
en réponse àCellValueNeeded
, votre application doit anticiper les actions de l'utilisateur et de la lecture à l'avance. Ainsi, par exemple, lorsque le programme démarre pour la première fois, il faut lire les premiers 10 000 enregistrements (ou peut-être seulement 1 000 ou peut-être de 100 000--tout ce qui est raisonnable dans votre cas). Ensuite,CellValueNeeded
de demande peut être rempli immédiatement à partir de la mémoire.Que l'utilisateur se déplace à travers la grille, votre programme, autant que possible, reste une étape à l'avance de l'utilisateur. Il peut y avoir des pauses courtes si l'utilisateur passe devant vous (dire, veut passer à la fin de l'avant) et vous devez aller sur le disque afin de répondre à une demande.
Que la mémoire tampon est généralement mieux assurée par un thread séparé, bien que la synchronisation peut parfois être un problème si le fil est de la lecture à l'avance en prévision de l'utilisateur de l'action suivante, puis l'utilisateur fait quelque chose de complètement inattendu comme aller au début de la liste.
16 millions de dossiers n'est pas vraiment tout ce que nombre d'enregistrements à conserver dans la mémoire, à moins que les enregistrements sont de très grande taille. Ou si vous n'avez pas beaucoup de mémoire sur votre serveur. Certainement, 16 millions de dollars est nulle part près de la taille maximale d'un
List<T>
, à moins queT
est un type de valeur (de la structure). Combien de gigaoctets de données parlez-vous ici?J'ai essayé d'utiliser .NET MemoryMappedFile, mais dès que vous créez une vue, apparemment, il essaie de charger le fichier en mémoire, parce que je suis sorti de la mémoire des exceptions. J'ai pensé que peut-être MemoryMappedFile serait en interne segment de données accède à des pages et uniquement de charger des pages de mémoire.
Je suppose que 512 MO est un problème si vous êtes sur une machine 32 bits. Si vous utilisez un fichier mappé en mémoire, vous aurez envie de faire votre point de vue dans le fichier plus petit que l'ensemble de la taille du fichier. Ensuite, vous réglez votre point de vue comme les pages utilisateur à travers les données.
OriginalL'auteur Jim Mischel
Eh bien, voici une solution qui semble fonctionner beaucoup mieux:
Étape 0: Jeu de dataGridView.Nombre de lignes à une faible valeur, par exemple, à 25 (ou le nombre réel qui s'adapte à votre forme/écran)
Étape 1: Désactiver la barre de défilement de la dataGridView.
Étape 2: Ajouter votre propre barre de défilement.
Étape 3: Dans votre CellValueNeeded routine, de répondre à des e.RowIndex+barre de défilement.Valeur
Étape 4: Comme pour la banque de données, je suis actuellement ouvrir un Flux, et dans le CellValueNeeded de routine, d'abord faire un Seek() et Read() les données requises.
Avec ces étapes, je suis très raisonnable de la performance de défilement grâce à la grille de données pour les très gros fichiers (testé jusqu'à 0,8 GO).
Donc, en conclusion, il apparaît que la cause réelle de ce ralentissement n'était pas le fait que nous avons gardé Seek()ing et Read()ing, mais le dataGridView.
OriginalL'auteur SomethingBetter
La gestion des lignes et des colonnes qui peuvent être roulés, sous-totalisé utilisées pour les calculs de colonne, etc présente un ensemble unique de défis; pas vraiment juste de comparer le problème à ceux d'un éditeur rencontrerait. Tiers datagrid contrôles ont été aborder le problème de l'affichage et de manipuler de gros jeux de données côté client depuis VB6 jours. Ce n'est pas une tâche facile pour obtenir vraiment accrocheur performance en utilisant soit la charge sur demande ou à l'auto-contenue côté client garguantuan ensembles de données. Charge sur demande, peuvent souffrir de latence côté serveur; la manipulation de l'ensemble du jeu de données sur le client peuvent souffrir de mémoire et les limites du PROCESSEUR. Certains tiers contrôles à l'appui de juste-à-temps de chargement d'approvisionnement à la fois côté client et côté serveur logique, tandis que les autres tentent de résoudre le problème à 100% côté client.
OriginalL'auteur Tim
Parce que .net est posé sur le dessus du système d'exploitation natif, chargement à l'exécution et à la gestion des données du disque vers la mémoire a besoin d'une autre approche.
Voir pourquoi et comment: http://www.codeproject.com/Articles/38069/Memory-Management-in-NET
OriginalL'auteur Zarmac
Pour traiter de cette question, je vous suggère de ne pas charger toutes les données à la fois. Au lieu de charger les données en morceaux et afficher les données les plus pertinentes en cas de besoin. J'ai juste fait un test rapide et a constaté que l'établissement d'un
DataSource
propriété d'unDataGridView
est une bonne approche, mais avec un grand nombre de lignes, il faut aussi du temps. Donc, utiliserMerge
fonction de la DataTable pour charger les données en morceaux et de montrer à l'utilisateur les données les plus pertinentes. Ici , j'ai montré un exemple qui peut vous aider.OriginalL'auteur NeverHopeless