Как освободить память? - PullRequest
       7

Как освободить память?

0 голосов
/ 04 ноября 2010

У меня есть следующий метод для циклического перебора таблицы, изменения некоторых значений в каждой строке и сохранения изменений в базе данных.Чтобы ускорить процесс, я собираю данные в наборах по 10 000 строк.Это большая таблица с более чем 25 миллионами записей.

Проблема в том, что мое приложение не освобождает память.Я попытался переопределить переменную records на nothing или явно вызвать сборщик мусора, но память остается там.Запустив встроенный профилировщик VS10, я вижу, что виновником является метод system.linq.enumerable.tolist(), который занимает более 98% моей памяти.Как освободить эту память после вызова saveChanges?

db = New databaseEntities
Dim size = 25000000
Dim stepSize = 10000
For i = 0 to size Step stepSize
  Dim sql = (From A In db.table).OrderBy(Function(A) A.Column).Skip(i).Take(stepSize)
  Dim records As New List(Of table)
  records = sql.ToList
  For Each record In records
    'do some work
  Next
  db.SaveChanges()
  records = Nothing
  GC.Collect()
Next

Ответы [ 4 ]

0 голосов
/ 04 ноября 2010

Если вам не нужно обновлять сущности, используйте MergeOption.NoTracking.Контекст больше не будет хранить ссылку на сущность и не будет исправлять ошибки.

0 голосов
/ 04 ноября 2010

Я ни в коем случае не эксперт по Linq to SQL, но я предполагаю, что DataContext кэширует все прочитанные вами строки, поэтому вы должны либо очистить кеш, либо потерять ссылку на DataContext.

0 голосов
/ 04 ноября 2010

Репозиторий содержит ссылку на каждую сущность, которую он отслеживает, поэтому вы не сможете располагать сущность, пока репозиторий находится в рабочем состоянии и отслеживает ее. Это означает, что вам нужно либо удалить хранилище, либо отсоединить каждую сущность после того, как вы закончили ее обработку.

Вариант 1) если «выполнить какую-то работу» не влияет на порядок, в котором вы возвращаете записи, вы можете переместить создание databaseEntities в цикл For и объявить его с помощью блока using. Это должно привести к тому, что каждый блок сущностей будет освобождаться каждый раз вокруг цикла for

Вариант 2) Если ваша операция по существу параллельна, и то, что вы делаете с одним «табличным» объектом, не имеет никаких зависимостей от других, то вы можете вызвать databaseEntities.Detach (record) после db.SaveChanges, что включите сборщик мусора, чтобы освободить пространство объекта.

Глядя на ваш код, я подозреваю, что можно использовать любой из этих

0 голосов
/ 04 ноября 2010

может быть, вы можете попробовать это: (я не проверял)

db.SaveChanges()
For Each record In records
    record.dispose ''only if class table got a dispose method
Next
records.clear
records = Nothing
...