2010-07-01 6 views
1

J'ai une question sur la façon dont la récupération de place peut être traitée dans une requête linq. Supposons qu'on me donne une liste de demandes à traiter. Chaque requête génère un très grand ensemble de données, mais un filtre est appliqué pour conserver uniquement les données critiques de chaque chargement demandé. Donc, je sais que la requête est différée pour chaque élément de données jusqu'à ce que chaque élément de données filtré soit demandé, donc c'est bon. Mais cette partie intense de la mémoire moyenne persiste-t-elle jusqu'à ce que l'énumérable soit terminé? Ce que j'espère, c'est que chaque élément de données peut être récupéré dès qu'il passe l'étape filtrée, s'assurant ainsi que j'ai assez de mémoire pour traiter toute la liste. Est-ce le cas, ou est-ce que le milieu énumérable garde tout autour jusqu'à la fin de la requête entière? Si oui, y a-t-il un moyen de faire face à cela?Garbage Collection dans une requête linq


Note: la fonction Process() génère les données à forte intensité de mémoire ... thats ce que je suis inquiet pour

Répondre

3

Tant que la valeur de retour de Process(...) et Filter(...) ne détiennent aucune référence à la "éléments de données volumineux" utilisés en interne, la mémoire utilisée dans ce processus doit devenir non racinée et candidate à la GC après chaque élément.

Cela ne signifie pas qu'il sera recueilli, mais seulement qu'il sera candidat. Si la pression de la mémoire devient élevée, le GC la recueillera probablement.

+0

cool. mon souci était le intermédiaire énumérable de la première sélection tiendrait les données jusqu'à ce qu'il soit complété – tbischel

+0

@tbischel: Non - LINQ ne contiendra pas de références, autres que celles que vous ajoutez à une collection, etc. Tant qu'il n'y a pas de refs, il peut être GCed. –

0

Il est difficile de répondre à votre question, ce que vous avez posté compilera pas réellement (Select produit un IEnumerable<T>, mais vous l'assigner à un List<T>. En supposant que la fonction Filter(data) retourne un filteredData, vous auriez pour appeler ToList() sur la requête pour le stocker dans results).

requests est, je suppose, déjà rempli de données. Cette liste suivra les règles normales de collecte de place. Je suppose que ce qui vous inquiète est le résultat de la fonction Process. Je ne peux pas dire exactement ce qui va se passer, parce que je ne sais pas non plus ce que fait votre fonction . À moins que le résultat de la fonction Filter ne contienne une référence à son paramètre (en d'autres termes, le résultat de la fonction Process), les objets créés par Process seront complètement hors de portée à la fin de la requête et suivront la normale règles de collecte des ordures. Gardez à l'esprit que ces règles régissent admissibilité pour la collecte. Aucun objet n'est jamais garanti pour être collecté pendant la durée de votre application. Les résultats, cependant, seront éligibles, ainsi le GC sera capable de les collecter.

+0

fixe que ... ne copiait pas à partir d'un fichier, alors oui c'était un surdimensionné – tbischel

3

Le garbage collector est assez agressif dans .NET et peut nettoyer les objets intermédiaires lorsqu'ils ne sont plus référencés, même à l'intérieur des boucles. En fait, dans certains cas, il va nettoyer un objet qui est toujours référencé s'il peut voir qu'il ne sera jamais accessible à nouveau.

L'exécution de ce code montre que les objets sont nettoyés assez rapidement et ne pendent pas jusqu'à ce que la requête complète (ce qui ne fait jamais):

public class MyClass1 { ~MyClass1() { Console.WriteLine("Cleaned up MyClass1"); } } 
public class MyClass2 { ~MyClass2() { Console.WriteLine("Cleaned up MyClass2"); } } 

public class Program 
{ 
    static IEnumerable<MyClass1> lotsOfObjects() 
    { 
     while (true) 
      yield return new MyClass1(); 
    } 

    static void Main() 
    { 
     var query = lotsOfObjects().Select(x => foo(x)); 
     foreach (MyClass2 x in query) 
      query.ToString(); 
    } 

    static MyClass2 foo(MyClass1 x) 
    { 
     return new MyClass2(); 
    } 
} 

Résultat:

 
Cleaned up MyClass1 
Cleaned up MyClass1 
Cleaned up MyClass1 
Cleaned up MyClass2 
Cleaned up MyClass2 
Cleaned up MyClass1 
Cleaned up MyClass2 
etc...