8
votes

Fonction expirée pour une grande liste (requête LINQ en C #)

J'utilise la requête suivante xxx

tandis que myfilecompare est une comparaison de 2 fichiers basés sur le nom et la longueur.

Le La requête renvoyait les résultats si la liste1 et la liste2 étaient petites (disons 100 fichiers pendant que j'ai testé), j'ai augmenté la liste1 à 30 000 fichiers et lister2 à 20 000 fichiers et la requête indique maintenant "Evaluation de la fonction chronométrée" .

J'ai cherché en ligne et que l'a trouvé le débogage pourrait le causer, donc j'ai supprimé tous les points d'arrêt et dirigé le code, maintenant le programme juste geze, sans aucune sortie pour QueryList1only i J'essaie d'imprimer pour le vérifier.

Edit: Ceci est le code de myfilecompare xxx


5 commentaires

Postez le code pour myfilecompare


Quoi qu'il en soit, de telles opérations lourdes doivent être exécutées simultanément dans un fil séparé pour éviter les situations que vous venez de faire face.


Cela fonctionne bien pour 3000 fichiers et le code ci-dessus (testé juste maintenant)


@Tall: J'essaie de travailler sur les problèmes de mémoire (si tel est le cas), en supprimant les objets FileInfo des listes, etc. Merci à tous tellement pour votre contribution et vos commentaires


@All: J'ai modifié le hashcode (partiellement pris de SLLEV) et la méthode Equals dans MyCompare. Je n'ai pas utilisé hashset (il n'a pas prouvé de résoudre mon problème). Je suis capable d'obtenir les résultats souhaités en moins de 5 minutes maintenant sur ma machine locale. Maintenant, lorsque je le pointe sur les dossiers sur le serveur, il gèle (cela fonctionne sur le serveur avec 1000 fichiers, j'ai testé). Au moins certains progrès :) Merci à tous


3 Réponses :


3
votes

Quelles sont vous avez besoin de faire avec les articles retournés par une requête? Essentiellement, de telles opérations lourdes seraient excellentes d'exécuter simultanément dans un fil séparé pour éviter les situations que vous venez de faire face.

EDIT: une idée fore> p>

comme cas que vous pouvez essayez de suivre l'algorithme: p>

  • Trier les éléments dans les deux tableaux à l'aide de QuickSort code> ( Liste .sort () code> Utilise par défaut ), il sera assez rapide avec une bonne implémentation de gethascode () code> li>
  • puis dans le bien connu pour () code> liste de traverser la boucle et comparer des éléments avec le même index li>
  • Lorsque le nombre de tout tableau atteint un indice maximal d'une autre liste - Sélectionnez tous les éléments de cette dernière liste comme différent (fondamentalement, ils n'existent pas du tout). LI> ul>

    Je crois avec des tableaux triés, vous donnerez beaucoup de meilleures performances. Je crois que la complexité de sauf () forte> est o (m * n) forte>. P>

    edit: une autre idée doit être vraiment rapide p>

    • d'un magasin de magasin de serveur dans définir code> li>
    • puis boucle via la deuxième matrice et recherchez dans un ensemble Set code>, ce serait très rapide! Fondamentalement o (mlogm) + o (n) strong> car vous devez traverser uniquement une seule matrice et recherchez dans un ensemble avec une bonne fonction de hachage (Utiliser gethascode () code> j'ai fourni avec une logique mise à jour) est très rapide. Essayez-le! LI> ul> xxx pré>

      EDIT: Plus de détails sur la logique d'égalité ont été fournis dans Commentaires strong> P>

      Essayez cette impression p>

      public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
      {
            if ( f1 == null || f2 == null)
            {
                return false;
            }
      
            return (f1.Name == f2.Name && f1.Directory.Name == f2.Directory.Name && 
                   f1.Length == f2.Length);
      }
      
      public int GetHashCode(System.IO.FileInfo fi)
      {
          unchecked
          {
              int hash = 17;    
              hash = hash * 23 + fi.Name.GetHashCode();
              hash = hash * 23 + fi.Directory.Name.GetHashCode();
              hash = hash * 23 + fi.Length.GetHashCode();
      
              return hash;
          }
      }
      


14 commentaires

J'essaie de comparer des fichiers à partir de 2 serveurs pris dans 2 listes. Tout le programme concerne cela. Aucun autre code n'existe dans ce programme autre que de comparer les 2 listes


Devrait être une liste d'éléments différents être affichés à un utilisateur? Et quelle version de .NET utilisez-vous?


Les fichiers différents de 2 listes doivent être enregistrés sur un fichier texte


Mais le nom complet utilise le chemin complet du fichier. et pour les fichiers sur 2 serveurs différents, vous ne pouvez pas comparer en fonction du nom complet.


@superstar: Yep Dans ce cas, vous avez raison, de sorte que les critères d'égalité s'appellent fondamentalement. Taille, Dernière modification, etc. n'a pas d'importance?


Le nom et le répertoire étaient suffisants pour distinguer les fichiers. Je n'ai pas trouvé de cas, où ils ne fonctionnaient pas bien. Donc, je vais bien avec ça


BTW, comment vous créez une instance d'objets FileInfo? Est-il possible que FI1 et F2 référent le même objet? Dans ce cas, vous pouvez étendre des égaux () par f1.reefereferequentaux (F2)


J'ai une liste d'objets FileInfo, alors j'essaie de le modifier à une liste normale avec peu de valeurs, car cela pourrait entraîner une question de performance pour les charger.


J'essaie de me débarrasser des objets FileInfo pour vérifier si le problème de la mémoire est un problème.


Sauf () fonctionne déjà dans la manière dont vous suggérez. Le problème est le code de hachage OPS, qui ne prend pas en compte le nom du répertoire. S'il utilise sauf () avec vos méthodes d'égalité dans son filecomparer, il devrait améliorer les performances


Je ne suis pas sûr de la question de la performance avec HashCode, mais le code fonctionne assez bien pour distinguer le même nom de fichier de différents dossiers également (tout cas donné)


@Supperstar: essentiellement si vous appliquez l'un des algorithmes proposés, votre fonction s'exécutera beaucoup plus rapidement, j'espère que vous vous débarrasserez du problème mentionné.


@sllev: vos suggestions m'ont aidé dans la bonne direction. Merci beaucoup pour votre temps et vos efforts pour modifier la réponse, avec mes exigences changeantes. Bonne chance :)


@superstar: Vous êtes les bienvenus! À votre santé!



-1
votes

Je recommande de supprimer la longueur du code de hachage et de faire FI.FullName. Cela tient toujours la directive de l'unicité, bien que cela puisse (dans certains cas, où vous pensez que la longueur est nécessaire pour distinguer) être des collisions de hachage. Mais cela est probablement préférable à une exécution plus longue "sauf". De même, changez votre comparaison sur l'égalité d'être nom et annuaire, à la notification complète, qui serait probablement plus performante.


4 commentaires

Comme op déjà l'a dit dans des commentaires (voir les commentaires de mes réponses) Les fichiers proviennent de différents serveurs, les chemins supplémentaires sont différents.


Je crois que les collisions de hachage pourraient se produire dans des articles de stockage dans une sorte de Habilla, dans ce cas, nous avons deux listes simples


@SLLEV Oui, je suis conscient que les collisions de hachage pourraient se produire et même indiquées, mais c'est mieux si la génération de code de hachage cause-t-elle des problèmes de performance? Parfois, les choses ont le même code de hachage, c'est bon, la partie importante est que les éléments qui sont égaux ont le même code de hachage.


J'ai noté à propos de la collision car OP n'utilise aucune haquetable pour stocker des articles, il utilise des listes. Et les collisions pourraient se produire lorsque vous stockez l'élément de HASHTABLE / SET / MAP. Je crois que c'est la raison pour laquelle quelqu'un a révélé votre question, mais je ne suis vraiment pas sûr de savoir pourquoi juste hypothèse, de toute façon en termes de changements récents et d'idées avec des ensembles de jeux, votre réponse a du sens afin de pouvoir revenir au vote.



1
votes

Je n'ai pas essayé cela moi-même, mais voici une idée: Implémentez list1 comme cassette, de cette façon: xxx

Ajouter tous les fichiers: xxx

puis retirer les éléments: < / p> xxx

puis énumérer: xxx

Je pense que c'est plus rapide, mais comme je l'ai dit, je n'ai pas essayé. Voici un lien avec des informations générales sur HashSet.

modifier : Ou mieux encore, vous pouvez initialiser et ajouter des données en une étape: xxx


2 commentaires

En fait, en utilisant un hashset, réduit le temps pris sur ma machine locale. Mais l'application se gèle toujours lorsque je pointe les dossiers sur le serveur.


Oh je vois. Heureux qu'il a finalement travaillé avec une autre solution tu =)